Skip to content

Commit

Permalink
WIP: add implicit div calculation without boundary contribution
Browse files Browse the repository at this point in the history
  • Loading branch information
HenningScheufler committed Jan 26, 2025
1 parent 99ea680 commit a7177c8
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
11 changes: 11 additions & 0 deletions include/NeoFOAM/finiteVolume/cellCentred/operators/divOperator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma once

#include "NeoFOAM/fields/field.hpp"
#include "NeoFOAM/linearAlgebra.hpp"
#include "NeoFOAM/core/executor/executor.hpp"
#include "NeoFOAM/core/input.hpp"
#include "NeoFOAM/dsl/operator.hpp"
Expand Down Expand Up @@ -45,6 +46,11 @@ class DivOperatorFactory :
div(VolumeField<scalar>& divPhi, const SurfaceField<scalar>& faceFlux, VolumeField<scalar>& phi
) = 0;

virtual void
div(la::LinearSystem<scalar, localIdx>& ls,
const SurfaceField<scalar>& faceFlux,
VolumeField<scalar>& phi) = 0;

virtual void
div(Field<scalar>& divPhi, const SurfaceField<scalar>& faceFlux, VolumeField<scalar>& phi) = 0;

Expand Down Expand Up @@ -112,6 +118,11 @@ class DivOperator : public dsl::OperatorMixin<VolumeField<scalar>>

void div(Field<scalar>& divPhi) { divOperatorStrategy_->div(divPhi, faceFlux_, getField()); }

void div(la::LinearSystem<scalar, localIdx>& ls)
{
divOperatorStrategy_->div(ls, faceFlux_, getField());
};

void div(VolumeField<scalar>& divPhi)
{
divOperatorStrategy_->div(divPhi, faceFlux_, getField());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "NeoFOAM/mesh/unstructured.hpp"
#include "NeoFOAM/finiteVolume/cellCentred/operators/divOperator.hpp"
#include "NeoFOAM/finiteVolume/cellCentred/interpolation/surfaceInterpolation.hpp"
#include "NeoFOAM/finiteVolume/cellCentred/operators/fvccSparsityPattern.hpp"

namespace NeoFOAM::finiteVolume::cellCentred
{
Expand All @@ -28,6 +29,11 @@ class GaussGreenDiv : public DivOperatorFactory::Register<GaussGreenDiv>
div(VolumeField<scalar>& divPhi, const SurfaceField<scalar>& faceFlux, VolumeField<scalar>& phi
) override;

void
div(la::LinearSystem<scalar, localIdx>& ls,
const SurfaceField<scalar>& faceFlux,
VolumeField<scalar>& phi) override;

void
div(Field<scalar>& divPhi, const SurfaceField<scalar>& faceFlux, VolumeField<scalar>& phi
) override;
Expand All @@ -40,6 +46,7 @@ class GaussGreenDiv : public DivOperatorFactory::Register<GaussGreenDiv>
private:

SurfaceInterpolation surfaceInterpolation_;
const std::shared_ptr<SparsityPattern> sparsityPattern_;
};

} // namespace NeoFOAM
50 changes: 49 additions & 1 deletion src/finiteVolume/cellCentred/operators/gaussGreenDiv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ GaussGreenDiv::GaussGreenDiv(
const Executor& exec, const UnstructuredMesh& mesh, const Input& inputs
)
: DivOperatorFactory::Register<GaussGreenDiv>(exec, mesh),
surfaceInterpolation_(exec, mesh, inputs) {};
surfaceInterpolation_(exec, mesh, inputs),
sparsityPattern_(SparsityPattern::readOrCreate(mesh)) {};

void GaussGreenDiv::div(
VolumeField<scalar>& divPhi, const SurfaceField<scalar>& faceFlux, VolumeField<scalar>& phi
Expand All @@ -109,6 +110,53 @@ void GaussGreenDiv::div(
computeDiv(faceFlux, phi, surfaceInterpolation_, divPhi);
};

void GaussGreenDiv::div(
la::LinearSystem<scalar, localIdx>& ls,
const SurfaceField<scalar>& faceFlux,
VolumeField<scalar>& phi
)
{
const UnstructuredMesh& mesh = phi.mesh();
const std::size_t nInternalFaces = mesh.nInternalFaces();
const auto exec = phi.exec();
const auto [sFaceFlux, owner, neighbour, diagOffs, ownOffs, neiOffs] = spans(
faceFlux.internalField(),
mesh.faceOwner(),
mesh.faceNeighbour(),
sparsityPattern_->diagOffset(),
sparsityPattern_->ownerOffset(),
sparsityPattern_->neighbourOffset()
);
const auto rowPtrs = ls.matrix().rowPtrs();
const auto colIdxs = ls.matrix().colIdxs();
const auto values = ls.matrix().values();

parallelFor(
exec,
{0, nInternalFaces},
KOKKOS_LAMBDA(const size_t facei) {
scalar flux = sFaceFlux[facei];
scalar weight = 0.5;
std::size_t own = static_cast<std::size_t>(owner[facei]);
std::size_t nei = static_cast<std::size_t>(neighbour[facei]);

// lower triangular part

// add neighbour contribution
std::size_t rowNeiStart = rowPtrs[nei];
values[rowNeiStart + neiOffs[facei]] += -flux * weight;
Kokkos::atomic_sub(&values[rowNeiStart + diagOffs[nei]], -flux * weight);

// upper triangular part

// add owner contribution
std::size_t rowOwnStart = rowPtrs[own];
values[rowOwnStart + ownOffs[facei]] += flux * (1 - weight);
Kokkos::atomic_sub(&values[rowOwnStart + diagOffs[own]], flux * (1 - weight));
}
);
};

void GaussGreenDiv::div(
Field<scalar>& divPhi, const SurfaceField<scalar>& faceFlux, VolumeField<scalar>& phi
)
Expand Down

0 comments on commit a7177c8

Please sign in to comment.