LCOV - code coverage report
Current view: top level - src/userobjects - DiscreteNucleationMap.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 58 59 98.3 %
Date: 2025-09-04 07:55:36 Functions: 7 7 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 "DiscreteNucleationMap.h"
      11             : #include "MooseMesh.h"
      12             : #include "Executioner.h"
      13             : 
      14             : #include "libmesh/quadrature.h"
      15             : 
      16             : registerMooseObject("PhaseFieldApp", DiscreteNucleationMap);
      17             : 
      18             : InputParameters
      19         310 : DiscreteNucleationMap::validParams()
      20             : {
      21         310 :   InputParameters params = ElementUserObject::validParams();
      22         310 :   params.addClassDescription("Generates a spatial smoothed map of all nucleation sites with the "
      23             :                              "data of the DiscreteNucleationInserter for use by the "
      24             :                              "DiscreteNucleation material.");
      25         620 :   params.addParam<Real>("int_width", 0.0, "Nucleus interface width for smooth nuclei");
      26         620 :   params.addRequiredParam<UserObjectName>("inserter", "DiscreteNucleationInserter user object");
      27         620 :   params.addCoupledVar("periodic",
      28             :                        "Use the periodicity settings of this variable to populate the grain map");
      29             :   // the mapping needs to run at timestep begin, which is after the adaptivity
      30             :   // run of the previous timestep.
      31         310 :   params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_BEGIN;
      32         310 :   return params;
      33           0 : }
      34             : 
      35         164 : DiscreteNucleationMap::DiscreteNucleationMap(const InputParameters & parameters)
      36             :   : ElementUserObject(parameters),
      37         164 :     _mesh_changed(false),
      38         164 :     _inserter(getUserObject<DiscreteNucleationInserterBase>("inserter")),
      39         298 :     _periodic(isCoupled("periodic") ? coupled("periodic") : -1),
      40         328 :     _int_width(getParam<Real>("int_width")),
      41         328 :     _nucleus_list(_inserter.getNucleusList())
      42             : {
      43         164 :   _zero_map.assign(_fe_problem.getMaxQps(), 0.0);
      44         164 : }
      45             : 
      46             : void
      47        1123 : DiscreteNucleationMap::initialize()
      48             : {
      49        1123 :   if (_inserter.isMapUpdateRequired() || _mesh_changed || _force_rebuild_map)
      50             :   {
      51             :     // If the last solve didn't converge, postpone the rebuild until the next timestep
      52         511 :     if (_app.getExecutioner()->lastSolveConverged())
      53             :     {
      54         502 :       _rebuild_map = true;
      55             :       _nucleus_map.clear();
      56         502 :       _force_rebuild_map = false;
      57             :     }
      58             :     else
      59             :     {
      60           9 :       _rebuild_map = false;
      61           9 :       _force_rebuild_map = true;
      62             :     }
      63             :   }
      64             :   else
      65         612 :     _rebuild_map = false;
      66             : 
      67        1123 :   _mesh_changed = false;
      68        1123 : }
      69             : 
      70             : void
      71     1586128 : DiscreteNucleationMap::execute()
      72             : {
      73     1586128 :   if (_rebuild_map)
      74             :   {
      75             :     // reserve space for each quadrature point in the element
      76      833074 :     _elem_map.assign(_qrule->n_points(), 0);
      77             : 
      78             :     // store a random number for each quadrature point
      79             :     unsigned int active_nuclei = 0;
      80     4119770 :     for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp)
      81             :     {
      82             :       Real r = std::numeric_limits<Real>::max();
      83             : 
      84             :       // find the distance to the closest nucleus
      85             :       Real local_radius = 0.0;
      86    12783568 :       for (unsigned i = 0; i < _nucleus_list.size(); ++i)
      87             :       {
      88             :         // use a non-periodic or periodic distance
      89     9496872 :         r = _periodic < 0
      90     9496872 :                 ? (_q_point[qp] - _nucleus_list[i].center).norm()
      91     7779272 :                 : _mesh.minPeriodicDistance(_periodic, _q_point[qp], _nucleus_list[i].center);
      92             : 
      93             :         // grab the radius of the nucleus that this qp is closest to
      94     9496872 :         local_radius = _nucleus_list[i].radius;
      95             : 
      96             :         // compute intensity value with smooth interface
      97             :         Real value = 0.0;
      98     9496872 :         if (r <= local_radius - _int_width / 2.0) // Inside circle
      99             :         {
     100     1055880 :           active_nuclei++;
     101             :           value = 1.0;
     102             :         }
     103     8440992 :         else if (r < local_radius + _int_width / 2.0) // Smooth interface
     104             :         {
     105       52444 :           Real int_pos = (r - local_radius + _int_width / 2.0) / _int_width;
     106       52444 :           active_nuclei++;
     107       52444 :           value = (1.0 + std::cos(int_pos * libMesh::pi)) / 2.0;
     108             :         }
     109     9496872 :         if (value > _elem_map[qp])
     110      883053 :           _elem_map[qp] = value;
     111             :       }
     112             :     }
     113             : 
     114             :     // if the map is not empty insert it
     115      833074 :     if (active_nuclei > 0)
     116             :       _nucleus_map.insert(
     117      458058 :           std::pair<dof_id_type, std::vector<Real>>(_current_elem->id(), _elem_map));
     118             :   }
     119     1586128 : }
     120             : 
     121             : void
     122         142 : DiscreteNucleationMap::threadJoin(const UserObject & y)
     123             : {
     124             :   // if the map needs to be updated we merge the maps from all threads
     125         142 :   if (_rebuild_map)
     126             :   {
     127             :     const auto & uo = static_cast<const DiscreteNucleationMap &>(y);
     128          64 :     _nucleus_map.insert(uo._nucleus_map.begin(), uo._nucleus_map.end());
     129             :   }
     130         142 : }
     131             : 
     132             : void
     133          27 : DiscreteNucleationMap::meshChanged()
     134             : {
     135          27 :   _mesh_changed = true;
     136          27 : }
     137             : 
     138             : const std::vector<Real> &
     139     2228668 : DiscreteNucleationMap::nuclei(const Elem * elem) const
     140             : {
     141     2228668 :   NucleusMap::const_iterator i = _nucleus_map.find(elem->id());
     142             : 
     143             :   // if no entry in the map was found the element contains no nucleus
     144     2228668 :   if (i == _nucleus_map.end())
     145     1787694 :     return _zero_map;
     146             : 
     147      440974 :   return i->second;
     148             : }

Generated by: LCOV version 1.14