LCOV - code coverage report
Current view: top level - src/userobjects - FFTBufferBase.C (source / functions) Hit Total Coverage
Test: idaholab/magpie: 5710af Lines: 68 84 81.0 %
Date: 2025-07-21 23:34:39 Functions: 21 35 60.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /**********************************************************************/
       2             : /*                     DO NOT MODIFY THIS HEADER                      */
       3             : /* MAGPIE - Mesoscale Atomistic Glue Program for Integrated Execution */
       4             : /*                                                                    */
       5             : /*            Copyright 2017 Battelle Energy Alliance, LLC            */
       6             : /*                        ALL RIGHTS RESERVED                         */
       7             : /**********************************************************************/
       8             : 
       9             : #include "FFTBufferBase.h"
      10             : #include "MyTRIMMesh.h"
      11             : 
      12             : #include "MooseTypes.h"
      13             : #include "AuxiliarySystem.h"
      14             : #include "AllLocalDofIndicesThread.h"
      15             : #include "RankTwoTensor.h"
      16             : #include "RankThreeTensor.h"
      17             : #include "RankFourTensor.h"
      18             : 
      19             : #include <type_traits>
      20             : 
      21             : template <typename T>
      22             : InputParameters
      23          84 : FFTBufferBase<T>::validParams()
      24             : {
      25          84 :   InputParameters params = ElementUserObject::validParams();
      26          84 :   params.addClassDescription("Fourier transform data buffer object.");
      27         168 :   params.addRangeCheckedParam<std::vector<int>>(
      28             :       "grid",
      29             :       "grid > 0",
      30             :       "Number of grid cells in each dimension to compute "
      31             :       "the FFT on (can be omitted when using MyTRIMMesh)");
      32         168 :   params.addCoupledVar("moose_variable",
      33             :                        "Optional AuxVariable to take the initial condition of the buffer from.");
      34             : 
      35             :   // make sure we run the object on initial to apply the initial conditions
      36          84 :   params.set<ExecFlagEnum>("execute_on") = EXEC_INITIAL;
      37             : 
      38          84 :   return params;
      39           0 : }
      40             : 
      41             : template <typename T>
      42          42 : FFTBufferBase<T>::FFTBufferBase(const InputParameters & parameters)
      43             :   : ElementUserObject(parameters),
      44          84 :     _mesh(_subproblem.mesh()),
      45          42 :     _dim(_mesh.dimension()),
      46          42 :     _cell_volume(1.0),
      47          42 :     _moose_variable(coupledComponents("moose_variable")),
      48          42 :     _k_table(_dim),
      49         126 :     _how_many(_real_space_data.howMany())
      50             : {
      51             :   // make sure Real is double
      52             :   static_assert(
      53             :       std::is_same<Real, double>::value,
      54             :       "Libmesh must be build with double precision floating point numbers as the 'Real' type.");
      55             : 
      56             :   static_assert(sizeof(std::complex<Real>) == 2 * sizeof(Real),
      57             :                 "Complex numbers based on 'Real' should have the size of two 'Real' types.");
      58             : 
      59             :   // FFT needs a regular grid of values to operate on
      60          84 :   if (isParamValid("grid"))
      61             :   {
      62             :     // cannot specify a corresponding MOOSE Variable when running mesh-less
      63           0 :     if (!_moose_variable.empty())
      64           0 :       paramError("moose_variable",
      65             :                  "You cannot specify a corresponding MOOSE Variable when running mesh-less, i.e. "
      66             :                  "using the 'grid' parameter.");
      67             : 
      68             :     // if valid use the user-supplied sampling grid
      69           0 :     _grid = getParam<std::vector<int>>("grid");
      70           0 :     if (_grid.size() != _dim)
      71           0 :       paramError("grid", "Number of entries must match the mesh dimension ", _dim);
      72             :   }
      73             :   else
      74             :   {
      75          42 :     auto * mytrim_mesh = dynamic_cast<MyTRIMMesh *>(&_mesh);
      76          42 :     if (!mytrim_mesh)
      77           0 :       mooseError("Must specify 'grid' parameter if not using MyTRIMMesh");
      78             : 
      79             :     // querying the mesh to set grid
      80         144 :     for (unsigned int i = 0; i < _dim; ++i)
      81         102 :       _grid.push_back(mytrim_mesh->getCellCountInDimension(i));
      82             :   }
      83             : 
      84             :   // check optional coupled MOOSE variable (only for Real valued buffers)
      85          42 :   if (!_moose_variable.empty())
      86             :   {
      87          21 :     if (_moose_variable.size() != _how_many)
      88           0 :       paramError("moose_variable", "Variable needs to have ", _how_many, " components.");
      89             : 
      90          48 :     for (unsigned i = 0; i < _moose_variable.size(); ++i)
      91             :     {
      92             :       // check
      93          27 :       auto var = getVar("moose_variable", i);
      94          27 :       if (var->order() != 0)
      95           0 :         paramError("moose_variable", "Variable needs to have CONSTANT order.");
      96          27 :       if (var->isNodal())
      97           0 :         paramError("moose_variable", "Variable must be elemental.");
      98             : 
      99          27 :       _moose_variable[i] = &coupledValue("moose_variable", i);
     100             :     }
     101             :   }
     102             : 
     103             :   // get mesh extents and calculate space required and estimate spectrum bins
     104             :   std::size_t real_space_buffer_size = 1;
     105             :   std::size_t reciprocal_space_buffer_size = 1;
     106         144 :   for (unsigned int i = 0; i < _dim; ++i)
     107             :   {
     108         102 :     _min_corner(i) = _mesh.getMinInDimension(i);
     109         102 :     _max_corner(i) = _mesh.getMaxInDimension(i);
     110         102 :     _box_size(i) = _max_corner(i) - _min_corner(i);
     111         102 :     _cell_volume *= _box_size(i) / _grid[i];
     112             : 
     113             :     // unumber of physical grid cells
     114         102 :     real_space_buffer_size *= _grid[i];
     115             :     // last direction needs to be roughly cut in half
     116         102 :     reciprocal_space_buffer_size *= (i == _dim - 1) ? ((_grid[i] >> 1) + 1) : _grid[i];
     117             : 
     118             :     // precompute kvector components for current direction
     119         102 :     _k_table[i].resize(_grid[i]);
     120        4770 :     for (int j = 0; j < _grid[i]; ++j)
     121        4668 :       _k_table[i][j] = 2.0 * libMesh::pi *
     122        4668 :                        ((j < (_grid[i] >> 1) + 1) ? Real(j) : (Real(j) - _grid[i])) / _box_size(i);
     123             : 
     124         102 :     if (i == _dim - 1)
     125          42 :       _k_table[i].resize((_grid[i] >> 1) + 1);
     126             :   }
     127             :   _real_space_data.resize(real_space_buffer_size);
     128             :   _reciprocal_space_data.resize(reciprocal_space_buffer_size);
     129             : 
     130             :   // compute stride and start pointer
     131          42 :   _real_space_data_start = reinterpret_cast<Real *>(_real_space_data.start(0));
     132          42 :   _reciprocal_space_data_start = reinterpret_cast<Complex *>(_reciprocal_space_data.start(0));
     133             : 
     134          42 :   _real_space_data_stride = reinterpret_cast<char *>(_real_space_data.start(1)) -
     135          42 :                             reinterpret_cast<char *>(_real_space_data_start);
     136          42 :   _reciprocal_space_data_stride = reinterpret_cast<char *>(_reciprocal_space_data.start(1)) -
     137          42 :                                   reinterpret_cast<char *>(_reciprocal_space_data_start);
     138             : 
     139          42 :   if (_real_space_data_stride % sizeof(Real) != 0)
     140           0 :     mooseError("Invalid data alignment");
     141          42 :   _real_space_data_stride /= sizeof(Real);
     142             : 
     143          42 :   if (_reciprocal_space_data_stride % sizeof(Complex) != 0)
     144           0 :     mooseError("Invalid data alignment");
     145          42 :   _reciprocal_space_data_stride /= sizeof(Complex);
     146          42 : }
     147             : 
     148             : template <typename T>
     149             : void
     150      682224 : FFTBufferBase<T>::execute()
     151             : {
     152             :   // get  grid / buffer location
     153      682224 :   Point centroid = _current_elem->vertex_average();
     154             :   std::size_t a = 0;
     155     2636496 :   for (unsigned int i = 0; i < _dim; ++i)
     156     1954272 :     a = a * _grid[i] + std::floor(((centroid(i) - _min_corner(i)) * _grid[i]) / _box_size(i));
     157             : 
     158             :   // copy solution value from the variables into the buffer
     159      872928 :   for (unsigned i = 0; i < _moose_variable.size(); ++i)
     160      190704 :     _real_space_data_start[a * _how_many + i] = (*_moose_variable[i])[0];
     161      682224 : }
     162             : 
     163             : template <typename T>
     164             : void
     165          15 : FFTBufferBase<T>::forward()
     166             : {
     167          15 :   forwardRaw();
     168          15 : }
     169             : 
     170             : template <typename T>
     171             : void
     172          78 : FFTBufferBase<T>::backward()
     173             : {
     174          78 :   backwardRaw();
     175          78 :   _real_space_data *= backwardScale();
     176          78 : }
     177             : 
     178             : template <typename T>
     179             : const T &
     180     3267120 : FFTBufferBase<T>::operator()(const Point & p) const
     181             : {
     182             :   std::size_t a = 0;
     183    12750480 :   for (unsigned int i = 0; i < _dim; ++i)
     184     9483360 :     a = a * _grid[i] + std::floor(((p(i) - _min_corner(i)) * _grid[i]) / _box_size(i));
     185     3267120 :   return _real_space_data[a];
     186             : }
     187             : 
     188             : template <typename T>
     189             : T &
     190           0 : FFTBufferBase<T>::operator()(const Point & p)
     191             : {
     192             :   std::size_t a = 0;
     193           0 :   for (unsigned int i = 0; i < _dim; ++i)
     194           0 :     a = a * _grid[i] + std::floor(((p(i) - _min_corner(i)) * _grid[i]) / _box_size(i));
     195           0 :   return _real_space_data[a];
     196             : }
     197             : 
     198             : // explicit instantiations
     199             : template class FFTBufferBase<Real>;
     200             : template class FFTBufferBase<RealVectorValue>;
     201             : template class FFTBufferBase<RankTwoTensor>;
     202             : template class FFTBufferBase<RankThreeTensor>;
     203             : template class FFTBufferBase<RankFourTensor>;

Generated by: LCOV version 1.14