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 "PICStudyBase.h" 18 : #include "ParticleStepperBase.h" 19 : #include "libmesh/int_range.h" 20 : 21 : InputParameters 22 1309 : PICStudyBase::validParams() 23 : { 24 1309 : auto params = RayTracingStudy::validParams(); 25 1309 : params.addClassDescription("Base class for PIC studies. Provides some of the basic ray data " 26 : "needed for particle tracking." 27 : "Basic logic for resetting rays to be used as particles after the " 28 : "original generation is complete is also provided"); 29 2618 : params.addRequiredParam<UserObjectName>( 30 : "stepper", 31 : "The ParticleStepper UserObject that has the rules for how particle" 32 : "velocities should be updated"); 33 : // We're not going to use registration because we don't care to name our rays because 34 : // we will have a lot of them 35 1309 : params.set<bool>("_use_ray_registration") = false; 36 : 37 1309 : return params; 38 0 : } 39 : 40 650 : PICStudyBase::PICStudyBase(const InputParameters & parameters) 41 : : RayTracingStudy(parameters), 42 650 : _banked_rays( 43 1300 : declareRestartableDataWithContext<std::vector<std::shared_ptr<Ray>>>("_banked_rays", this)), 44 650 : _v_x_index(registerRayData("v_x")), 45 650 : _v_y_index(registerRayData("v_y")), 46 650 : _v_z_index(registerRayData("v_z")), 47 650 : _weight_index(registerRayData("weight")), 48 650 : _charge_index(registerRayData("charge")), 49 650 : _mass_index(registerRayData("mass")), 50 650 : _species_index(registerRayData("species")), 51 650 : _stepper(getUserObject<ParticleStepperBase>("stepper")), 52 1950 : _has_generated(declareRestartableData<bool>("has_generated", false)) 53 : { 54 650 : } 55 : 56 : void 57 1624 : PICStudyBase::generateRays() 58 : { 59 : // We generate rays the first time only, after that we will 60 : // pull from the bank and update velocities/max distances 61 1624 : if (!_has_generated) 62 : { 63 434 : this->initializeParticles(); 64 432 : _has_generated = true; 65 : } 66 : else 67 : { 68 1190 : reinitializeParticles(); 69 : // Add the rays to be traced 70 1190 : moveRaysToBuffer(_banked_rays); 71 1190 : _banked_rays.clear(); 72 : } 73 1622 : } 74 : 75 : void 76 1190 : PICStudyBase::reinitializeParticles() 77 : { 78 : // Reset each ray 79 7614 : for (auto & ray : _banked_rays) 80 : { 81 : // Store off the ray's info before we reset it 82 : const auto elem = ray->currentElem(); 83 6424 : const auto point = ray->currentPoint(); 84 : const auto distance = ray->distance(); 85 : 86 6424 : getVelocity(*ray, _temporary_velocity); 87 : // Reset it (this is required to reuse a ray) 88 6424 : ray->resetCounters(); 89 6424 : ray->clearStartingInfo(); 90 : 91 : // And set the new starting information 92 6424 : ray->setStart(point, elem); 93 6424 : _stepper.setupStep( 94 6424 : *ray, _temporary_velocity, ray->data()[_charge_index] / ray->data()[_mass_index], distance); 95 : 96 6424 : setVelocity(*ray, _temporary_velocity); 97 : } 98 1190 : } 99 : 100 : void 101 1622 : PICStudyBase::postExecuteStudy() 102 : { 103 : // we are going to be re using the same rays which just took a step so 104 : // we store them here to reset them in the generateRays method 105 1622 : _banked_rays = rayBank(); 106 : // removing all of the rays which were killed during their tracing 107 1622 : _banked_rays.erase(std::remove_if(_banked_rays.begin(), 108 : _banked_rays.end(), 109 : [](const std::shared_ptr<Ray> & ray) 110 : { 111 23512 : if (ray->stationary()) 112 : return false; 113 : 114 7312 : return std::abs(ray->distance() - ray->maxDistance()) / 115 : ray->maxDistance() > 116 7312 : 1e-6; 117 : }), 118 : _banked_rays.end()); 119 1622 : } 120 : 121 : void 122 71254 : PICStudyBase::getVelocity(const Ray & ray, Point & v) const 123 : { 124 71254 : v(0) = ray.data(_v_x_index); 125 71254 : v(1) = ray.data(_v_y_index); 126 71254 : v(2) = ray.data(_v_z_index); 127 71254 : } 128 : 129 : void 130 71254 : PICStudyBase::setVelocity(Ray & ray, const Point & v) const 131 : { 132 71254 : ray.data(_v_x_index) = v(0); 133 71254 : ray.data(_v_y_index) = v(1); 134 71254 : ray.data(_v_z_index) = v(2); 135 71254 : } 136 : 137 : const std::vector<std::shared_ptr<Ray>> & 138 1374 : PICStudyBase::getBankedRays() const 139 : { 140 1374 : return _banked_rays; 141 : } 142 : 143 : void 144 65070 : PICStudyBase::setInitialParticleData(std::shared_ptr<Ray> & ray, const InitialParticleData & data) 145 : { 146 65070 : ray->setStart(data.position, data.elem); 147 65070 : ray->data(_v_x_index) = data.velocity(0); 148 65070 : ray->data(_v_y_index) = data.velocity(1); 149 65070 : ray->data(_v_z_index) = data.velocity(2); 150 65070 : ray->data(_mass_index) = data.mass; 151 65070 : ray->data(_weight_index) = data.weight; 152 65070 : ray->data(_charge_index) = data.charge; 153 65070 : } 154 : 155 : const std::vector<RayDataIndex> 156 165 : PICStudyBase::getVelocityIndicies(const bool all_components) const 157 : { 158 165 : const unsigned int vel_dim = all_components ? 3 : _mesh.dimension(); 159 : 160 165 : std::vector<RayDataIndex> indicies(vel_dim); 161 579 : for (const auto dim : make_range(vel_dim)) 162 1353 : indicies[dim] = getRayDataIndex(std::string("v_") + (dim == 0 ? "x" : (dim == 1 ? "y" : "z"))); 163 : 164 165 : return indicies; 165 : }