From 1ed787aea1c48deb08b35d651e7c817a1ba9cd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=BChlh=C3=A4u=C3=9Fer?= <43962524+thesamriel@users.noreply.github.com> Date: Wed, 24 Jan 2024 08:42:41 +0100 Subject: [PATCH] Add phase variable and flux coupling for interFOAM in the FF module (#308) --- FF/Alpha.C | 116 ++++++++++++++++++ FF/Alpha.H | 43 +++++++ FF/AlphaGradient.C | 73 +++++++++++ FF/AlphaGradient.H | 42 +++++++ .../coupledPressureFvPatchField.C | 2 +- .../coupledVelocityFvPatchField.C | 2 +- FF/FF.C | 46 +++++++ FF/FF.H | 6 + FF/ModuleFF.C | 3 + FF/Phi.C | 59 +++++++++ FF/Phi.H | 42 +++++++ changelog-entries/308.md | 1 + docs/README.md | 4 + docs/config.md | 12 +- 14 files changed, 448 insertions(+), 3 deletions(-) create mode 100644 FF/Alpha.C create mode 100644 FF/Alpha.H create mode 100644 FF/AlphaGradient.C create mode 100644 FF/AlphaGradient.H create mode 100644 FF/Phi.C create mode 100644 FF/Phi.H create mode 100644 changelog-entries/308.md diff --git a/FF/Alpha.C b/FF/Alpha.C new file mode 100644 index 00000000..f11d9c2e --- /dev/null +++ b/FF/Alpha.C @@ -0,0 +1,116 @@ +#include "Alpha.H" + +using namespace Foam; + +preciceAdapter::FF::Alpha::Alpha( + const Foam::fvMesh& mesh, + const std::string nameAlpha) +: Alpha_( + const_cast( + &mesh.lookupObject(nameAlpha))) +{ + dataType_ = scalar; +} + +std::size_t preciceAdapter::FF::Alpha::write(double* buffer, bool meshConnectivity, const unsigned int dim) +{ + int bufferIndex = 0; + + if (this->locationType_ == LocationType::volumeCenters) + { + if (cellSetNames_.empty()) + { + for (const auto& cell : Alpha_->internalField()) + { + buffer[bufferIndex++] = cell; + } + } + else + { + for (const auto& cellSetName : cellSetNames_) + { + cellSet overlapRegion(Alpha_->mesh(), cellSetName); + const labelList& cells = overlapRegion.toc(); + + for (const auto& currentCell : cells) + { + // Copy the alpha valus into the buffer + buffer[bufferIndex++] = Alpha_->internalField()[currentCell]; + } + } + } + } + + // For every boundary patch of the interface + for (uint j = 0; j < patchIDs_.size(); j++) + { + int patchID = patchIDs_.at(j); + + // For every cell of the patch + forAll(Alpha_->boundaryFieldRef()[patchID], i) + { + // Copy the Alpha into the buffer + buffer[bufferIndex++] = + Alpha_->boundaryFieldRef()[patchID][i]; + } + } + return bufferIndex; +} + +void preciceAdapter::FF::Alpha::read(double* buffer, const unsigned int dim) +{ + int bufferIndex = 0; + + if (this->locationType_ == LocationType::volumeCenters) + { + if (cellSetNames_.empty()) + { + for (auto& cell : Alpha_->ref()) + { + cell = buffer[bufferIndex++]; + } + } + else + { + for (const auto& cellSetName : cellSetNames_) + { + cellSet overlapRegion(Alpha_->mesh(), cellSetName); + const labelList& cells = overlapRegion.toc(); + + for (const auto& currentCell : cells) + { + // Copy the pressure into the buffer + Alpha_->ref()[currentCell] = buffer[bufferIndex++]; + } + } + } + } + + // For every boundary patch of the interface + for (uint j = 0; j < patchIDs_.size(); j++) + { + int patchID = patchIDs_.at(j); + // For every cell of the patch + forAll(Alpha_->boundaryFieldRef()[patchID], i) + { + Alpha_->boundaryFieldRef()[patchID][i] = buffer[bufferIndex++]; + } + } +} + +bool preciceAdapter::FF::Alpha::isLocationTypeSupported(const bool meshConnectivity) const +{ + if (meshConnectivity) + { + return (this->locationType_ == LocationType::faceCenters); + } + else + { + return (this->locationType_ == LocationType::faceCenters || this->locationType_ == LocationType::volumeCenters); + } +} + +std::string preciceAdapter::FF::Alpha::getDataName() const +{ + return "Alpha"; +} diff --git a/FF/Alpha.H b/FF/Alpha.H new file mode 100644 index 00000000..7e5feb99 --- /dev/null +++ b/FF/Alpha.H @@ -0,0 +1,43 @@ +#ifndef FF_ALPHA_H +#define FF_ALPHA_H + +#include "CouplingDataUser.H" + +#include "fvCFD.H" +#include "cellSet.H" + +namespace preciceAdapter +{ +namespace FF +{ + +//- Class that writes and reads Alpha +class Alpha : public CouplingDataUser +{ + +private: + //- Alpha field + Foam::volScalarField* Alpha_; + +public: + //- Constructor + Alpha( + const Foam::fvMesh& mesh, + const std::string nameAlpha); + + //- Write the Alpha values into the buffer + std::size_t write(double* buffer, bool meshConnectivity, const unsigned int dim); + + //- Read the Alpha values from the buffer + void read(double* buffer, const unsigned int dim); + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; +}; + +} +} + +#endif diff --git a/FF/AlphaGradient.C b/FF/AlphaGradient.C new file mode 100644 index 00000000..00260801 --- /dev/null +++ b/FF/AlphaGradient.C @@ -0,0 +1,73 @@ +#include "AlphaGradient.H" +#include "mixedFvPatchFields.H" + +using namespace Foam; + +preciceAdapter::FF::AlphaGradient::AlphaGradient( + const Foam::fvMesh& mesh, + const std::string nameAlpha) +: Alpha_( + const_cast( + &mesh.lookupObject(nameAlpha))) +{ + dataType_ = scalar; +} + +std::size_t preciceAdapter::FF::AlphaGradient::write(double* buffer, bool meshConnectivity, const unsigned int dim) +{ + int bufferIndex = 0; + + // For every boundary patch of the interface + for (uint j = 0; j < patchIDs_.size(); j++) + { + int patchID = patchIDs_.at(j); + + // Get the Alpha gradient boundary patch + const scalarField gradientPatch((Alpha_->boundaryFieldRef()[patchID]) + .snGrad()); + + // For every cell of the patch + forAll(gradientPatch, i) + { + // Copy the Alpha gradient into the buffer + buffer[bufferIndex++] = + -gradientPatch[i]; + } + } + return bufferIndex; +} + +void preciceAdapter::FF::AlphaGradient::read(double* buffer, const unsigned int dim) +{ + int bufferIndex = 0; + + // For every boundary patch of the interface + for (uint j = 0; j < patchIDs_.size(); j++) + { + int patchID = patchIDs_.at(j); + + // Get the Alpha gradient boundary patch + scalarField& gradientPatch = + refCast( + Alpha_->boundaryFieldRef()[patchID]) + .gradient(); + + // For every cell of the patch + forAll(gradientPatch, i) + { + // Set the Alpha gradient as the buffer value + gradientPatch[i] = + buffer[bufferIndex++]; + } + } +} + +bool preciceAdapter::FF::AlphaGradient::isLocationTypeSupported(const bool meshConnectivity) const +{ + return (this->locationType_ == LocationType::faceCenters); +} + +std::string preciceAdapter::FF::AlphaGradient::getDataName() const +{ + return "AlphaGradient"; +} diff --git a/FF/AlphaGradient.H b/FF/AlphaGradient.H new file mode 100644 index 00000000..b538f009 --- /dev/null +++ b/FF/AlphaGradient.H @@ -0,0 +1,42 @@ +#ifndef FF_ALPHA_GRADIENT_H +#define FF_ALPHA_GRADIENT_H + +#include "CouplingDataUser.H" + +#include "fvCFD.H" + +namespace preciceAdapter +{ +namespace FF +{ + +//- Class that writes and reads Alpha gradient +class AlphaGradient : public CouplingDataUser +{ + +private: + //- Alpha field + Foam::volScalarField* Alpha_; + +public: + //- Constructor + AlphaGradient( + const Foam::fvMesh& mesh, + const std::string nameAlpha); + + //- Write the Alpha gradient values into the buffer + std::size_t write(double* buffer, bool meshConnectivity, const unsigned int dim); + + //- Read the Alpha gradient values from the buffer + void read(double* buffer, const unsigned int dim); + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; +}; + +} +} + +#endif diff --git a/FF/BoundaryConditions/coupledPressure/coupledPressureFvPatchField.C b/FF/BoundaryConditions/coupledPressure/coupledPressureFvPatchField.C index 28d61e8a..320a6ca2 100644 --- a/FF/BoundaryConditions/coupledPressure/coupledPressureFvPatchField.C +++ b/FF/BoundaryConditions/coupledPressure/coupledPressureFvPatchField.C @@ -178,4 +178,4 @@ namespace Foam makePatchTypeField( fixedFluxExtrapolatedPressureFvPatchScalarField, coupledPressureFvPatchField); -} \ No newline at end of file +} diff --git a/FF/BoundaryConditions/coupledVelocity/coupledVelocityFvPatchField.C b/FF/BoundaryConditions/coupledVelocity/coupledVelocityFvPatchField.C index 3c51fb92..1546477c 100644 --- a/FF/BoundaryConditions/coupledVelocity/coupledVelocityFvPatchField.C +++ b/FF/BoundaryConditions/coupledVelocity/coupledVelocityFvPatchField.C @@ -175,4 +175,4 @@ namespace Foam makePatchTypeField( fvPatchVectorField, coupledVelocityFvPatchField); -} \ No newline at end of file +} diff --git a/FF/FF.C b/FF/FF.C index 15b2e53b..2c2144ee 100644 --- a/FF/FF.C +++ b/FF/FF.C @@ -63,6 +63,10 @@ bool preciceAdapter::FF::FluidFluid::readConfig(const IOdictionary& adapterConfi nameT_ = FFdict.lookupOrDefault("nameT", "T"); DEBUG(adapterInfo(" temperature field name : " + nameT_)); + // Read the name of the phase variable field (if different) + nameAlpha_ = FFdict.lookupOrDefault("nameAlpha", "alpha"); + DEBUG(adapterInfo(" phase variable (alpha) field name : " + nameAlpha_)); + // Read the name of the face flux field (if different) namePhi_ = FFdict.lookupOrDefault("namePhi", "phi"); DEBUG(adapterInfo(" face flux field name : " + namePhi_)); @@ -155,6 +159,27 @@ bool preciceAdapter::FF::FluidFluid::addWriters(std::string dataName, Interface* new Temperature(mesh_, nameT_)); DEBUG(adapterInfo("Added writer: Flow Temperature.")); } + else if (dataName.find("AlphaGradient") == 0) + { + interface->addCouplingDataWriter( + dataName, + new AlphaGradient(mesh_, nameAlpha_)); + DEBUG(adapterInfo("Added writer: Alpha Gradient.")); + } + else if (dataName.find("Alpha") == 0) + { + interface->addCouplingDataWriter( + dataName, + new Alpha(mesh_, nameAlpha_)); + DEBUG(adapterInfo("Added writer: Alpha.")); + } + else if (dataName.find("Phi") == 0) + { + interface->addCouplingDataWriter( + dataName, + new Phi(mesh_, namePhi_)); + DEBUG(adapterInfo("Added writer: Phi.")); + } else { found = false; @@ -215,6 +240,27 @@ bool preciceAdapter::FF::FluidFluid::addReaders(std::string dataName, Interface* new Temperature(mesh_, nameT_)); DEBUG(adapterInfo("Added reader: Flow Temperature.")); } + else if (dataName.find("AlphaGradient") == 0) + { + interface->addCouplingDataReader( + dataName, + new AlphaGradient(mesh_, nameAlpha_)); + DEBUG(adapterInfo("Added reader: Alpha Gradient.")); + } + else if (dataName.find("Alpha") == 0) + { + interface->addCouplingDataReader( + dataName, + new Alpha(mesh_, nameAlpha_)); + DEBUG(adapterInfo("Added reader: Alpha.")); + } + else if (dataName.find("Phi") == 0) + { + interface->addCouplingDataReader( + dataName, + new Phi(mesh_, namePhi_)); + DEBUG(adapterInfo("Added reader: Phi.")); + } else { found = false; diff --git a/FF/FF.H b/FF/FF.H index fbcee8cb..77629442 100644 --- a/FF/FF.H +++ b/FF/FF.H @@ -6,9 +6,12 @@ #include "FF/Velocity.H" #include "FF/Pressure.H" #include "FF/Temperature.H" +#include "FF/Alpha.H" #include "FF/PressureGradient.H" #include "FF/VelocityGradient.H" #include "FF/TemperatureGradient.H" +#include "FF/AlphaGradient.H" +#include "FF/Phi.H" #include "fvCFD.H" @@ -38,6 +41,9 @@ protected: //- Name of the temperature field std::string nameT_ = "T"; + //- Name of the phase variable (alpha) field + std::string nameAlpha_ = "alpha"; + //- Name of the face flux field std::string namePhi_ = "phi"; diff --git a/FF/ModuleFF.C b/FF/ModuleFF.C index 30465704..21d191ea 100644 --- a/FF/ModuleFF.C +++ b/FF/ModuleFF.C @@ -6,5 +6,8 @@ #include "PressureGradient.C" #include "Temperature.C" #include "TemperatureGradient.C" +#include "Alpha.C" +#include "AlphaGradient.C" +#include "Phi.C" #include "BoundaryConditions/coupledPressure/coupledPressureFvPatchField.C" #include "BoundaryConditions/coupledVelocity/coupledVelocityFvPatchField.C" diff --git a/FF/Phi.C b/FF/Phi.C new file mode 100644 index 00000000..d2001395 --- /dev/null +++ b/FF/Phi.C @@ -0,0 +1,59 @@ +#include "Phi.H" + +using namespace Foam; + +preciceAdapter::FF::Phi::Phi( + const Foam::fvMesh& mesh, + const std::string namePhi) +: phi_( + const_cast( + &mesh.lookupObject(namePhi))) +{ + dataType_ = scalar; +} + +std::size_t preciceAdapter::FF::Phi::write(double* buffer, bool meshConnectivity, const unsigned int dim) +{ + int bufferIndex = 0; + + // For every boundary patch of the interface + for (uint j = 0; j < patchIDs_.size(); j++) + { + int patchID = patchIDs_.at(j); + + // For every cell of the patch + forAll(phi_->boundaryFieldRef()[patchID], i) + { + // Copy the Phi into the buffer + buffer[bufferIndex++] = + phi_->boundaryFieldRef()[patchID][i]; + } + } + return bufferIndex; +} + +void preciceAdapter::FF::Phi::read(double* buffer, const unsigned int dim) +{ + int bufferIndex = 0; + + // For every boundary patch of the interface + for (uint j = 0; j < patchIDs_.size(); j++) + { + int patchID = patchIDs_.at(j); + + forAll(phi_->boundaryFieldRef()[patchID], i) + { + phi_->boundaryFieldRef()[patchID][i] = -buffer[bufferIndex++]; + } + } +} + +bool preciceAdapter::FF::Phi::isLocationTypeSupported(const bool meshConnectivity) const +{ + return (this->locationType_ == LocationType::faceCenters); +} + +std::string preciceAdapter::FF::Phi::getDataName() const +{ + return "Phi"; +} diff --git a/FF/Phi.H b/FF/Phi.H new file mode 100644 index 00000000..0b42c6ad --- /dev/null +++ b/FF/Phi.H @@ -0,0 +1,42 @@ +#ifndef FF_PHI_H +#define FF_PHI_H + +#include "CouplingDataUser.H" + +#include "fvCFD.H" + +namespace preciceAdapter +{ +namespace FF +{ + +//- Class that writes and reads the flux phi +class Phi : public CouplingDataUser +{ + +private: + //- Phi field + Foam::surfaceScalarField* phi_; + +public: + //- Constructor + Phi( + const Foam::fvMesh& mesh, + const std::string namePhi); + + //- Write the Phi values into the buffer + std::size_t write(double* buffer, bool meshConnectivity, const unsigned int dim); + + //- Read the Phi values from the buffer + void read(double* buffer, const unsigned int dim); + + bool isLocationTypeSupported(const bool meshConnectivity) const override; + + //- Get the name of the current data field + std::string getDataName() const override; +}; + +} +} + +#endif diff --git a/changelog-entries/308.md b/changelog-entries/308.md new file mode 100644 index 00000000..5bcda115 --- /dev/null +++ b/changelog-entries/308.md @@ -0,0 +1 @@ +- Added phase variable and flux coupling for interFOAM in the FF module [#308](https://github.com/precice/openfoam-adapter/pull/308) diff --git a/docs/README.md b/docs/README.md index 82527395..cb5e6671 100644 --- a/docs/README.md +++ b/docs/README.md @@ -15,6 +15,7 @@ This preCICE adapter is a plug-in (function object) for OpenFOAM, which can work This adapter can read/write the following fields in a surface coupling setup: - Temperature (read + write) +- Temperature gradient (read + write) - Heat flux (read + write) - Sink temperature (read + write) - Heat transfer coefficient (read + write) @@ -26,6 +27,9 @@ This adapter can read/write the following fields in a surface coupling setup: - Pressure gradient (read + write) - Velocity (read + write) - Velocity gradient (read + write) +- Phase fraction (alpha) (read + write) +- Phase fraction (alpha) gradient (read + write) +- Phase flux (phi) (read + write) In addition, the adapter supports the following fields in a volume coupling setup: diff --git a/docs/config.md b/docs/config.md index 073a1fa9..7f22c51a 100644 --- a/docs/config.md +++ b/docs/config.md @@ -217,7 +217,7 @@ solver displacementLaplacian; #### FF -The fluid-fluid coupling module supports reading and writing `Pressure`, `Velocity`, `PressureGradient`, `VelocityGradient`, `FlowTemperature` and `FlowTemperatureGradient`. +The fluid-fluid coupling module supports reading and writing `Pressure`, `Velocity`, `PressureGradient`, `VelocityGradient`, `FlowTemperature`, `FlowTemperatureGradient`, `Alpha`, `AlphaGradient` and the face flux `Phi`. Similarly to the CHT module, you need a `fixedValue` boundary condition of the respective primary field in order to read and apply values, and a `fixedGradient` boundary condition of the respective gradient field in order to read and apply gradients. @@ -248,6 +248,10 @@ interface The FF module is still experimental and the boundary conditions presented here have not been rigorously tested. {% endexperimental %} +`Alpha` refers to the phase variable used in e.g. the volume of fluid multiphase solver `interFoam`. + +When coupling face flux `Phi`, usually no specific boundary condition needs to be set. The coupled boundary values are therefore not persistent and may change within a timestep. + ### Volume coupling Besides surface coupling on the domain boundaries, the OpenFOAM adapter also supports coupling overlapping domains, which can be the complete domain, or regions of it. In contrast to surface coupling, though, reading volume data (source terms) requires a few additional configuration steps compared to writing data. @@ -565,6 +569,12 @@ FF nameU U; // Pressure nameP p; + // Face flux (phi for most sovlers) + namePhi phi; + // Temperature + nameT T; + // Multiphase variable + nameAlpha alpha } ```