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 41 : DiscreteNucleationFromFile::validParams() 20 : { 21 41 : InputParameters params = DiscreteNucleationInserterBase::validParams(); 22 41 : 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 82 : params.addRequiredParam<FileName>( 26 : "file", 27 : "CSV file with (time, x, y, z) coordinates for nucleation events and optionally radius."); 28 82 : params.addRequiredParam<Real>("hold_time", "Time to keep each nucleus active"); 29 82 : params.addParam<Real>("tolerance", 1e-9, "Tolerance for determining insertion time"); 30 82 : params.addRangeCheckedParam<Real>("radius", "radius > 0.0", "fixed radius (if using)"); 31 : 32 41 : return params; 33 0 : } 34 : 35 22 : DiscreteNucleationFromFile::DiscreteNucleationFromFile(const InputParameters & parameters) 36 : : DiscreteNucleationInserterBase(parameters), 37 22 : _hold_time(getParam<Real>("hold_time")), 38 66 : _reader(getParam<FileName>("file")), 39 44 : _history_pointer(declareRestartableData<unsigned int>("history_pointer", 0)), 40 44 : _tol(getParam<Real>("tolerance")), 41 22 : _nucleation_rate(0.0), 42 44 : _fixed_radius(isParamValid("radius")), 43 58 : _radius(_fixed_radius ? getParam<Real>("radius") : 0) 44 : { 45 22 : _reader.read(); 46 : 47 22 : auto & names = _reader.getNames(); 48 22 : auto & data = _reader.getData(); 49 : 50 : const std::size_t rows = data[0].size(); 51 22 : _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 96 : for (std::size_t i = 0; i < names.size(); ++i) 60 : { 61 : // make sure all data columns have the same length 62 74 : if (data[i].size() != rows) 63 0 : paramError("file", "Mismatching column lengths in file"); 64 : 65 74 : if (names[i] == "time") 66 : { 67 76 : for (std::size_t j = 0; j < rows; ++j) 68 54 : _nucleation_history[j].time = data[i][j]; 69 : found_time = true; 70 : } 71 52 : else if (names[i] == "x") 72 : { 73 76 : for (std::size_t j = 0; j < rows; ++j) 74 54 : _nucleation_history[j].center(0) = data[i][j]; 75 : found_x = true; 76 : } 77 30 : else if (names[i] == "y") 78 : { 79 76 : for (std::size_t j = 0; j < rows; ++j) 80 54 : _nucleation_history[j].center(1) = data[i][j]; 81 : found_y = true; 82 : } 83 8 : 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 8 : else if (names[i] == "r") 90 : { 91 32 : for (std::size_t j = 0; j < rows; ++j) 92 24 : _nucleation_history[j].radius = data[i][j]; 93 : found_r = true; 94 : } 95 74 : if (_fixed_radius) 96 132 : for (std::size_t j = 0; j < rows; ++j) 97 90 : _nucleation_history[j].radius = _radius; 98 : } 99 : 100 : // check if all required columns were found 101 22 : if (!found_time) 102 0 : paramError("file", "Missing 'time' column in file"); 103 22 : if (!found_x) 104 0 : paramError("file", "Missing 'x' column in file"); 105 22 : if (!found_y && _mesh.dimension() >= 2) 106 0 : paramError("file", "Missing 'y' column in file"); 107 22 : if (!found_z && _mesh.dimension() >= 3) 108 0 : paramError("file", "Missing 'z' column in file"); 109 22 : 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 22 : std::sort(_nucleation_history.begin(), 114 : _nucleation_history.end(), 115 : [](NucleusLocation a, NucleusLocation b) { return a.time < b.time; }); 116 22 : } 117 : 118 : void 119 155 : 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 155 : if (_fe_problem.converged(_sys.number())) 126 : { 127 : unsigned int i = 0; 128 292 : while (i < _global_nucleus_list.size()) 129 : { 130 137 : 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 42 : _global_nucleus_list[i] = _global_nucleus_list.back(); 134 : _global_nucleus_list.pop_back(); 135 42 : _changes_made.second++; 136 : } 137 : else 138 95 : ++i; 139 : } 140 : } 141 : 142 : // check if it is time to insert from the nucleus history 143 203 : while (_history_pointer < _nucleation_history.size() && 144 105 : _nucleation_history[_history_pointer].time <= _fe_problem.time()) 145 : { 146 : NucleusLocation nucleus; 147 48 : nucleus.time = _nucleation_history[_history_pointer].time + _hold_time; 148 48 : nucleus.center = _nucleation_history[_history_pointer].center; 149 48 : nucleus.radius = _nucleation_history[_history_pointer].radius; 150 : 151 48 : _global_nucleus_list.push_back(nucleus); 152 : 153 48 : _changes_made.first++; 154 48 : _history_pointer++; 155 : } 156 155 : } 157 : 158 : void 159 133 : DiscreteNucleationFromFile::finalize() 160 : { 161 : // no communication necessary as all ranks have the full nucleus history from the 162 : // DelimitedFileReader 163 133 : _update_required = _changes_made.first > 0 || _changes_made.second > 0; 164 133 : }