ENH: add enthalpy sub-looping for chtMultiRegion* solvers

This commit is contained in:
Mark Olesen
2017-12-05 12:00:00 +01:00
parent 96ed3638e4
commit 0e2798399e
13 changed files with 189 additions and 97 deletions

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -47,6 +47,7 @@ Description
#include "radiationModel.H"
#include "fvOptions.H"
#include "coordinateSystem.H"
#include "loopControl.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -89,11 +90,10 @@ int main(int argc, char *argv[])
}
}
// --- PIMPLE loop
for (int oCorr=0; oCorr<nOuterCorr; oCorr++)
for (int oCorr=0; oCorr<nOuterCorr; ++oCorr)
{
bool finalIter = oCorr == nOuterCorr-1;
const bool finalIter = (oCorr == nOuterCorr-1);
forAll(fluidRegions, i)
{
@ -113,6 +113,35 @@ int main(int argc, char *argv[])
#include "solveSolid.H"
}
// Additional loops for energy solution only
if (!oCorr && nOuterCorr > 1)
{
loopControl looping(runTime, pimple, "energyCoupling");
while (looping.loop())
{
Info<< nl << looping << nl;
forAll(fluidRegions, i)
{
Info<< "\nSolving for fluid region "
<< fluidRegions[i].name() << endl;
#include "setRegionFluidFields.H"
#include "readFluidMultiRegionPIMPLEControls.H"
frozenFlow = true;
#include "solveFluid.H"
}
forAll(solidRegions, i)
{
Info<< "\nSolving for solid region "
<< solidRegions[i].name() << endl;
#include "setRegionSolidFields.H"
#include "readSolidMultiRegionPIMPLEControls.H"
#include "solveSolid.H"
}
}
}
}
runTime.write();

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -42,6 +42,7 @@ Description
#include "radiationModel.H"
#include "fvOptions.H"
#include "coordinateSystem.H"
#include "loopControl.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -57,7 +58,6 @@ int main(int argc, char *argv[])
#include "createFields.H"
#include "initContinuityErrs.H"
while (runTime.loop())
{
Info<< "Time = " << runTime.timeName() << nl << endl;
@ -80,6 +80,35 @@ int main(int argc, char *argv[])
#include "solveSolid.H"
}
// Additional loops for energy solution only
{
loopControl looping(runTime, "SIMPLE", "energyCoupling");
while (looping.loop())
{
Info<< nl << looping << nl;
forAll(fluidRegions, i)
{
Info<< "\nSolving for fluid region "
<< fluidRegions[i].name() << endl;
#include "setRegionFluidFields.H"
#include "readFluidMultiRegionSIMPLEControls.H"
frozenFlow = true;
#include "solveFluid.H"
}
forAll(solidRegions, i)
{
Info<< "\nSolving for solid region "
<< solidRegions[i].name() << endl;
#include "setRegionSolidFields.H"
#include "readSolidMultiRegionSIMPLEControls.H"
#include "solveSolid.H"
}
}
}
runTime.write();
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"

View File

@ -12,6 +12,14 @@
volScalarField& p = thermo.p();
const volScalarField& psi = thermo.psi();
volScalarField& p_rgh = p_rghFluid[i];
const dimensionedVector& g = gFluid[i];
const volScalarField& gh = ghFluid[i];
const surfaceScalarField& ghf = ghfFluid[i];
radiation::radiationModel& rad = radiation[i];
IOMRFZoneList& MRF = MRFfluid[i];
fv::options& fvOptions = fluidFvOptions[i];
@ -22,14 +30,7 @@
initialMassFluid[i]
);
radiation::radiationModel& rad = radiation[i];
bool frozenFlow = frozenFlowFluid[i];
const label pRefCell = pRefCellFluid[i];
const scalar pRefValue = pRefValueFluid[i];
const bool frozenFlow = frozenFlowFluid[i];
volScalarField& p_rgh = p_rghFluid[i];
const dimensionedVector& g = gFluid[i];
const volScalarField& gh = ghFluid[i];
const surfaceScalarField& ghf = ghfFluid[i];

View File

@ -1,5 +1,5 @@
{
for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
for (int nonOrth=0; nonOrth<=nNonOrthCorr; ++nonOrth)
{
fvScalarMatrix hEqn
(
@ -20,9 +20,9 @@
fvOptions.correct(h);
}
}
thermo.correct();
thermo.correct();
Info<< "Min/max T:" << min(thermo.T()).value() << ' '
Info<< "Min/max T:" << min(thermo.T()).value() << ' '
<< max(thermo.T()).value() << endl;
}

