Skip to content

Commit

Permalink
Compute gradient (idaholab#401)
Browse files Browse the repository at this point in the history
  • Loading branch information
dschwen authored and recuero committed Apr 29, 2020
1 parent 27f5b84 commit 960d1ea
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 8 deletions.
54 changes: 52 additions & 2 deletions examples/spectral.i
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@
function = 'cos(x/100*2*pi*4)*cos(y/100*2*pi*2)'
[../]
[../]


[./u_aux]
order = CONSTANT
family = MONOMIAL
[./InitialCondition]
type = SmoothCircleIC
x1 = 50
y1 = 50
radius = 30
int_width = 20
invalue = 1
outvalue = 0
[../]
[../]
[./grad_u0_aux]
order = CONSTANT
family = MONOMIAL
[../]
[./grad_u1_aux]
order = CONSTANT
family = MONOMIAL
[../]
[]

[Materials]
Expand All @@ -66,8 +89,13 @@
moose_variable = 'R0_aux R1_aux R2_aux'
[../]

# Solver
# ...
[./u]
type = RealFFTWBuffer
moose_variable = u_aux
[../]
[./grad_u]
type = RealVectorValueFFTWBuffer
[../]
[]

[AuxKernels]
Expand Down Expand Up @@ -99,6 +127,28 @@
component = 2
execute_on = FINAL
[../]

[./u_aux]
type = FFTBufferAux
variable = u_aux
fft_buffer = u
execute_on = FINAL
[../]

[./grad_u0_aux]
type = FFTBufferAux
variable = grad_u0_aux
fft_buffer = grad_u
component = 0
execute_on = FINAL
[../]
[./grad_u1_aux]
type = FFTBufferAux
variable = grad_u1_aux
fft_buffer = grad_u
component = 1
execute_on = FINAL
[../]
[]

[Executioner]
Expand Down
4 changes: 4 additions & 0 deletions include/executioners/SpectralExecutionerBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@ class SpectralExecutionerBase : public Executioner
virtual bool lastSolveConverged() const override { return true; }

protected:
/// obtain a non-const reference to an FFT buffer
template <typename T>
FFTBufferBase<T> & getFFTBuffer(const std::string & name);

/// multiply a scalar buffer by its corresponding k-vector field int a vector buffer
void kVectorMultiply(const FFTBufferBase<Real> & in, FFTBufferBase<RealVectorValue> & out) const;

Real _system_time;
int & _time_step;
Real & _time;
Expand Down
32 changes: 30 additions & 2 deletions include/userobjects/FFTBufferBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,31 @@ class FFTBufferBase : public ElementUserObject
T & operator()(const Point & p);
///@}

///@{ convenience math operators
FFTBufferBase<T> & operator+=(FFTBufferBase<T> const & rhs);
FFTBufferBase<T> & operator-=(FFTBufferBase<T> const & rhs);
FFTBufferBase<T> & operator*=(FFTBufferBase<Real> const & rhs);
FFTBufferBase<T> & operator/=(FFTBufferBase<Real> const & rhs);
FFTBufferBase<T> & operator*=(Real rhs);
FFTBufferBase<T> & operator/=(Real rhs);
///@}

/// return the number of grid cells along each dimension without padding
const std::vector<int> & grid() const { return _grid; }

/// return the number of proper grid cells without padding
const std::size_t & size() const { return _grid_size; }

/// return the buffer dimension
const unsigned int & dim() const { return _dim; }

/// return the buffer dimension
const std::vector<Real> & kTable(unsigned int d) const
{
mooseAssert(d < _dim, "invalid kTable component");
return _k_table[d];
}

protected:
/// get the addres of the first data element of the ith object in the bufefr
Real * start(std::size_t i);
Expand All @@ -77,9 +102,9 @@ class FFTBufferBase : public ElementUserObject
/// FFT grid cell volume
Real _cell_volume;

///@{ FFT data buffer
///@{ FFT data buffer and unpadded number of grid cells
std::vector<T> _buffer;
std::size_t _buffer_size;
std::size_t _grid_size;
///@}

/// pointer to the start of the data
Expand All @@ -91,6 +116,9 @@ class FFTBufferBase : public ElementUserObject
/// optional moose sister variabe (to obtain IC from)
std::vector<const VariableValue *> _moose_variable;

/// pretabulated k-vector components
std::vector<std::vector<Real>> _k_table;

/// cache the howMany value
const std::size_t _how_many;
};
78 changes: 77 additions & 1 deletion src/executioners/SpectralExecutionerBase.C
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,99 @@ SpectralExecutionerBase::execute()
_fe_problem.outputStep(EXEC_INITIAL);
_fe_problem.advanceState();

// back and forth test
auto & c = getFFTBuffer<Real>("c");
c.forward();

auto & R = getFFTBuffer<RealVectorValue>("R");
R.forward();

// gradient test
auto & u = getFFTBuffer<Real>("u");
u.forward();
auto & grad_u = getFFTBuffer<RealVectorValue>("grad_u");
kVectorMultiply(u, grad_u);

_time_step = 1;
_fe_problem.execute(EXEC_FINAL);
_time = _time_step;
_fe_problem.outputStep(EXEC_FINAL);
_fe_problem.advanceState();

