LCOV - code coverage report
Current view: top level - src/ics - BimodalSuperellipsoidsIC.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 97 110 88.2 %
Date: 2025-09-04 07:55:36 Functions: 6 6 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 "BimodalSuperellipsoidsIC.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "MooseMesh.h"
      14             : #include "MooseVariable.h"
      15             : 
      16             : registerMooseObject("PhaseFieldApp", BimodalSuperellipsoidsIC);
      17             : 
      18             : InputParameters
      19          22 : BimodalSuperellipsoidsIC::validParams()
      20             : {
      21          22 :   InputParameters params = SpecifiedSmoothSuperellipsoidIC::validParams();
      22          22 :   params.addClassDescription("Bimodal size distribution of large particles (specified in input "
      23             :                              "file) and small particles (placed randomly outside the larger "
      24             :                              "particles)");
      25          44 :   params.addRequiredParam<unsigned int>("npart", "The number of random (small) particles to place");
      26          44 :   params.addRequiredParam<Real>(
      27             :       "small_spac",
      28             :       "minimum spacing between small particles, measured from closest edge to closest edge");
      29          44 :   params.addRequiredParam<Real>("large_spac",
      30             :                                 "minimum spacing between large and small particles, "
      31             :                                 "measured from closest edge to closest edge");
      32          44 :   params.addRequiredParam<Real>(
      33             :       "small_a", "Mean semiaxis a value for the randomly placed (small) superellipsoids");
      34          44 :   params.addRequiredParam<Real>(
      35             :       "small_b", "Mean semiaxis b value for the randomly placed (small) superellipsoids");
      36          44 :   params.addRequiredParam<Real>(
      37             :       "small_c", "Mean semiaxis c value for the randomly placed (small) superellipsoids");
      38          44 :   params.addRequiredParam<Real>("small_n",
      39             :                                 "Exponent n for the randomly placed (small) superellipsoids");
      40          44 :   params.addParam<Real>("size_variation",
      41          44 :                         0.0,
      42             :                         "Plus or minus fraction of random variation in the "
      43             :                         "semiaxes for uniform, standard deviation for "
      44             :                         "normal");
      45          44 :   MooseEnum rand_options("uniform normal none", "none");
      46          44 :   params.addParam<MooseEnum>(
      47             :       "size_variation_type", rand_options, "Type of distribution that random semiaxes will follow");
      48          44 :   params.addParam<unsigned int>(
      49          44 :       "numtries", 1000, "The number of tries to place the random particles");
      50          22 :   return params;
      51          22 : }
      52             : 
      53          12 : BimodalSuperellipsoidsIC::BimodalSuperellipsoidsIC(const InputParameters & parameters)
      54             :   : SpecifiedSmoothSuperellipsoidIC(parameters),
      55          12 :     _npart(getParam<unsigned int>("npart")),
      56          24 :     _small_spac(getParam<Real>("small_spac")),
      57          24 :     _large_spac(getParam<Real>("large_spac")),
      58          24 :     _small_a(getParam<Real>("small_a")),
      59          24 :     _small_b(getParam<Real>("small_b")),
      60          24 :     _small_c(getParam<Real>("small_c")),
      61          24 :     _small_n(getParam<Real>("small_n")),
      62          24 :     _size_variation(getParam<Real>("size_variation")),
      63          24 :     _size_variation_type(getParam<MooseEnum>("size_variation_type")),
      64          36 :     _max_num_tries(getParam<unsigned int>("numtries"))
      65             : {
      66          12 : }
      67             : 
      68             : void
      69          12 : BimodalSuperellipsoidsIC::initialSetup()
      70             : {
      71             :   // Set up domain bounds with mesh tools
      72          48 :   for (const auto i : make_range(Moose::dim))
      73             :   {
      74          36 :     _bottom_left(i) = _mesh.getMinInDimension(i);
      75          36 :     _top_right(i) = _mesh.getMaxInDimension(i);
      76             :   }
      77          12 :   _range = _top_right - _bottom_left;
      78             : 
      79          12 :   if (_size_variation_type == 2 && _size_variation > 0.0)
      80           0 :     mooseError("If size_variation > 0.0, you must pass in a size_variation_type in "
      81             :                "BimodalSuperellipsoidsIC");
      82             : 
      83          12 :   SmoothSuperellipsoidBaseIC::initialSetup();
      84          12 : }
      85             : 
      86             : void
      87          12 : BimodalSuperellipsoidsIC::computeSuperellipsoidSemiaxes()
      88             : {
      89          12 :   _as.resize(_input_as.size() + _npart);
      90          12 :   _bs.resize(_input_bs.size() + _npart);
      91          12 :   _cs.resize(_input_cs.size() + _npart);
      92             : 
      93             :   // First fill in the specified (large) superellipsoids from the input file
      94          30 :   for (unsigned int i = 0; i < _input_as.size(); ++i)
      95             :   {
      96          18 :     _as[i] = _input_as[i];
      97          18 :     _bs[i] = _input_bs[i];
      98          18 :     _cs[i] = _input_cs[i];
      99             :   }
     100             : 
     101             :   // Then fill in the randomly positioned (small) superellipsoids
     102          90 :   for (unsigned int i = _input_as.size(); i < _input_as.size() + _npart; ++i)
     103             :   {
     104             :     // Vary semiaxes
     105          78 :     switch (_size_variation_type)
     106             :     {
     107           0 :       case 0: // Random distrubtion, maintaining constant shape
     108             :       {
     109           0 :         Real rand_num = _random.rand(_tid);
     110           0 :         _as[i] = _small_a * (1.0 + (1.0 - 2.0 * rand_num) * _size_variation);
     111           0 :         _bs[i] = _small_b * (1.0 + (1.0 - 2.0 * rand_num) * _size_variation);
     112           0 :         _cs[i] = _small_c * (1.0 + (1.0 - 2.0 * rand_num) * _size_variation);
     113           0 :         break;
     114             :       }
     115          30 :       case 1: // Normal distribution of semiaxis size, maintaining constant shape
     116          30 :         _as[i] = _random.randNormal(_tid, _small_a, _size_variation);
     117          30 :         _bs[i] = _as[i] * _small_b / _small_a;
     118          30 :         _cs[i] = _as[i] * _small_c / _small_a;
     119          30 :         break;
     120          48 :       case 2: // No variation
     121          48 :         _as[i] = _small_a;
     122          48 :         _bs[i] = _small_b;
     123          48 :         _cs[i] = _small_c;
     124             :     }
     125             : 
     126          78 :     if (_as[i] < 0.0)
     127           0 :       _as[i] = 0.0;
     128          78 :     if (_bs[i] < 0.0)
     129           0 :       _bs[i] = 0.0;
     130          78 :     if (_cs[i] < 0.0)
     131           0 :       _cs[i] = 0.0;
     132             :   }
     133          12 : }
     134             : 
     135             : void
     136          12 : BimodalSuperellipsoidsIC::computeSuperellipsoidExponents()
     137             : {
     138          12 :   _ns.resize(_input_ns.size() + _npart);
     139             : 
     140             :   // First fill in the specified (large) superellipsoids from the input file
     141          30 :   for (unsigned int i = 0; i < _input_ns.size(); ++i)
     142          18 :     _ns[i] = _input_ns[i];
     143             : 
     144             :   // Then fill in the randomly positioned (small) superellipsoids
     145             :   // The shape is assumed to stay constant so n does not vary
     146          90 :   for (unsigned int i = _input_ns.size(); i < _input_ns.size() + _npart; ++i)
     147          78 :     _ns[i] = _small_n;
     148          12 : }
     149             : 
     150             : void
     151           6 : BimodalSuperellipsoidsIC::computeSuperellipsoidCenters()
     152             : {
     153           6 :   _centers.resize(_x_positions.size() + _npart);
     154             : 
     155             :   // First place the specified (large) particles from the input file
     156          18 :   for (unsigned int i = 0; i < _x_positions.size(); ++i)
     157             :   {
     158          12 :     _centers[i](0) = _x_positions[i];
     159          12 :     _centers[i](1) = _y_positions[i];
     160          12 :     _centers[i](2) = _z_positions[i];
     161             :   }
     162             : 
     163             :   // Next place the randomly positioned (small) particles
     164          36 :   for (unsigned int i = _x_positions.size(); i < _x_positions.size() + _npart; ++i)
     165             :   {
     166             :     unsigned int num_tries = 0;
     167             : 
     168         690 :     while (num_tries < _max_num_tries)
     169             :     {
     170         690 :       num_tries++;
     171             : 
     172             :       RealTensorValue ran;
     173         690 :       ran(0, 0) = _random.rand(_tid);
     174         690 :       ran(1, 1) = _random.rand(_tid);
     175         690 :       ran(2, 2) = _random.rand(_tid);
     176             : 
     177         690 :       _centers[i] = _bottom_left + ran * _range;
     178             : 
     179             :       // check for collisions with the specified (large) and randomly placed small particles
     180        1644 :       for (unsigned int j = 0; j < i; ++j)
     181             :       {
     182             :         // Compute the distance r1 from the center of each specified superellipsoid to its
     183             :         // outside edge along the vector between the specified superellipsoid and the current
     184             :         // randomly positioned one.
     185             :         // This uses the equation for a superellipse in polar coordinates and substitutes
     186             :         // distances for sin, cos functions.
     187        1614 :         Point dist_vec = _mesh.minPeriodicVector(_var.number(), _centers[i], _centers[j]);
     188        1614 :         const Real dist = dist_vec.norm();
     189             : 
     190             :         // First calculate rmn1 = r1^(-n), replacing sin, cos functions with distances
     191        1614 :         Real rmn1 = (std::pow(std::abs(dist_vec(0) / dist / _as[j]), _ns[j]) +
     192        1614 :                      std::pow(std::abs(dist_vec(1) / dist / _bs[j]), _ns[j]) +
     193        1614 :                      std::pow(std::abs(dist_vec(2) / dist / _cs[j]), _ns[j]));
     194             :         // Then calculate r1 from rmn1
     195        1614 :         const Real r1 = std::pow(rmn1, (-1.0 / _ns[j]));
     196             : 
     197             :         // Now calculate the distance r2 from the center of the randomly placed
     198             :         // superellipsoid to its outside edge in the same manner
     199        1614 :         Real rmn2 = (std::pow(std::abs(dist_vec(0) / dist / _as[i]), _ns[i]) +
     200        1614 :                      std::pow(std::abs(dist_vec(1) / dist / _bs[i]), _ns[i]) +
     201        1614 :                      std::pow(std::abs(dist_vec(2) / dist / _cs[i]), _ns[i]));
     202        1614 :         const Real r2 = std::pow(rmn2, (-1.0 / _ns[i]));
     203             : 
     204             :         // Calculate the distance between the edges (first in the list are the large then come the
     205             :         // small)
     206        1614 :         if ((dist - r1 - r2) < (j < _x_positions.size() ? _large_spac : _small_spac))
     207         660 :           goto fail;
     208             :       }
     209             : 
     210             :       // accept the position of the new center
     211          30 :       goto accept;
     212             : 
     213             :     // retry a new position until tries are exhausted
     214             :     fail:
     215             :       continue;
     216             :     }
     217             : 
     218           0 :     if (num_tries == _max_num_tries)
     219           0 :       mooseError("Too many tries in MultiSmoothCircleIC");
     220             : 
     221           0 :   accept:
     222             :     continue;
     223          30 :   }
     224           6 : }

Generated by: LCOV version 1.14