View File

@ -19,8 +19,8 @@ List<bool> frozenFlowFluid(fluidRegions.size(), false);
PtrList<IOMRFZoneList> MRFfluid(fluidRegions.size());
PtrList<fv::options> fluidFvOptions(fluidRegions.size());
List<label> refCellFluid(fluidRegions.size());
List<scalar> refValueFluid(fluidRegions.size());
List<label> pRefCellFluid(fluidRegions.size());
List<scalar> pRefValueFluid(fluidRegions.size());
// Populate fluid field pointer lists
forAll(fluidRegions, i)
@ -252,8 +252,8 @@ forAll(fluidRegions, i)
turbulence[i].validate();
refCellFluid[i] = 0;
refValueFluid[i] = 0.0;
pRefCellFluid[i] = 0;
pRefValueFluid[i] = 0.0;
if (p_rghFluid[i].needReference())
{
@ -262,8 +262,8 @@ forAll(fluidRegions, i)
thermoFluid[i].p(),
p_rghFluid[i],
pimpleDict,
refCellFluid[i],
refValueFluid[i]
pRefCellFluid[i],
pRefValueFluid[i]
);
}

View File

@ -32,7 +32,8 @@
initialMassFluid[i]
);
const bool frozenFlow = frozenFlowFluid[i];
bool frozenFlow = frozenFlowFluid[i];
const label pRefCell = pRefCellFluid[i];
const scalar pRefValue = pRefValueFluid[i];
const label pRefCell = refCellFluid[i];
const scalar pRefValue = refValueFluid[i];

View File

