Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #include "DiscreteNucleationFromFile.h" 11 : #include "MooseMesh.h" 12 : #include "SystemBase.h" 13 : 14 : #include <algorithm> 15 : 16 : registerMooseObject("PhaseFieldApp", DiscreteNucleationFromFile); 17 : 18 : InputParameters 19 57 : DiscreteNucleationFromFile::validParams() 20 : { 21 57 : InputParameters params = DiscreteNucleationInserterBase::validParams(); 22 57 : params.addClassDescription( 23 : "Manages the list of currently active nucleation sites and adds new " 24 : "sites according to a predetermined list from a CSV file (use this with sync_times)."); 25 114 : params.addRequiredParam<FileName>( 26 : "file", 27 : "CSV file with (time, x, y, z) coordinates for nucleation events and optionally radius."); 28 114 : params.addRequiredParam<Real>("hold_time", "Time to keep each nucleus active"); 29 114 : params.addParam<Real>("tolerance", 1e-9, "Tolerance for determining insertion time"); 30 114 : params.addRangeCheckedParam<Real>("radius", "radius > 0.0", "fixed radius (if using)"); 31 : 32 57 : return params; 33 0 : } 34 : 35 30 : DiscreteNucleationFromFile::DiscreteNucleationFromFile(const InputParameters & parameters) 36 : : DiscreteNucleationInserterBase(parameters), 37 30 : _hold_time(getParam<Real>("hold_time")), 38 90 : _reader(getParam<FileName>("file")), 39 60 : _history_pointer(declareRestartableData<unsigned int>("history_pointer", 0)), 40 60 : _tol(getParam<Real>("tolerance")), 41 30 : _nucleation_rate(0.0), 42 60 : _fixed_radius(isParamValid("radius")), 43 78 : _radius(_fixed_radius ? getParam<Real>("radius") : 0) 44 : { 45 30 : _reader.read(); 46 : 47 30 : auto & names = _reader.getNames(); 48 30 : auto & data = _reader.getData(); 49 : 50 : const std::size_t rows = data[0].size(); 51 30 : _nucleation_history.resize(rows); 52 : 53 : bool found_time = false; 54 : bool found_x = false; 55 : bool found_y = false; 56 : bool found_z = false; 57 : bool found_r = false; 58 : 59 132 : for (std::size_t i = 0; i < names.size(); ++i) 60 : { 61 : // make sure all data columns have the same length 62 102 : if (data[i].size() != rows) 63 0 : paramError("file", "Mismatching column lengths in file"); 64 : 65 102 : if (names[i] == "time") 66 : { 67 108 : for (std::size_t j = 0; j < rows; ++j) 68 78 : _nucleation_history[j].time = data[i][j]; 69 : found_time = true; 70 : } 71 72 : else if (names[i] == "x") 72 : { 73 108 : for (std::size_t j = 0; j < rows; ++j) 74 78 : _nucleation_history[j].center(0) = data[i][j]; 75 : found_x = true; 76 : } 77 42 : else if (names[i] == "y") 78 : { 79 108 : for (std::size_t j = 0; j < rows; ++j) 80 78 : _nucleation_history[j].center(1) = data[i][j]; 81 : found_y = true; 82 : } 83 12 : else if (names[i] == "z") 84 : { 85 0 : for (std::size_t j = 0; j < rows; ++j) 86 0 : _nucleation_history[j].center(2) = data[i][j]; 87 : found_z = true; 88 : } 89 12 : else if (names[i] == "r") 90 : { 91 48 : for (std::size_t j = 0; j < rows; ++j) 92 36 : _nucleation_history[j].radius = data[i][j]; 93 : found_r = true; 94 : } 95 102 : if (_fixed_radius) 96 180 : for (std::size_t j = 0; j < rows; ++j) 97 126 : _nucleation_history[j].radius = _radius; 98 : } 99 : 100 : // check if all required columns were found 101 30 : if (!found_time) 102 0 : paramError("file", "Missing 'time' column in file"); 103 30 : if (!found_x) 104 0 : paramError("file", "Missing 'x' column in file"); 105 30 : if (!found_y && _mesh.dimension() >= 2) 106 0 : paramError("file", "Missing 'y' column in file"); 107 30 : if (!found_z && _mesh.dimension() >= 3) 108 0 : paramError("file", "Missing 'z' column in file"); 109 30 : if (!found_r && !_fixed_radius) 110 0 : paramError("file", "Missing 'r' column in file"); 111 : 112 : // sort the nucleation history primarily according to time 113 30 : std::sort(_nucleation_history.begin(), 114 : _nucleation_history.end(), 115 : [](NucleusLocation a, NucleusLocation b) { return a.time < b.time; }); 116 30 : } 117 : 118 : void 119 195 : DiscreteNucleationFromFile::initialize() 120 : { 121 : // clear insertion and deletion counter 122 : _changes_made = {0, 0}; 123 : 124 : // expire entries from the local nucleus list (if the current time step converged) 125 195 : if (_fe_problem.converged(_sys.number())) 126 : { 127 : unsigned int i = 0; 128 368 : while (i < _global_nucleus_list.size()) 129 : { 130 173 : if (_global_nucleus_list[i].time - _tol <= _fe_problem.time()) 131 : { 132 : // remove entry (by replacing with last element and shrinking size by one) 133 54 : _global_nucleus_list[i] = _global_nucleus_list.back(); 134 : _global_nucleus_list.pop_back(); 135 54 : _changes_made.second++; 136 : } 137 : else 138 119 : ++i; 139 : } 140 : } 141 : 142 : // check if it is time to insert from the nucleus history 143 255 : while (_history_pointer < _nucleation_history.size() && 144 133 : _nucleation_history[_history_pointer].time <= _fe_problem.time()) 145 : { 146 : NucleusLocation nucleus; 147 60 : nucleus.time = _nucleation_history[_history_pointer].time + _hold_time; 148 60 : nucleus.center = _nucleation_history[_history_pointer].center; 149 60 : nucleus.radius = _nucleation_history[_history_pointer].radius; 150 : 151 60 : _global_nucleus_list.push_back(nucleus); 152 : 153 60 : _changes_made.first++; 154 60 : _history_pointer++; 155 : } 156 195 : } 157 : 158 : void 159 173 : DiscreteNucleationFromFile::finalize() 160 : { 161 : // no communication necessary as all ranks have the full nucleus history from the 162 : // DelimitedFileReader 163 173 : _update_required = _changes_made.first > 0 || _changes_made.second > 0; 164 173 : }