LCOV - code coverage report
Current view: top level - src/ics - SmoothCircleBaseIC.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 82 91 90.1 %
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 "SmoothCircleBaseIC.h"
      11             : #include "MooseMesh.h"
      12             : #include "MooseVariable.h"
      13             : #include "FEProblemBase.h"
      14             : 
      15             : #include "libmesh/utility.h"
      16             : 
      17             : InputParameters
      18        5468 : SmoothCircleBaseIC::validParams()
      19             : {
      20        5468 :   InputParameters params = InitialCondition::validParams();
      21       10936 :   params.addRequiredParam<Real>("invalue", "The variable value inside the circle");
      22       10936 :   params.addRequiredParam<Real>("outvalue", "The variable value outside the circle");
      23       10936 :   params.addParam<Real>(
      24       10936 :       "int_width", 0.0, "The interfacial width of the void surface.  Defaults to sharp interface");
      25       10936 :   params.addParam<bool>("3D_spheres", true, "in 3D, whether the objects are spheres or columns");
      26       10936 :   params.addParam<bool>("zero_gradient",
      27       10936 :                         false,
      28             :                         "Set the gradient DOFs to zero. This can avoid "
      29             :                         "numerical problems with higher order shape "
      30             :                         "functions and overlapping circles.");
      31       10936 :   params.addParam<unsigned int>("rand_seed", 12345, "Seed value for the random number generator");
      32       10936 :   MooseEnum profileType("COS TANH", "COS");
      33       10936 :   params.addParam<MooseEnum>(
      34             :       "profile", profileType, "Functional dependence for the interface profile");
      35        5468 :   return params;
      36        5468 : }
      37             : 
      38        2849 : SmoothCircleBaseIC::SmoothCircleBaseIC(const InputParameters & parameters)
      39             :   : InitialCondition(parameters),
      40        2849 :     _mesh(_fe_problem.mesh()),
      41        2849 :     _invalue(parameters.get<Real>("invalue")),
      42        2849 :     _outvalue(parameters.get<Real>("outvalue")),
      43        2849 :     _int_width(parameters.get<Real>("int_width")),
      44        2849 :     _3D_spheres(parameters.get<bool>("3D_spheres")),
      45        2849 :     _zero_gradient(parameters.get<bool>("zero_gradient")),
      46        2942 :     _num_dim(_3D_spheres ? 3 : 2),
      47        8547 :     _profile(getParam<MooseEnum>("profile").getEnum<ProfileType>())
      48             : {
      49        5698 :   _random.seed(_tid, getParam<unsigned int>("rand_seed"));
      50             : 
      51        2849 :   if (_int_width <= 0.0 && _profile == ProfileType::TANH)
      52           0 :     paramError("int_width",
      53             :                "Interface width has to be strictly positive for the hyperbolic tangent profile");
      54        2849 : }
      55             : 
      56             : void
      57        2158 : SmoothCircleBaseIC::initialSetup()
      58             : {
      59             :   // Compute radii and centers and initialize vector sizes
      60        2158 :   computeCircleRadii();
      61        2158 :   computeCircleCenters();
      62             : 
      63        2158 :   if (_centers.size() != _radii.size())
      64           0 :     mooseError("_center and _radii vectors are not the same size in the Circle IC");
      65             : 
      66        2158 :   if (_centers.size() < 1)
      67           0 :     mooseError("_center and _radii were not initialized in the Circle IC");
      68        2158 : }
      69             : 
      70             : Real
      71    13543496 : SmoothCircleBaseIC::value(const Point & p)
      72             : {
      73    13543496 :   Real value = _outvalue;
      74             :   Real val2 = 0.0;
      75             : 
      76   331826366 :   for (unsigned int circ = 0; circ < _centers.size() && value != _invalue; ++circ)
      77             :   {
      78   318282870 :     val2 = computeCircleValue(p, _centers[circ], _radii[circ]);
      79   318282870 :     if ((val2 > value && _invalue > _outvalue) || (val2 < value && _outvalue > _invalue))
      80             :       value = val2;
      81             :   }
      82             : 
      83    13543496 :   return value;
      84             : }
      85             : 
      86             : RealGradient
      87      228588 : SmoothCircleBaseIC::gradient(const Point & p)
      88             : {
      89      228588 :   if (_zero_gradient)
      90             :     return 0.0;
      91             : 
      92             :   RealGradient gradient = 0.0;
      93      228588 :   Real value = _outvalue;
      94             :   Real val2 = 0.0;
      95             : 
      96      502176 :   for (unsigned int circ = 0; circ < _centers.size(); ++circ)
      97             :   {
      98      273588 :     val2 = computeCircleValue(p, _centers[circ], _radii[circ]);
      99      273588 :     if ((val2 > value && _invalue > _outvalue) || (val2 < value && _outvalue > _invalue))
     100             :     {
     101             :       value = val2;
     102       77754 :       gradient = computeCircleGradient(p, _centers[circ], _radii[circ]);
     103             :     }
     104             :   }
     105             : 
     106      228588 :   return gradient;
     107             : }
     108             : 
     109             : Real
     110   318496458 : SmoothCircleBaseIC::computeCircleValue(const Point & p, const Point & center, const Real & radius)
     111             : {
     112   318496458 :   Point l_center = center;
     113   318496458 :   Point l_p = p;
     114   318496458 :   if (!_3D_spheres) // Create 3D cylinders instead of spheres
     115             :   {
     116      216288 :     l_p(2) = 0.0;
     117      216288 :     l_center(2) = 0.0;
     118             :   }
     119             :   // Compute the distance between the current point and the center
     120   318496458 :   Real dist = _mesh.minPeriodicDistance(_var.number(), l_p, l_center);
     121             : 
     122   318496458 :   switch (_profile)
     123             :   {
     124   318446858 :     case ProfileType::COS:
     125             :     {
     126             :       // Return value
     127   318446858 :       Real value = _outvalue; // Outside circle
     128             : 
     129   318446858 :       if (dist <= radius - _int_width / 2.0) // Inside circle
     130     4012601 :         value = _invalue;
     131   314434257 :       else if (dist < radius + _int_width / 2.0) // Smooth interface
     132             :       {
     133     1600904 :         Real int_pos = (dist - radius + _int_width / 2.0) / _int_width;
     134     1600904 :         value = _outvalue + (_invalue - _outvalue) * (1.0 + std::cos(int_pos * libMesh::pi)) / 2.0;
     135             :       }
     136             :       return value;
     137             :     }
     138             : 
     139       49600 :     case ProfileType::TANH:
     140       49600 :       return (_invalue - _outvalue) * 0.5 * (std::tanh(2.0 * (radius - dist) / _int_width) + 1.0) +
     141       49600 :              _outvalue;
     142             : 
     143           0 :     default:
     144           0 :       mooseError("Internal error.");
     145             :   }
     146             : }
     147             : 
     148             : RealGradient
     149       77754 : SmoothCircleBaseIC::computeCircleGradient(const Point & p,
     150             :                                           const Point & center,
     151             :                                           const Real & radius)
     152             : {
     153       77754 :   Point l_center = center;
     154       77754 :   Point l_p = p;
     155       77754 :   if (!_3D_spheres) // Create 3D cylinders instead of spheres
     156             :   {
     157           0 :     l_p(2) = 0.0;
     158           0 :     l_center(2) = 0.0;
     159             :   }
     160             :   // Compute the distance between the current point and the center
     161       77754 :   Real dist = _mesh.minPeriodicDistance(_var.number(), l_p, l_center);
     162             : 
     163             :   // early return if we are probing the center of the circle
     164       77754 :   if (dist == 0.0)
     165             :     return 0.0;
     166             : 
     167             :   Real DvalueDr = 0.0;
     168       77672 :   switch (_profile)
     169             :   {
     170       47672 :     case ProfileType::COS:
     171       47672 :       if (dist < radius + _int_width / 2.0 && dist > radius - _int_width / 2.0)
     172             :       {
     173       18276 :         const Real int_pos = (dist - radius + _int_width / 2.0) / _int_width;
     174       18276 :         const Real Dint_posDr = 1.0 / _int_width;
     175       18276 :         DvalueDr = Dint_posDr * (_invalue - _outvalue) *
     176       18276 :                    (-std::sin(int_pos * libMesh::pi) * libMesh::pi) / 2.0;
     177             :       }
     178             :       break;
     179             : 
     180       30000 :     case ProfileType::TANH:
     181       30000 :       DvalueDr = -(_invalue - _outvalue) * 0.5 / _int_width * libMesh::pi *
     182       30000 :                  (1.0 - Utility::pow<2>(std::tanh(4.0 * (radius - dist) / _int_width)));
     183       30000 :       break;
     184             : 
     185           0 :     default:
     186           0 :       mooseError("Internal error.");
     187             :   }
     188             : 
     189       77672 :   return _mesh.minPeriodicVector(_var.number(), center, p) * (DvalueDr / dist);
     190             : }

Generated by: LCOV version 1.14