LCOV - code coverage report
Current view: top level - src/userobjects - PolycrystalHex.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 52 59 88.1 %
Date: 2025-09-04 07:55:36 Functions: 3 3 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 "PolycrystalHex.h"
      11             : #include "MooseRandom.h"
      12             : #include "MooseMesh.h"
      13             : #include "MathUtils.h"
      14             : 
      15             : registerMooseObject("PhaseFieldApp", PolycrystalHex);
      16             : 
      17             : InputParameters
      18          76 : PolycrystalHex::validParams()
      19             : {
      20          76 :   InputParameters params = PolycrystalVoronoi::validParams();
      21          76 :   params.addClassDescription("Perturbed hexagonal polycrystal");
      22         152 :   params.addParam<Real>("x_offset", 0.5, "Specifies offset of hexagon grid in x-direction");
      23         228 :   params.addRangeCheckedParam<Real>(
      24             :       "perturbation_percent",
      25         152 :       0.0,
      26             :       "perturbation_percent >= 0.0 & perturbation_percent <= 1.0",
      27             :       "The percent to randomly perturb centers of grains relative to the size of the grain");
      28          76 :   return params;
      29           0 : }
      30             : 
      31          38 : PolycrystalHex::PolycrystalHex(const InputParameters & parameters)
      32             :   : PolycrystalVoronoi(parameters),
      33          38 :     _x_offset(getParam<Real>("x_offset")),
      34         114 :     _perturbation_percent(getParam<Real>("perturbation_percent"))
      35             : {
      36          38 :   if (_columnar_3D == false && _dim == 3)
      37           0 :     mooseError(
      38             :         "PolycrystalHex is supported on 2D domains or 3D domains with the columnar_3D option");
      39          38 :   if (_grain_num % 2 != 0)
      40           0 :     mooseError("PolycrystalHex requires an even square number for 2D or columnar 3D");
      41             : 
      42          76 :   _random.seed(_tid, getParam<unsigned int>("rand_seed"));
      43          38 : }
      44             : 
      45             : void
      46          29 : PolycrystalHex::precomputeGrainStructure()
      47             : {
      48          29 :   unsigned int d = _dim;
      49             : 
      50          29 :   if (_columnar_3D && _dim == 3)
      51             :     d -= 1;
      52             : 
      53             :   // check if periodic boundary condition is set
      54          87 :   for (unsigned int j = 0; j < d; ++j)
      55             :   {
      56         370 :     for (unsigned int i = 0; i < _vars.size(); ++i)
      57         312 :       if (!_mesh.isTranslatedPeriodic(_vars[i]->number(), j))
      58           0 :         mooseError("PolycrystalHex works only with periodic BCs");
      59             :   }
      60             : 
      61          29 :   const unsigned int root = MathUtils::round(std::pow(_grain_num, 1.0 / d));
      62             : 
      63             :   // integer power the rounded root and check if we recover the grain number
      64             :   unsigned int grain_pow = root;
      65          58 :   for (unsigned int i = 1; i < d; ++i)
      66          29 :     grain_pow *= root;
      67             : 
      68          29 :   if (_grain_num != grain_pow)
      69           0 :     mooseError(
      70             :         "PolycrystalHex requires a square number for 2D or columnar 3D and a cubic number for 3D");
      71             : 
      72             :   // Set up domain bounds with mesh tools
      73         116 :   for (const auto i : make_range(Moose::dim))
      74             :   {
      75          87 :     _bottom_left(i) = _mesh.getMinInDimension(i);
      76          87 :     _top_right(i) = _mesh.getMaxInDimension(i);
      77             :   }
      78          29 :   _range = _top_right - _bottom_left;
      79             : 
      80          29 :   _centerpoints.resize(_grain_num);
      81             : 
      82          29 :   std::vector<Real> distances(_grain_num);
      83          29 :   std::vector<Point> holder(_grain_num);
      84             : 
      85          29 :   const Real ndist = 1.0 / root;
      86             : 
      87             :   // Assign the relative center points positions, defining the grains according to a hexagonal
      88             :   // pattern
      89             :   unsigned int count = 0;
      90             : 
      91         116 :   for (unsigned int k = 0; k < (d == 3 ? root : 1); ++k)
      92         119 :     for (unsigned int j = 0; j < (d >= 2 ? root : 1); ++j)
      93         462 :       for (unsigned int i = 0; i < root; ++i)
      94             :       {
      95             :         // set x-coordinate
      96         372 :         holder[count](0) = i * ndist + (0.5 * ndist * (j % 2)) + _x_offset * ndist;
      97             : 
      98             :         // set y-coordinate
      99         372 :         holder[count](1) = j * ndist + (0.5 * ndist * (k % 2));
     100             : 
     101             :         // set z-coordinate
     102         372 :         holder[count](2) = k * ndist;
     103             : 
     104             :         // increment counter
     105         372 :         count++;
     106             :       }
     107             : 
     108             :   // Assign center point values
     109         401 :   for (unsigned int grain = 0; grain < _grain_num; ++grain)
     110        1488 :     for (const auto i : make_range(Moose::dim))
     111             :     {
     112        1116 :       if (_range(i) == 0)
     113         352 :         continue;
     114             : 
     115         764 :       Real perturbation_dist = (_range(i) / root * (_random.rand(_tid) * 2 - 1.0)) *
     116         764 :                                _perturbation_percent; // Perturb -100 to 100%
     117         764 :       _centerpoints[grain](i) = _bottom_left(i) + _range(i) * holder[grain](i) + perturbation_dist;
     118             : 
     119         764 :       if (_centerpoints[grain](i) > _top_right(i))
     120           0 :         _centerpoints[grain](i) = _top_right(i);
     121         764 :       if (_centerpoints[grain](i) < _bottom_left(i))
     122           0 :         _centerpoints[grain](i) = _bottom_left(i);
     123             : 
     124         764 :       if (_columnar_3D && _dim == 3)
     125          60 :         _centerpoints[grain](2) = _bottom_left(2) + _range(2) * 0.5;
     126             :     }
     127             : 
     128          29 :   buildSearchTree();
     129          29 : }

Generated by: LCOV version 1.14