LCOV - code coverage report
Current view: top level - src/userobjects - DiscreteNucleationFromFile.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #32971 (54bef8) with base c6cf66 Lines: 64 73 87.7 %
Date: 2026-05-29 20:38:39 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          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 : }

Generated by: LCOV version 1.14