// back and forth test
c.backward();
R.backward();
R /= 10000.0;
c /= 10000.0;

// gradient test
u.backward();
grad_u.backward();
u /= 10000.0;
grad_u /= 100.0;

_time_step = 2;
_fe_problem.execute(EXEC_FINAL);
_time = _time_step;
_fe_problem.outputStep(EXEC_FINAL);
}

void
SpectralExecutionerBase::kVectorMultiply(const FFTBufferBase<Real> & in,
FFTBufferBase<RealVectorValue> & out) const
{
mooseAssert(in.size() == out.size(), "Buffer sizes must be equal");
mooseAssert(in.dim() == out.dim(), "Buffer dimensions must be equal");

const auto & grid = in.grid();
switch (in.dim())
{
case 1:
{
const int ni = grid[0];
for (int i = 0; i < ni; ++i)
{
out[i](0) = in[i] * i;
out[i](1) = 0.0;
out[i](2) = 0.0;
}
return;
}

case 2:
{
std::size_t index = 0;
const int ni = grid[0];
const int nj = grid[1];
for (int i = 0; i < ni; ++i)
for (int j = 0; j < nj; ++j)
{
out[index](0) = in[index] * i;
out[index](1) = in[index] * j;
out[index](2) = 0.0;
index++;
}
return;
}

case 3:
{
std::size_t index = 0;
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)
{
out[index](0) = in[index] * i;
out[index](1) = in[index] * j;
out[index](2) = in[index] * k;
index++;
}
return;
}

default:
mooseError("Invalid buffer dimension");
}
}
71 changes: 68 additions & 3 deletions src/userobjects/FFTBufferBase.C
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ FFTBufferBase<T>::FFTBufferBase(const InputParameters & parameters)
_mesh(_subproblem.mesh()),
_dim(_mesh.dimension()),
_cell_volume(1.0),
_buffer_size(1),
_grid_size(1),
_moose_variable(coupledComponents("moose_variable")),
_k_table(_dim),
_how_many(howMany())
{
// make sure Real is double
Expand Down Expand Up @@ -98,17 +99,26 @@ FFTBufferBase<T>::FFTBufferBase(const InputParameters & parameters)
}

// get mesh extents and calculate space required and estimate spectrum bins
std::size_t buffer_size = 1;
for (unsigned int i = 0; i < _dim; ++i)
{
_min_corner(i) = _mesh.getMinInDimension(i);
_max_corner(i) = _mesh.getMaxInDimension(i);
_box_size(i) = _max_corner(i) - _min_corner(i);
_cell_volume *= _box_size(i) / _grid[i];

// unpadded size (number of physical grid cells)
_grid_size *= _grid[i];

// last direction needs to be padded for in-place transforms
_buffer_size *= (i == _dim - 1) ? ((_grid[i] >> 1) + 1) << 1 : _grid[i];
buffer_size *= (i == _dim - 1) ? ((_grid[i] >> 1) + 1) << 1 : _grid[i];

// precompute kvector components for current direction
_k_table[i].resize(_grid[i]);
for (int j = 0; j < _grid[i]; ++j)
_k_table[i][j] = (j * 2 > _grid[i] ? Real(_grid[i] - j) : Real(j)) / _box_size(i);
}
_buffer.resize(_buffer_size);
_buffer.resize(buffer_size);

// compute stride and start pointer
_start = reinterpret_cast<Real *>(start(0));
Expand Down Expand Up @@ -153,6 +163,61 @@ FFTBufferBase<T>::operator()(const Point & p)
return _buffer[a];
}

template <typename T>
FFTBufferBase<T> &
FFTBufferBase<T>::operator+=(FFTBufferBase<T> const & rhs)
{
for (std::size_t i = 0; i < _grid_size; ++i)
_buffer[i] += rhs[i];
return *this;
}

template <typename T>
FFTBufferBase<T> &
FFTBufferBase<T>::operator-=(FFTBufferBase<T> const & rhs)
{
for (std::size_t i = 0; i < _grid_size; ++i)
_buffer[i] -= rhs[i];
return *this;
}

template <typename T>
FFTBufferBase<T> &
FFTBufferBase<T>::operator*=(FFTBufferBase<Real> const & rhs)
{
for (std::size_t i = 0; i < _grid_size; ++i)
_buffer[i] *= rhs[i];
return *this;
}

template <typename T>
FFTBufferBase<T> &
FFTBufferBase<T>::operator/=(FFTBufferBase<Real> const & rhs)
{
for (std::size_t i = 0; i < _grid_size; ++i)
_buffer[i] /= rhs[i];
return *this;
}

template <typename T>
FFTBufferBase<T> &
FFTBufferBase<T>::operator*=(Real rhs)
{
for (std::size_t i = 0; i < _grid_size; ++i)
_buffer[i] *= rhs;
return *this;
}

template <typename T>
FFTBufferBase<T> &
FFTBufferBase<T>::operator/=(Real rhs)
{
const Real reciprocal = 1 / rhs;
for (std::size_t i = 0; i < _grid_size; ++i)
_buffer[i] *= reciprocal;
return *this;
}

template <>
Real *
FFTBufferBase<Real>::start(std::size_t i)
Expand Down

0 comments on commit 960d1ea

Please sign in to comment.