From ee72a7feebe3c3bd4a0067128d2c0f9e87248d6e Mon Sep 17 00:00:00 2001 From: Daniel Schwen Date: Mon, 2 Mar 2020 08:50:34 -0700 Subject: [PATCH] Add FFTData (#401) --- include/problems/FFTProblem.h | 2 - include/userobjects/FFTBufferBase.h | 3 +- include/utils/ComplexTypes.h | 8 +- include/utils/FFTData.h | 65 +++++++ include/variables/MooseFFTVariable.h | 2 +- src/executioners/SpectralExecutionerBase.C | 27 +-- src/problems/FFTProblem.C | 2 +- src/userobjects/FFTBufferBase.C | 1 + src/utils/ComplexTypes.C | 11 +- src/utils/FFTData.C | 193 +++++++++++++++++++++ src/variables/MooseFFTVariable.C | 2 +- 11 files changed, 290 insertions(+), 26 deletions(-) create mode 100644 include/utils/FFTData.h create mode 100644 src/utils/FFTData.C diff --git a/include/problems/FFTProblem.h b/include/problems/FFTProblem.h index 488aee18..be0a090a 100644 --- a/include/problems/FFTProblem.h +++ b/include/problems/FFTProblem.h @@ -39,8 +39,6 @@ class FFTProblem : public FEProblem /// dummy system for the FFT variables AuxiliarySystem _fft_dummy_system; - - unsigned int _fft_var_number; }; template diff --git a/include/userobjects/FFTBufferBase.h b/include/userobjects/FFTBufferBase.h index e7db1c80..fe4921eb 100644 --- a/include/userobjects/FFTBufferBase.h +++ b/include/userobjects/FFTBufferBase.h @@ -18,8 +18,7 @@ class FFTBufferBase; #define usingFFTBufferBaseMembers \ using ElementUserObject::_perf_graph; \ using FFTBufferBase::_dim; \ - using FFTBufferBase::_real_space_grid; \ - using FFTBufferBase::_reciprocal_space_grid; \ + using FFTBufferBase::_grid; \ using FFTBufferBase::_real_space_data; \ using FFTBufferBase::_reciprocal_space_data; \ using FFTBufferBase::_real_space_data_start; \ diff --git a/include/utils/ComplexTypes.h b/include/utils/ComplexTypes.h index 3caddeb3..8f2f7fd2 100644 --- a/include/utils/ComplexTypes.h +++ b/include/utils/ComplexTypes.h @@ -17,10 +17,10 @@ #include "libmesh/vector_value.h" typedef std::complex Complex; -typedef VectorValue> ComplexVectorValue; -typedef RankTwoTensorTempl> ComplexRankTwoTensor; -typedef RankThreeTensorTempl> ComplexRankThreeTensor; -typedef RankFourTensorTempl> ComplexRankFourTensor; +typedef VectorValue ComplexVectorValue; +typedef RankTwoTensorTempl ComplexRankTwoTensor; +typedef RankThreeTensorTempl ComplexRankThreeTensor; +typedef RankFourTensorTempl ComplexRankFourTensor; // helper template to select the corresponding complex tensor type template diff --git a/include/utils/FFTData.h b/include/utils/FFTData.h new file mode 100644 index 00000000..1f17bab0 --- /dev/null +++ b/include/utils/FFTData.h @@ -0,0 +1,65 @@ +/**********************************************************************/ +/* DO NOT MODIFY THIS HEADER */ +/* MAGPIE - Mesoscale Atomistic Glue Program for Integrated Execution */ +/* */ +/* Copyright 2017 Battelle Energy Alliance, LLC */ +/* ALL RIGHTS RESERVED */ +/**********************************************************************/ + +#pragma once + +#include "ComplexTypes.h" + +// helper template to select the corresponding scalar type +template +struct FFTScalarType +{ + using type = Real; +}; + +template +struct FFTScalarType> +{ + using type = Complex; +}; + +/** + * Helper class to hold the reciprocal space data + */ +template +class FFTData +{ + using ScalarT = typename FFTScalarType::type; + +public: + FFTData(std::size_t size = 0) { resize(size); } + void resize(std::size_t size) { _buffer.resize(size); } + + ///@{ data access by index + const T & operator[](std::size_t i) const { return _buffer[i]; } + T & operator[](std::size_t i) { return _buffer[i]; } + ///@} + + ///@{ convenience math operators + FFTData & operator+=(FFTData const & rhs); + FFTData & operator-=(FFTData const & rhs); + FFTData & operator*=(FFTData const & rhs); + FFTData & operator/=(FFTData const & rhs); + FFTData & operator*=(Real rhs); + FFTData & operator/=(Real rhs); + FFTData & operator=(FFTData const & rhs); + ///@} + + /// return the number of proper grid cells + std::size_t size() const { return _buffer.size(); } + + /// get the addres of the first data element of the ith object in the buffer + void * start(std::size_t i); + + /// get the number of transforms required for type T + std::size_t howMany() const; + +protected: + /// FFT data buffer + std::vector _buffer; +}; diff --git a/include/variables/MooseFFTVariable.h b/include/variables/MooseFFTVariable.h index 698eabdc..8f39a8b5 100644 --- a/include/variables/MooseFFTVariable.h +++ b/include/variables/MooseFFTVariable.h @@ -53,7 +53,7 @@ class MooseFFTVariable : public MooseVariable { mooseError("Nodal FFT variables are not supported."); } - virtual void reinitNodesNeighbor(const std::vector & nodes) + virtual void reinitNodesNeighbor(const std::vector &) { mooseError("Nodal FFT variables are not supported."); } diff --git a/src/executioners/SpectralExecutionerBase.C b/src/executioners/SpectralExecutionerBase.C index 09067b3e..6b677041 100644 --- a/src/executioners/SpectralExecutionerBase.C +++ b/src/executioners/SpectralExecutionerBase.C @@ -59,6 +59,7 @@ SpectralExecutionerBase::execute() // back and forth test auto & c_buffer = getFFTBuffer("c"); auto c = c_buffer.realSpace(); + auto c_tilde = c_buffer.reciprocalSpace(); c_buffer.forward(); auto & R_buffer = getFFTBuffer("R"); @@ -114,24 +115,25 @@ SpectralExecutionerBase::kVectorMultiply(const FFTBufferBase & in_buffer, { case 1: { + const auto & ivec = in_buffer.kTable(0); const int ni = grid[0]; - for (int i = 0; i < ni; ++i) - { - out[i](0) = in[i] * i; - } + for (int i = 0; i * 2 <= ni; ++i) + out[i](0) = in[i] * ivec[i]; return; } case 2: { std::size_t index = 0; + const auto & ivec = in_buffer.kTable(0); + const auto & jvec = in_buffer.kTable(1); const int ni = grid[0]; const int nj = grid[1]; for (int i = 0; i < ni; ++i) - for (int j = 0; j < nj; ++j) + for (int j = 0; j * 2 <= nj; ++j) { - out[index](0) = in[index] * i; - out[index](1) = in[index] * j; + out[index](0) = in[index] * ivec[i]; + out[index](1) = in[index] * jvec[j]; index++; } return; @@ -140,16 +142,19 @@ SpectralExecutionerBase::kVectorMultiply(const FFTBufferBase & in_buffer, case 3: { std::size_t index = 0; + const auto & ivec = in_buffer.kTable(0); + const auto & jvec = in_buffer.kTable(1); + const auto & kvec = in_buffer.kTable(2); const int ni = grid[0]; const int nj = grid[1]; const int nk = grid[2]; for (int i = 0; i < ni; ++i) for (int j = 0; j < nj; ++j) - for (int k = 0; k < nk; ++k) + for (int k = 0; k * 2 <= nk; ++k) { - out[index](0) = in[index] * i; - out[index](1) = in[index] * j; - out[index](2) = in[index] * k; + out[index](0) = in[index] * ivec[i]; + out[index](1) = in[index] * jvec[j]; + out[index](2) = in[index] * kvec[k]; index++; } return; diff --git a/src/problems/FFTProblem.C b/src/problems/FFTProblem.C index 92a0c86e..48119025 100644 --- a/src/problems/FFTProblem.C +++ b/src/problems/FFTProblem.C @@ -85,7 +85,7 @@ FFTProblem::getVariable(THREAD_ID tid, auto params = MooseVariableBase::validParams(); params.set("order") = "CONSTANT"; params.set("family") = "MONOMIAL"; - params.set("_var_num") = _fft_var_number; + params.set("_var_num") = fft_var_number; params.set("tid") = tid; params.set("_tid") = tid; params.set("_var_kind") = Moose::VarKindType::VAR_AUXILIARY; diff --git a/src/userobjects/FFTBufferBase.C b/src/userobjects/FFTBufferBase.C index 5b37241f..aa45e65c 100644 --- a/src/userobjects/FFTBufferBase.C +++ b/src/userobjects/FFTBufferBase.C @@ -45,6 +45,7 @@ FFTBufferBase::FFTBufferBase(const InputParameters & parameters) _dim(_mesh.dimension()), _cell_volume(1.0), _moose_variable(coupledComponents("moose_variable")), + _k_table(_dim), _how_many(_real_space_data.howMany()) { // make sure Real is double diff --git a/src/utils/ComplexTypes.C b/src/utils/ComplexTypes.C index 489ea50e..9556ff51 100644 --- a/src/utils/ComplexTypes.C +++ b/src/utils/ComplexTypes.C @@ -37,8 +37,11 @@ absoluteFuzzyEqual(const std::complex & var1, #include "RankThreeTensorImplementation.h" #include "RankFourTensorImplementation.h" -template class VectorValue>; +namespace libMesh +{ +template class VectorValue; +} -template class RankTwoTensorTempl>; -template class RankThreeTensorTempl>; -template class RankFourTensorTempl>; +template class RankTwoTensorTempl; +template class RankThreeTensorTempl; +template class RankFourTensorTempl; diff --git a/src/utils/FFTData.C b/src/utils/FFTData.C new file mode 100644 index 00000000..0f162069 --- /dev/null +++ b/src/utils/FFTData.C @@ -0,0 +1,193 @@ +/**********************************************************************/ +/* DO NOT MODIFY THIS HEADER */ +/* MAGPIE - Mesoscale Atomistic Glue Program for Integrated Execution */ +/* */ +/* Copyright 2017 Battelle Energy Alliance, LLC */ +/* ALL RIGHTS RESERVED */ +/**********************************************************************/ + +#include "FFTData.h" + +template +FFTData & +FFTData::operator+=(FFTData const & rhs) +{ + for (std::size_t i = 0; i < _buffer.size(); ++i) + _buffer[i] += rhs[i]; + return *this; +} + +template +FFTData & +FFTData::operator-=(FFTData const & rhs) +{ + for (std::size_t i = 0; i < _buffer.size(); ++i) + _buffer[i] -= rhs[i]; + return *this; +} + +template +FFTData & +FFTData::operator*=(FFTData::type> const & rhs) +{ + for (std::size_t i = 0; i < _buffer.size(); ++i) + _buffer[i] *= rhs[i]; + return *this; +} + +template +FFTData & +FFTData::operator/=(FFTData::type> const & rhs) +{ + for (std::size_t i = 0; i < _buffer.size(); ++i) + _buffer[i] /= rhs[i]; + return *this; +} + +template +FFTData & +FFTData::operator*=(Real rhs) +{ + for (std::size_t i = 0; i < _buffer.size(); ++i) + _buffer[i] *= rhs; + return *this; +} + +template +FFTData & +FFTData::operator/=(Real rhs) +{ + const Real reciprocal = 1 / rhs; + for (std::size_t i = 0; i < _buffer.size(); ++i) + _buffer[i] *= reciprocal; + return *this; +} + +template +FFTData & +FFTData::operator=(FFTData const & rhs) +{ + mooseAssert(size() == rhs.size(), "Buffers need to have identical size!"); + _buffer = rhs._buffer; + return *this; +} + +template <> +void * +FFTData::start(std::size_t i) +{ + return reinterpret_cast(&_buffer[i]); +} +template <> +void * +FFTData::start(std::size_t i) +{ + return reinterpret_cast(&_buffer[i]); +} + +template <> +void * +FFTData::start(std::size_t i) +{ + return reinterpret_cast(&_buffer[i](0)); +} +template <> +void * +FFTData::start(std::size_t i) +{ + return reinterpret_cast(&_buffer[i](0)); +} + +template <> +void * +FFTData::start(std::size_t i) +{ + return reinterpret_cast(&_buffer[i](0, 0)); +} +template <> +void * +FFTData::start(std::size_t i) +{ + return reinterpret_cast(&_buffer[i](0, 0)); +} + +template <> +void * +FFTData::start(std::size_t i) +{ + return reinterpret_cast(&_buffer[i](0, 0, 0)); +} +template <> +void * +FFTData::start(std::size_t i) +{ + return reinterpret_cast(&_buffer[i](0, 0, 0)); +} + +template <> +void * +FFTData::start(std::size_t i) +{ + return reinterpret_cast(&_buffer[i](0, 0, 0, 0)); +} +template <> +void * +FFTData::start(std::size_t i) +{ + return reinterpret_cast(&_buffer[i](0, 0, 0, 0)); +} + +template +std::size_t +FFTData::howMany() const +{ + mooseError("Only call howMany() on the real space buffer!"); +} + +template <> +std::size_t +FFTData::howMany() const +{ + return 1; +} + +template <> +std::size_t +FFTData::howMany() const +{ + return LIBMESH_DIM; +} + +template <> +std::size_t +FFTData::howMany() const +{ + return LIBMESH_DIM * LIBMESH_DIM; +} + +template <> +std::size_t +FFTData::howMany() const +{ + return LIBMESH_DIM * LIBMESH_DIM * LIBMESH_DIM; +} + +template <> +std::size_t +FFTData::howMany() const +{ + return LIBMESH_DIM * LIBMESH_DIM * LIBMESH_DIM * LIBMESH_DIM; +} + +// explicit instantiations +template class FFTData; +template class FFTData; +template class FFTData; +template class FFTData; +template class FFTData; + +template class FFTData; +template class FFTData; +template class FFTData; +template class FFTData; +template class FFTData; diff --git a/src/variables/MooseFFTVariable.C b/src/variables/MooseFFTVariable.C index eedf1db4..a2230891 100644 --- a/src/variables/MooseFFTVariable.C +++ b/src/variables/MooseFFTVariable.C @@ -11,7 +11,7 @@ InputParameters MooseFFTVariable::validParams() { - InputParameters params = MooseVariableFEBase::validParams(); + auto params = MooseVariableFEBase::validParams(); return params; }