LCOV - code coverage report
Current view: top level - src/vectorpostprocessors - FourierPowerSpectrum.C (source / functions) Hit Total Coverage
Test: idaholab/magpie: 5710af Lines: 54 55 98.2 %
Date: 2025-07-21 23:34:39 Functions: 5 5 100.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             : #ifdef FFTW3_ENABLED
       9             : 
      10             : #include "FourierPowerSpectrum.h"
      11             : #include "FourierTransform.h"
      12             : #include "MyTRIMMesh.h"
      13             : 
      14             : #include "libmesh/utility.h"
      15             : 
      16             : #include <functional>
      17             : 
      18             : registerMooseObject("MagpieApp", FourierPowerSpectrum);
      19             : 
      20             : InputParameters
      21           8 : FourierPowerSpectrum::validParams()
      22             : {
      23           8 :   InputParameters params = GeneralVectorPostprocessor::validParams();
      24           8 :   params.addClassDescription("Compute the power spectrum of a given fourier transform. The "
      25             :                              "resulting frequency is in reciprocal length units.");
      26          16 :   params.addRequiredParam<UserObjectName>(
      27             :       "fourier_transform", "FourierTransform user object to compute the power spectrum of");
      28           8 :   return params;
      29           0 : }
      30             : 
      31           4 : FourierPowerSpectrum::FourierPowerSpectrum(const InputParameters & parameters)
      32             :   : GeneralVectorPostprocessor(parameters),
      33           4 :     _fourier_transform(getUserObject<FourierTransform>("fourier_transform")),
      34           4 :     _dim(_fourier_transform.dimension()),
      35           4 :     _grid(_fourier_transform.getGrid()),
      36           4 :     _box_size(_fourier_transform.getBoxSize()),
      37           4 :     _buffer(_fourier_transform.getBuffer()),
      38           4 :     _spectrum_size(0),
      39           4 :     _max_frequency(0),
      40           4 :     _power_spectrum(declareVector("power_spectrum")),
      41           8 :     _frequency(declareVector("frequency"))
      42             : {
      43             :   // estimate spectrum bins
      44          12 :   for (unsigned int i = 0; i < _dim; ++i)
      45             :   {
      46           8 :     _max_frequency += Utility::pow<2>(_grid[i] * 0.5 / _box_size(i));
      47           8 :     _spectrum_size += Utility::pow<2>(_grid[i]);
      48             :   }
      49             : 
      50           4 :   _max_frequency = std::sqrt(_max_frequency);
      51           4 :   _spectrum_size = std::sqrt(_spectrum_size) + 1;
      52             : 
      53             :   // resize power spectrum vector
      54           4 :   _power_spectrum.resize(_spectrum_size);
      55           4 :   _frequency.resize(_spectrum_size);
      56           4 :   _n_samples.resize(_spectrum_size);
      57             : 
      58             :   // set frequencies
      59         152 :   for (auto i = beginIndex(_frequency); i < _spectrum_size; ++i)
      60         148 :     _frequency[i] = (i * _max_frequency) / (_spectrum_size - 1);
      61           4 : }
      62             : 
      63             : void
      64          63 : FourierPowerSpectrum::computePowerSpectrum(std::vector<int> & c,
      65             :                                            std::vector<Real> & F,
      66             :                                            std::size_t i)
      67             : {
      68          63 :   if (i == 0)
      69             :   {
      70             :     Real sum_high = 0.0;
      71         120 :     for (unsigned int j = 1; j < _dim; ++j)
      72          60 :       sum_high += F[j];
      73             : 
      74        1860 :     for (c[0] = 0; c[0] < _grid[0]; ++c[0])
      75             :     {
      76             :       // do stuff at lowest dimension
      77             :       const Real sum =
      78        1800 :           sum_high + Utility::pow<2>((c[0] * 2 > _grid[0] ? _grid[0] - c[0] : c[0]) / _box_size(0));
      79             : 
      80             :       // recalculate index (row major)
      81             :       int index = 0;
      82        5400 :       for (unsigned int j = 0; j < _dim; ++j)
      83        3600 :         index = index * _grid[j] + c[j];
      84             : 
      85             :       // find bin and add to spectrum
      86        1800 :       const std::size_t bin = std::floor((std::sqrt(sum) * (_spectrum_size - 1)) / _max_frequency);
      87             :       mooseAssert(bin < _power_spectrum.size(), "Bin out of bounds in power spectrum");
      88        1800 :       _power_spectrum[bin] += Utility::pow<2>(_buffer[index]);
      89        1800 :       ++_n_samples[bin];
      90             :     }
      91             :   }
      92             :   else
      93             :     // iterate over lower dimensions
      94          63 :     for (c[i] = 0; c[i] < _grid[i]; ++c[i])
      95             :     {
      96          60 :       F[i] = Utility::pow<2>((c[i] * 2 > _grid[i] ? _grid[i] - c[i] : c[i]) / _box_size(i));
      97          60 :       computePowerSpectrum(c, F, i - 1);
      98             :     }
      99          63 : }
     100             : 
     101             : void
     102           4 : FourierPowerSpectrum::execute()
     103             : {
     104             :   // clear spectrum
     105           4 :   std::fill(_power_spectrum.begin(), _power_spectrum.end(), 0.0);
     106             : 
     107             :   // for now only compute spectrum on processor 0
     108           4 :   if (processor_id() == 0)
     109             :   {
     110             :     // clear sample count
     111             :     std::fill(_n_samples.begin(), _n_samples.end(), 0);
     112             : 
     113             :     // compute the power spectrum
     114           3 :     std::vector<int> c(_dim, 0);
     115           3 :     std::vector<Real> F(_dim);
     116           3 :     computePowerSpectrum(c, F, _dim - 1);
     117             : 
     118             :     // normalize by sample count
     119             :     mooseAssert(_power_spectrum.size() == _n_samples.size(),
     120             :                 "Size mismatch between spectrum and sample number vectors");
     121         114 :     for (auto i = beginIndex(_power_spectrum); i < _power_spectrum.size(); ++i)
     122         111 :       if (_n_samples[i] > 0)
     123         108 :         _power_spectrum[i] /= _n_samples[i];
     124             :   }
     125           4 : }
     126             : 
     127             : void
     128           4 : FourierPowerSpectrum::finalize()
     129             : {
     130             :   // broadcast result to all cores (lazily using gatherSum - all other ranks have zero vectors)
     131           4 :   gatherSum(_power_spectrum);
     132           4 : }
     133             : 
     134             : #endif // FFTW3_ENABLED

Generated by: LCOV version 1.14