@ -1,10 +1,10 @@
const wordList solidsNames(rp["solid"]);
const wordList solidNames(rp["solid"]);
PtrList<fvMesh> solidRegions(solidsNames.size());
PtrList<fvMesh> solidRegions(solidNames.size());
forAll(solidsNames, i)
forAll(solidNames, i)
{
Info<< "Create solid mesh for region " << solidsNames[i]
Info<< "Create solid mesh for region " << solidNames[i]
<< " for time = " << runTime.timeName() << nl << endl;
solidRegions.set
@ -14,7 +14,7 @@
(
IOobject
(
solidsNames[i],
solidNames[i],
runTime.timeName(),
runTime,
IOobject::MUST_READ

View File

@ -4,7 +4,7 @@ if (finalIter)
}
{
for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
for (int nonOrth=0; nonOrth<=nNonOrthCorr; ++nonOrth)
{
fvScalarMatrix hEqn
(
@ -26,12 +26,12 @@ if (finalIter)
fvOptions.correct(h);
}
}
thermo.correct();
thermo.correct();
Info<< "Min/max T:" << min(thermo.T()).value() << ' '
Info<< "Min/max T:" << min(thermo.T()).value() << ' '
<< max(thermo.T()).value() << endl;
}
if (finalIter)
{

View File

@ -127,7 +127,7 @@ void Foam::functionObjects::externalCoupled::readColumns
List<scalarField> values(nColumns);
// Number of rows to read for processor proci
label procNRows = globalFaces.localSize(proci);
const label procNRows = globalFaces.localSize(proci);
forAll(values, columni)
{
@ -195,7 +195,7 @@ void Foam::functionObjects::externalCoupled::readLines
for (label proci = 0; proci < Pstream::nProcs(); ++proci)
{
// Number of rows to read for processor proci
label procNRows = globalFaces.localSize(proci);
const label procNRows = globalFaces.localSize(proci);
UOPstream toProc(proci, pBufs);
@ -369,19 +369,17 @@ Foam::word Foam::functionObjects::externalCoupled::compositeName
return regionNames[0];
}
}
else
{
// Enforce lexical ordering
checkOrder(regionNames);
word composite(regionNames[0]);
for (label i = 1; i < regionNames.size(); i++)
for (label i = 1; i < regionNames.size(); ++i)
{
composite += "_" + regionNames[i];
}
return composite;
}
}
@ -418,8 +416,7 @@ void Foam::functionObjects::externalCoupled::initCoupling()
UPtrList<const fvMesh> meshes(regionNames.size());
forAll(regionNames, regi)
{
const word& regionName = regionNames[regi];
meshes.set(regi, &time_.lookupObject<fvMesh>(regionName));
meshes.set(regi, time_.lookupObjectPtr<fvMesh>(regionNames[regi]));
}
const labelList& groups = regionToGroups_[compName];
@ -484,6 +481,9 @@ void Foam::functionObjects::externalCoupled::performCoupling()
// Signal external source to wait (by creating the lock file)
useMaster();
// Update information about last triggering
lastTrigger_ = time_.timeIndex();
// Process any abort information sent from slave
if
(
@ -491,6 +491,9 @@ void Foam::functionObjects::externalCoupled::performCoupling()
&& action != Time::stopAtControls::saUnknown
)
{
Info<< type() << ": slave requested action "
<< Time::stopAtControlNames[action] << endl;
time_.stopAt(action);
}
}
@ -508,6 +511,8 @@ Foam::functionObjects::externalCoupled::externalCoupled
functionObject(name),
externalFileCoupler(),
time_(runTime),
calcFrequency_(-1),
lastTrigger_(-1),
initialisedCoupling_(false)
{
read(dict);
@ -523,7 +528,12 @@ Foam::functionObjects::externalCoupled::externalCoupled
bool Foam::functionObjects::externalCoupled::execute()
{
if (!initialisedCoupling_ || time_.timeIndex() % calcFrequency_ == 0)
// Not initialized or overdue
if
(
!initialisedCoupling_
|| (time_.timeIndex() >= lastTrigger_ + calcFrequency_)
)
{
performCoupling();
}
@ -532,6 +542,14 @@ bool Foam::functionObjects::externalCoupled::execute()
}
bool Foam::functionObjects::externalCoupled::execute(const label subIndex)
{
performCoupling();
return true;
}
bool Foam::functionObjects::externalCoupled::end()
{
functionObject::end();
@ -552,6 +570,8 @@ bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
calcFrequency_ = dict.lookupOrDefault("calcFrequency", 1);
// Leave trigger intact
// Get names of all fvMeshes (and derived types)
wordList allRegionNames(time_.lookupClass<fvMesh>().sortedToc());
@ -613,21 +633,21 @@ bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
Info<< type() << ": Communicating with regions:" << endl;
for (const word& compName : regionGroupNames_)
{
Info<< "Region: " << compName << endl << incrIndent;
Info<< "Region: " << compName << nl << incrIndent;
const labelList& groups = regionToGroups_[compName];
for (const label groupi : groups)
{
const wordRe& groupName = groupNames_[groupi];
Info<< indent << "patchGroup: " << groupName << "\t"
<< endl
<< nl
<< incrIndent
<< indent << "Reading fields: "
<< groupReadFields_[groupi]
<< endl
<< nl
<< indent << "Writing fields: "
<< groupWriteFields_[groupi]
<< endl
<< nl
<< decrIndent;
}
Info<< decrIndent;
@ -671,10 +691,9 @@ void Foam::functionObjects::externalCoupled::readDataMaster()
// Get the meshes for the region-group
UPtrList<const fvMesh> meshes(regionNames.size());
forAll(regionNames, j)
forAll(regionNames, regi)
{
const word& regionName = regionNames[j];
meshes.set(j, &time_.lookupObject<fvMesh>(regionName));
meshes.set(regi, time_.lookupObjectPtr<fvMesh>(regionNames[regi]));
}
const labelList& groups = regionToGroups_[compName];
@ -716,10 +735,9 @@ void Foam::functionObjects::externalCoupled::writeDataMaster() const
// Get the meshes for the region-group
UPtrList<const fvMesh> meshes(regionNames.size());
forAll(regionNames, j)
forAll(regionNames, regi)
{
const word& regionName = regionNames[j];
meshes.set(j, &time_.lookupObject<fvMesh>(regionName));
meshes.set(regi, time_.lookupObjectPtr<fvMesh>(regionNames[regi]));
}
const labelList& groups = regionToGroups_[compName];

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -29,9 +29,10 @@ Group
Description
This functionObject provides a simple interface for explicit coupling with
an external application. The coupling is through plain text files
where OpenFOAM boundary data is read/written as one line per face
(data from all processors collated):
an external application.
The coupling is through plain text files where OpenFOAM boundary data
is read/written as one line per face (data from all processors collated):
\verbatim
# Patch: <patch name>
<fld1> <fld2> .. <fldn> //face0
@ -167,7 +168,7 @@ namespace functionObjects
{
/*---------------------------------------------------------------------------*\
Class externalCoupled Declaration
Class functionObjects::externalCoupled Declaration
\*---------------------------------------------------------------------------*/
class externalCoupled
@ -200,6 +201,9 @@ private:
//- Calculation frequency
label calcFrequency_;
//- The last timeIndex when coupling was triggered
label lastTrigger_;
//- Names of (composite) regions
DynamicList<word> regionGroupNames_;
@ -232,7 +236,6 @@ private:
const wordRe& groupName
);
//- Read data for a single region, single field
template<class Type>
bool readData
@ -326,6 +329,9 @@ public:
//- Called at each ++ or += of the time-loop
virtual bool execute();
//- Manual execute (sub-loop or when converged)
virtual bool execute(const label subIndex);
//- Called when Time::run() determines that the time-loop exits
virtual bool end();

View File

@ -28,18 +28,23 @@ Group
grpGenericBoundaryConditions grpCoupledBoundaryConditions
Description
This boundary condition extends the mixed boundary condition with
serialisation through
Extends the mixed boundary condition with serialisation functions.
The serialisation functions:
- writeHeader
- writeData
- readData
functions. It is used for coupling to external applications in combination
It is used for coupling to external applications in combination
with the externalCoupled functionObject. The default output is one
line per face, with columns
\verbatim
<value> <snGrad> <refValue> <refGrad> <valueFraction>
\endverbatim
Notes
readData,writeData are not callbacks for regIOobject (since fvPatchField
Note
readData, writeData are not callbacks for regIOobject (since fvPatchField
not derived from it). They do however do exactly the same - streaming of
data.

View File

@ -29,33 +29,35 @@ Group
Description
This boundary condition provides a temperatue interface to an external
application. Values are transferred as plain text files, where OpenFOAM
data is written as:
application.
Values are transferred as plain text files, where OpenFOAM data are
written as follows:
\verbatim
# Patch: \<patch name\>
\<magSf1\> \<value1\> \<qDot1\> \<htc1\>
\<magSf2\> \<value2\> \<qDot2\> \<htc2\>
\<magSf3\> \<value3\> \<qDot3\> \<htc2\>
# Patch: <patch name>
<magSf1> <value1> <qDot1> <htc1>
<magSf2> <value2> <qDot2> <htc2>
<magSf3> <value3> <qDot3> <htc2>
...
\<magSfN\> \<valueN\> \<qDotN\> \<htcN\>
<magSfN> <valueN> <qDotN> <htcN>
\endverbatim
and received as the constituent pieces of the `mixed' condition, i.e.
\verbatim
# Patch: \<patch name\>
\<value1\> \<gradient1\> \<valueFracion1\>
\<value2\> \<gradient2\> \<valueFracion2\>
\<value3\> \<gradient3\> \<valueFracion3\>
# Patch: <patch name>
<value1> <gradient1> <valueFracion1>
<value2> <gradient2> <valueFracion2>
<value3> <gradient3> <valueFracion3>
...
\<valueN\> \<gradientN\> \<valueFracionN\>
<valueN> <gradientN> <valueFracionN>
\endverbatim
Data is sent/received as a single file for all patches from the directory
\verbatim
$FOAM_CASE/\<commsDir\>
$FOAM_CASE/<commsDir>
\endverbatim
At start-up, the boundary creates a lock file, i.e..
@ -68,7 +70,7 @@ Description
update, boundary values are written to file, e.g.
\verbatim
\<fileName\>.out
<fileName>.out
\endverbatim
The lock file is then removed, instructing the external source to take
@ -76,13 +78,14 @@ Description
should create the return values, e.g. to file
\verbatim
\<fileName\>.in
<fileName>.in
\endverbatim
... and then re-instate the lock file. The boundary condition will then
read the return values, and pass program execution back to OpenFOAM.
To be used in combination with the externalCoupled functionObject.
To be used in combination with the functionObjects::externalCoupled
functionObject.
SeeAlso
externalCoupledFunctionObject

View File

@ -28,7 +28,7 @@ Description
Simple class to hold region information for coupled region simulations.
Gives per physics ('fluid', 'solid') the names of the regions. There
is no assumption on this level that one region should only have one
is no assumption on this level that a region should only have a single
set of physics.
SourceFiles
@ -57,10 +57,10 @@ class regionProperties
{
//- Disallow default bitwise copy construct
regionProperties(const regionProperties&);
regionProperties(const regionProperties&) = delete;
//- Disallow default bitwise assignment
void operator=(const regionProperties&);
void operator=(const regionProperties&) = delete;
public: