Case Study: The Gauss Green Div KernelΒΆ
This section explains discusses how the Gauss Green Div Kernel is implemented. The class is implemented in the following files:
include/NeoFOAM/finiteVolume/cellCentred/operators/gaussGreenDiv.hppsrc/finiteVolume/cellCentred/operators/gaussGreenDiv.hpptest/finiteVolume/cellCentred/operators/gaussGreenDiv.hpp
The gaussGreenDiv class represents the following term \(\int \nabla \cdot \phi dV\) and is a particular implementation of the dsl::explicit::div operator.
Hence, in order to make the implementation selectable at runtime we let the GaussGreenDiv class derive from DivOperatorFactory::Register<GaussGreenDiv> and implement the static name function, (see also registerClass).
The actual implementation of the operator can be found in the gaussGreenDiv.cpp file.
The GaussGreenDiv::div member calls a free standing function computeDiv with the correct arguments.
In NeoFOAM it is a common pattern to use free standing functions since they are easier to test and communicate all dependencies explicitly via the function arguments.
The discretized version of the divergence term can be written as
and the internal field part is implemented in OpenFOAM as
forAll(owner, facei)
{
const GradType Sfssf = Sf[facei]*issf[facei];
igGrad[owner[facei]] += Sfssf;
igGrad[neighbour[facei]] -= Sfssf;
}
the corresponding NeoFOAM version is implemented as
parallelFor(
exec,
{0, nInternalFaces},
KOKKOS_LAMBDA(const size_t i) {
scalar flux = surfFaceFlux[i]*surfPhif[i];
threadsafe_add(&surfDivPhi[static_cast<size_t>(surfOwner[i])], flux);
threadsafe_sub(&surfDivPhi[static_cast<size_t>(surfNeighbour[i])], flux);
}
);
Here, the following changes have been applied
replace the
forAllmacro with theNeoFOAM::parallelFor(see parallelFor.) function which takes the executor, the range, and the loop body as arguments.calls to
+=and-=are replaced by thethreadsafe_addandthreadsafe_subfunction which takes the lhs and rhs as arguments.