Fields¶
Overview¶
Warning
The API of the classes probably will change in the future as currently parallelization is not supported.
NeoFOAM implements several field classes:
Field<ValueType>
the basic GPU capable container class supporting algebraic operationsBoundaryFields<ValueType>
A GPU friendly datastructure storing boundary data.DomainField<ValueType>
The combination of an internal field and its corresponding boundary data.
Besides these container like field classes several finite volume specific field classes are implemented. The corresponding classes are:
GeometricFieldMixin<ValueType>
Mixin class combining aDomainField
and the corresponding mesh.VolumeField<ValueType>
Uses the GeometricFieldMixin and implements finite volume specific members, including the notion of concrete boundary condiditonsSurfaceField<ValueType>
The surface field equivalent toVolumeField
The Field<ValueType> class¶
The Field class is the basic container class and is the central elements for implementing a platform portable CFD framework. Fields should allow to perform basic algebraic operations such as binary operations like the addition or subtraction of two fields, or scalar operations like the multiplication of a field with a scalar.
In the following, some implementation details of the field operations are detailed using the additions operator as an example. The block of code below shows an example implementation of the addition operator.
[[nodiscard]] Field<T> operator+(const Field<T>& rhs)
{
Field<T> result(exec_, size_);
result = *this;
add(result, rhs);
return result;
}
Besides creating a temporary for the result it mainly calls the free standing add
function which is implemented in include/NeoFOAM/field/fieldFreeFunctions.hpp
.
This, in turn, dispatches to the fieldBinaryOp
function, passing the actual kernel as lambda.
The fieldBinaryOp
is implemented using our parallelFor implementations which ultimately dispatch to the Kokkos::parallel_for
function, see Kokkos documentation for more details.
template<typename ValueType>
void add(Field<ValueType>& a, const Field<std::type_identity_t<ValueType>>& b)
{
detail::fieldBinaryOp(
a, b, KOKKOS_LAMBDA(ValueType va, ValueType vb) { return va + vb; }
);
}
A simplified version of the parallelFor
function is shown below.
The code snippet highlights another important aspect, the executor.
The executor defines the Kokkos::RangePolicy
, see Kokkos Programming Model.
Besides defining the RangePolicy, the executor also holds functions for allocating and deallocationg memory.
See our documentation for more details on the executor model.
Further Details.
Cell Centred Specific Fields¶
Within in the finiteVolume/cellCentred
folder and the namespace
NeoFOAM::finiteVolume::cellCentred
two specific field types, namely the VolumeField
and the SurfaceField
are implemented.
Both derive from the GeometricFieldMixin
a mixin class which handles that all derived fields contain geometric information via the mesh data member and field specific data via the DomainField
data member.
DomainField
acts as the fundamental data container within this structure, offering both read and write to the internalField
and boundaryFields
data structure holding actual boundary data.
The VolumeField
and the SurfaceField
hold a vector of boundary conditions implemented in finiteVolume/cellCentred/boundary
and a correctBoundaryConditions
member function that updates the field’s boundary condition.
Functionally, the VolumeField
and the SurfaceField
classes are comparable to OpenFOAM classes such as volScalarField
, volVectorField
, and volTensorField
or surfaceScalarField
, surfaceVectorField
, and surfaceTensorField
respectively.
A difference in the SurfaceField implementation is that the internalField
also contains the boundary values, so no branches (if) are required when iterating over all cell faces.
Thus the size of the internalField
in NeoFOAM differs from that of OpenFOAM.
Further details VolumeField and ScalarField.