LCOV - code coverage report
Current view: top level - src/userobjects - DiscreteNucleationFromFile.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 64 73 87.7 %
Date: 2025-09-04 07:55:36 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14