Line data Source code
1 : //* This file is part of SALAMANDER: Software for Advanced Large-scale Analysis of MAgnetic 2 : //* confinement for Numerical Design, Engineering & Research, 3 : //* A multiphysics application for modeling plasma facing components 4 : //* https://github.com/idaholab/salamander 5 : //* https://mooseframework.inl.gov/salamander 6 : //* 7 : //* SALAMANDER is powered by the MOOSE Framework 8 : //* https://www.mooseframework.inl.gov 9 : //* 10 : //* Licensed under LGPL 2.1, please see LICENSE for details 11 : //* https://www.gnu.org/licenses/lgpl-2.1.html 12 : //* 13 : //* Copyright 2025, Battelle Energy Alliance, LLC 14 : //* ALL RIGHTS RESERVED 15 : //* 16 : 17 : #include "PerElementParticleInitializer.h" 18 : #include "MooseRandom.h" 19 : #include "ElementSampler.h" 20 : #include "VelocityInitializerBase.h" 21 : 22 : registerMooseObject("SalamanderApp", PerElementParticleInitializer); 23 : 24 : InputParameters 25 552 : PerElementParticleInitializer::validParams() 26 : { 27 552 : auto params = ParticleInitializerBase::validParams(); 28 552 : params.addClassDescription( 29 : "Particle initializer that uniformly distributes a specified number of particles per " 30 : "element and calculates the corresponding particle weight based on the requested number " 31 : "density, particles per element, and the elements \"volume\"."); 32 1104 : params.addRangeCheckedParam<unsigned int>( 33 : "particles_per_element", 34 : "particles_per_element != 0", 35 : "The number of computational particles that should be placed in each element"); 36 : 37 1104 : params.addRangeCheckedParam<Real>("number_density", 38 : "number_density > 0.0", 39 : "The number density of particles you want to represent"); 40 552 : return params; 41 0 : } 42 : 43 275 : PerElementParticleInitializer::PerElementParticleInitializer(const InputParameters & parameters) 44 : : ParticleInitializerBase(parameters), 45 275 : _number_density(getParam<Real>("number_density")), 46 825 : _particles_per_element(getParam<unsigned int>("particles_per_element")) 47 : { 48 275 : } 49 : 50 : std::vector<InitialParticleData> 51 91 : PerElementParticleInitializer::getParticleData() const 52 : { 53 : 54 : // counting the number of elements this process is responsible for 55 : // this will allow us to allocated data structures of the appropriate length 56 91 : const auto & elem_range = *_fe_problem.mesh().getActiveLocalElementRange(); 57 : const auto num_local_elements = std::distance(elem_range.begin(), elem_range.end()); 58 : // if there are no elements for this processor: do nothing 59 91 : if (num_local_elements == 0) 60 0 : return {}; 61 : 62 : std::vector<InitialParticleData> data = 63 91 : std::vector<InitialParticleData>(num_local_elements * _particles_per_element); 64 : 65 : // random number generator to be used for sampling the elements 66 : MooseRandom generator; 67 91 : SALAMANDER::ElementSampler sampler = SALAMANDER::ElementSampler(_fe_problem, _seed, generator); 68 : // This will store the uniformly distributed points within the reference elements 69 : uint elem_count = 0; 70 4203 : for (const auto elem : *_fe_problem.mesh().getActiveLocalElementRange()) 71 : { 72 : 73 : // now that all of the particle locations have been placed we need to 74 : // set up the data they will need to be made into actual rays 75 4113 : const auto & physical_points = sampler.sampleElement(elem, _particles_per_element); 76 4112 : const auto & velocities = _velocity_initializer.getParticleVelocities(_particles_per_element); 77 4112 : Real weight = _number_density * elem->volume() / (_particles_per_element); 78 45232 : for (const auto i : make_range(_particles_per_element)) 79 : { 80 41120 : uint particle_index = elem_count * _particles_per_element + i; 81 41120 : data[particle_index].elem = elem; 82 41120 : data[particle_index].weight = weight; 83 41120 : data[particle_index].species = _species; 84 41120 : data[particle_index].mass = _mass; 85 41120 : data[particle_index].charge = _charge; 86 41120 : data[particle_index].position = physical_points[i]; 87 41120 : data[particle_index].velocity = velocities[i]; 88 : } 89 4112 : elem_count++; 90 : } 91 : return data; 92 180 : }