Merge branch 'feature-externalCoupled' into 'develop'

Feature external coupled

See merge request Development/OpenFOAM-plus!176
This commit is contained in:
Mark Olesen
2017-12-13 19:58:09 +00:00
127 changed files with 2990 additions and 122 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

@ -141,6 +141,12 @@ bool Foam::functionObject::read(const dictionary& dict)
}
bool Foam::functionObject::execute(const label)
{
return true;
}
bool Foam::functionObject::end()
{
return true;

View File

@ -222,13 +222,19 @@ public:
const word& name() const;
//- Read and set the function object if its data have changed
virtual bool read(const dictionary&);
virtual bool read(const dictionary& dict);
//- Called at each ++ or += of the time-loop.
// postProcess overrides the usual executeControl behaviour and
// forces execution (used in post-processing mode)
virtual bool execute() = 0;
//- Execute using the specified subIndex.
// The base implementation is a no-op.
// \param subIndex an execution sub-index corresponding to a
// sub-cycle or something similar.
virtual bool execute(const label subIndex);
//- Called at each ++ or += of the time-loop.
// postProcess overrides the usual writeControl behaviour and
// forces writing always (used in post-processing mode)
@ -245,9 +251,11 @@ public:
virtual bool filesModified() const;
//- Update for changes of mesh
// The base implementation is a no-op.
virtual void updateMesh(const mapPolyMesh& mpm);
//- Update for changes of mesh
// The base implementation is a no-op.
virtual void movePoints(const polyMesh& mesh);
};

View File

@ -32,6 +32,7 @@ License
//#include "IFstream.H"
#include "dictionaryEntry.H"
#include "stringOps.H"
#include "wordRes.H"
#include "Tuple2.H"
#include "etcFiles.H"
#include "IOdictionary.H"
@ -579,6 +580,7 @@ bool Foam::functionObjectList::execute()
}
}
}
// Force writing of state dictionary after function object execution
if (time_.writeTime())
{
@ -600,6 +602,49 @@ bool Foam::functionObjectList::execute()
}
bool Foam::functionObjectList::execute(const label subIndex)
{
bool ok = execution_;
if (ok)
{
forAll(*this, obji)
{
functionObject& funcObj = operator[](obji);
ok = funcObj.execute(subIndex) && ok;
}
}
return ok;
}
bool Foam::functionObjectList::execute
(
const wordRes& functionNames,
const label subIndex
)
{
bool ok = execution_;
if (ok && functionNames.size())
{
forAll(*this, obji)
{
functionObject& funcObj = operator[](obji);
if (functionNames.match(funcObj.name()))
{
ok = funcObj.execute(subIndex) && ok;
}
}
}
return ok;
}
bool Foam::functionObjectList::end()
{
bool ok = true;

View File

@ -52,8 +52,10 @@ SourceFiles
namespace Foam
{
class mapPolyMesh;
// Forward declarations
class argList;
class mapPolyMesh;
class wordRes;
/*---------------------------------------------------------------------------*\
Class functionObjectList Declaration
@ -94,19 +96,19 @@ class functionObjectList
void createStateDict() const;
//- Remove and return the function object pointer by name,
// and returns the old index via the parameter.
//- and returns the old index via the parameter.
// Returns a nullptr (and index -1) if it didn't exist
functionObject* remove(const word&, label& oldIndex);
functionObject* remove(const word& key, label& oldIndex);
//- Search the specified directory for functionObject
// configuration files, add to the given map and recurse
//- configuration files, add to the given map and recurse
static void listDir(const fileName& dir, HashSet<word>& foMap);
//- Disallow default bitwise copy construct
functionObjectList(const functionObjectList&);
functionObjectList(const functionObjectList&) = delete;
//- Disallow default bitwise assignment
void operator=(const functionObjectList&);
void operator=(const functionObjectList&) = delete;
public:
@ -114,7 +116,7 @@ public:
// Static data members
//- Default relative path to the directory structure
// containing the functionObject dictionary files
//- containing the functionObject dictionary files
static fileName functionObjectDictPath;
@ -188,7 +190,7 @@ public:
label findObjectID(const word& name) const;
//- Print a list of functionObject configuration files in
// user/group/shipped directories.
//- user/group/shipped directories.
// The search scheme allows for version-specific and
// version-independent files using the following hierarchy:
// - \b user settings:
@ -205,7 +207,7 @@ public:
static void list();
//- Search for functionObject dictionary file in
// user/group/shipped directories.
//- user/group/shipped directories.
// The search scheme allows for version-specific and
// version-independent files using the following hierarchy:
// - \b user settings:
@ -258,6 +260,18 @@ public:
// forces execution (used in post-processing mode)
bool execute();
//- Execute function objects using the specified subIndex.
// \param subIndex an execution sub-index corresponding to a
// sub-cycle or something similar
bool execute(const label subIndex);
//- Execute a subset of function objects using the specified subIndex.
// \param functionNames names or regex of existing functions to
// execute
// \param subIndex an execution sub-index corresponding to a
// sub-cycle or something similar
bool execute(const wordRes& functionNames, const label subIndex);
//- Called when Time::run() determines that the time-loop exits
bool end();

View File

@ -450,6 +450,18 @@ bool Foam::functionObjects::timeControl::execute()
}
bool Foam::functionObjects::timeControl::execute(const label subIndex)
{
if (active())
{
// Call underlying function object directly
foPtr_->execute(subIndex);
}
return true;
}
bool Foam::functionObjects::timeControl::write()
{
if (active() && (postProcess || writeControl_.execute()))
@ -726,10 +738,8 @@ bool Foam::functionObjects::timeControl::read(const dictionary& dict)
return true;
}
else
{
return false;
}
}

View File

@ -206,6 +206,9 @@ public:
// forces execution (used in post-processing mode)
virtual bool execute();
//- Execute using the specified subIndex.
virtual bool execute(const label subIndex);
//- Called at each ++ or += of the time-loop.
// postProcess overrides the usual writeControl behaviour and
// forces writing (used in post-processing mode)

View File

@ -425,6 +425,7 @@ $(coupling)/externalFileCoupler.C
solutionControl = $(general)/solutionControl
$(solutionControl)/solutionControl/solutionControl.C
$(solutionControl)/loopControl/loopControl.C
$(solutionControl)/simpleControl/simpleControl.C
$(solutionControl)/pimpleControl/pimpleControl.C
$(solutionControl)/pisoControl/pisoControl.C

View File

@ -0,0 +1,47 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object fvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
SIMPLE
{
energyCoupling
{
// (Max) number of loops
iterations 200;
// The interval to execute onLoop function-objects
interval 0;
// Convergence criteria to terminate loop
convergence
{
"h" 1e-3;
}
// Names of function objects to fire with execute(int) when looping
onLoop ( );
// Names of function objects to fire with execute(int) when converged
onConverged ( );
// Names of function objects to fire with execute(int) when loop ends
// without convergence
onEnd ( );
}
}
// ************************************************************************* //

View File

@ -0,0 +1,280 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "loopControl.H"
#include "fvSolution.H"
#include "wordRes.H"
#include "solutionControl.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::loopControl::clear()
{
total_ = 0;
interval_ = 0;
convergenceDict_.clear();
onLoop_.clear();
onConverged_.clear();
onEnd_.clear();
converged_ = false;
}
void Foam::loopControl::read(const dictionary& dict)
{
clear();
bool enabled = dict.lookupOrDefault("enabled", true);
if (enabled)
{
scalar timeStart;
if (dict.readIfPresent("timeStart", timeStart))
{
timeStart = time_.userTimeToTime(timeStart);
enabled =
(
enabled
&& time_.value() >= (timeStart - 0.5*time_.deltaTValue())
);
}
scalar timeEnd;
if (dict.readIfPresent("timeEnd", timeEnd))
{
timeEnd = time_.userTimeToTime(timeEnd);
enabled =
(
enabled
&& time_.value() <= (timeEnd + 0.5*time_.deltaTValue())
);
}
}
if (!enabled)
{
return;
}
dict.readIfPresent("iterations", total_);
dict.readIfPresent("interval", interval_);
convergenceDict_ = dict.subOrEmptyDict("convergence");
dict.readIfPresent("onLoop", onLoop_);
dict.readIfPresent("onConverged", onConverged_);
dict.readIfPresent("onEnd", onEnd_);
}
bool Foam::loopControl::checkConverged() const
{
if (convergenceDict_.empty())
{
return false;
}
HashTable<const fvMesh*> meshes = time_.lookupClass<const fvMesh>();
bool achieved = true;
bool checked = false; // safety that some checks were indeed performed
forAllConstIters(meshes, meshIter)
{
const fvMesh& regionMesh = *(meshIter.object());
const dictionary& solverDict = regionMesh.solverPerformanceDict();
forAllConstIters(solverDict, iter)
{
const entry& dataDictEntry = *iter;
const word& variableName = dataDictEntry.keyword();
const scalar absTol =
convergenceDict_.lookupOrDefault<scalar>(variableName, -1);
if (absTol > 0)
{
// Treat like a SIMPLE control
Pair<scalar> residuals =
solutionControl::maxResidual
(
regionMesh,
dataDictEntry
);
checked = true;
achieved = achieved && (residuals.first() < absTol);
}
}
}
return checked && achieved;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::loopControl::loopControl
(
Time& runTime,
const label nCycles,
const word& loopName
)
:
subLoopTime(runTime, nCycles),
name_(loopName),
interval_(0),
convergenceDict_(),
onLoop_(),
onConverged_(),
onEnd_(),
converged_(false)
{}
Foam::loopControl::loopControl
(
Time& runTime,
const dictionary& algorithmDict,
const word& dictName
)
:
loopControl(runTime, 0, dictName)
{
// The loop sub-dictionary
const dictionary* dictptr = algorithmDict.subDictPtr(dictName);
if (dictptr)
{
// Info<< dictName << *dictptr << endl;
read(*dictptr);
}
}
Foam::loopControl::loopControl
(
Time& runTime,
const word& algorithmName,
const word& dictName
)
:
loopControl(runTime, 0, dictName)
{
fvSolution fvsol(time_);
// Eg, PIMPLE or SIMPLE from <system/fvSolution>
const dictionary* dictptr =
fvsol.solutionDict().subDictPtr(algorithmName);
if (dictptr)
{
// The loop sub-dictionary
dictptr = dictptr->subDictPtr(dictName);
if (dictptr)
{
// Info<< dictName << *dictptr << endl;
read(*dictptr);
}
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::loopControl::~loopControl()
{
stop();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::loopControl::loop()
{
bool active = (index_ < total_); // as per status()
if (active)
{
operator++();
converged_ = checkConverged();
if (converged_)
{
time_.functionObjects().execute(onConverged_, index_);
stop();
return false;
}
else if
(
interval_ && !(index_ % interval_)
&& !onLoop_.empty()
)
{
time_.functionObjects().execute(onLoop_, index_);
}
}
else if (index_)
{
// Not active, the loop condition has now exiting on the last subloop
if (!converged_ && !onEnd_.empty())
{
time_.functionObjects().execute(onEnd_, index_);
}
}
return active;
}
// * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const loopControl& ctrl)
{
os << ctrl.name() << ": ";
if (ctrl.nCycles() && ctrl.index() <= ctrl.nCycles())
{
os << ctrl.index() << '/' << ctrl.nCycles();
}
else
{
os << "off";
}
return os;
}
// ************************************************************************* //

View File

@ -0,0 +1,227 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::loopControl
Description
A class for managing arbitrary loops with the ability to invoke
function object execution.
Usage
Examples of function object specification:
\verbatim
SIMPLE
{
energyCoupling
{
iterations 100;
onLoop ();
onConverged ( externalCoupled "loopThings.*" );
convergence
{
"h" 1e-3;
}
}
}
Where the loop entries comprise:
\table
Property | Description | Required | Default
enabled | active/deactive loop | no | true
iteration | times to loop | no | 0
timeStart | begin time for loop activation | no | -VGREAT
timeEnd | end time of loop activation | no | VGREAT
interval | sub-interval to execute onLoop | no | 0
onLoop | function object names to call at executeInterval | no
onConverged | function object names to call when converged | no
onEnd | function object names to call when loop ends | no
convergence | dictionary of convergence values to check | no
\endtable
The function object names listed by \c onLoop, \c onConverged, \c onEnd
must implement an \c execute(int) method.
If the time controls \c timeStart or \c timeEnd are used for the loop,
these values are only inspected upon creation, not during execution.
SeeAlso
fvSolution
SourceFiles
loopControl.C
\*---------------------------------------------------------------------------*/
#ifndef loopControl_H
#define loopControl_H
#include "subLoopTime.H"
#include "dictionary.H"
#include "wordReList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class loopControl Declaration
\*---------------------------------------------------------------------------*/
class loopControl
:
public subLoopTime
{
// Private Member Functions
//- Reset
void clear();
//- Read settings from dictionary
void read(const dictionary& dict);
//- Execute specified function names
bool checkConverged() const;
//- Disallow default bitwise copy construct
loopControl(const loopControl&) = delete;
//- Disallow default bitwise assignment
void operator=(const loopControl&) = delete;
protected:
// Protected data
//- Name of the loop control (the lookup dictionary name).
word name_;
//- The interval to execute onLoop function-objects
label interval_;
//- Dictionary for checking convergence (all regions)
dictionary convergenceDict_;
//- Function object names to fire during the loop (at executeInterval)
List<wordRe> onLoop_;
//- Function object names to fire on convergence
List<wordRe> onConverged_;
//- Function object names to fire when the loop exits without
//- convergence
List<wordRe> onEnd_;
//- Convergence tests passed
bool converged_;
public:
// Constructors
//- Construct from time with fixed number of cycles
// \param runTime the top-level time
// \param nCycles the number of times to loop
// \param loopName the name of the loop
loopControl
(
Time& runTime,
const label nCycles,
const word& dictName = "loop"
);
//- Construct from fvSolution dictionary based on time and the name
//- of the controlling algorithm
// \param runTime the top-level time
// \param algorithmName the name of the fvSolution dictionary,
// typically PIMPLE or SIMPLE
// \param dictName the name of the control dictionary
loopControl
(
Time& runTime,
const word& algorithmName,
const word& dictName = "loop"
);
//- Construct from fvSolution dictionary based on time and the name
//- of the controlling algorithm
// \param runTime the top-level time
// \param algorithmDict the fvSolution algorithm dictionary,
// typically PIMPLE or SIMPLE
// \param dictName the name of the control dictionary
loopControl
(
Time& runTime,
const dictionary& algorithmDict,
const word& dictName = "loop"
);
//- Destructor
~loopControl();
// Member Functions
//- Name of the loop control
inline const word& name() const
{
return name_;
}
//- The interval to execute onLoop function-objects
inline label interval() const
{
return interval_;
}
//- True if looping is active, increments the index and executes
//- the onLoop and onConverged functions.
// Example usage,
// \code
// while (control.loop())
// {
// solve;
// }
// \endcode
bool loop();
// IOstream operators
//- Write name and state (on/off, index/total) to Ostream
friend Ostream& operator<<(Ostream& os, const loopControl& ctrl);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

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:

View File

@ -23,7 +23,7 @@ boundaryField
".*"
{
type calculated;
value uniform 300;
value $internalField;
}
}

View File

@ -23,7 +23,7 @@ boundaryField
".*"
{
type calculated;
value uniform (0.01 0 0);
value $internalField;
}
}

View File

@ -23,9 +23,8 @@ boundaryField
".*"
{
type calculated;
value uniform 0.01;
value $internalField;
}
}
// ************************************************************************* //

View File

@ -23,9 +23,8 @@ boundaryField
".*"
{
type calculated;
value uniform 0.1;
value $internalField;
}
}
// ************************************************************************* //

View File

@ -23,7 +23,7 @@ boundaryField
".*"
{
type calculated;
value uniform 1e5;
value $internalField;
}
}

View File

@ -23,7 +23,7 @@ boundaryField
".*"
{
type calculated;
value uniform 1e5;
value $internalField;
}
}

View File

@ -23,6 +23,9 @@ waitSec=5
timeOut=100
nSteps=1000 # maximum number of time steps. Note: should be more than
# number of iterations on the OpenFOAM side
stopAt=600 # external solver signals OpenFOAM to stop
refGrad=0
valueFraction=1
@ -42,6 +45,13 @@ useMaster()
echo "status=openfoam" >| ${lockFile}
}
# Lock file with special content to stop OpenFOAM master
stopMasterNow()
{
log "writeNow terminate via lock file '${lockFile}'"
echo "action=writeNow" >| ${lockFile}
}
init()
{
@ -120,11 +130,21 @@ do
log "updating ${dataFile}.in from ${dataFile}.out"
if [ -f "${dataFile}.out" ]
then
awk '{if( $1 != "#" ){print $1+1 " 0 1"}}' \
${dataFile}.out >| ${dataFile}.in
else
log "Warning: no such file ${dataFile}.out"
fi
if [ "${stopAt:-0}" -eq $step ]
then
stopMasterNow
else
useMaster
fi
fi
done
log "done"

View File

@ -0,0 +1,44 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object decomposeParDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
numberOfSubdomains 4;
method scotch;
simpleCoeffs
{
n (2 2 1);
delta 0.001;
}
hierarchicalCoeffs
{
n (2 2 1);
delta 0.001;
order xyz;
}
scotchCoeffs
{
}
manualCoeffs
{
dataFile "decompositionData";
}
// ************************************************************************* //

View File

@ -0,0 +1,24 @@
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
. $WM_PROJECT_DIR/bin/tools/CleanFunctions # Tutorial clean functions
cleanCase
rm -rf comms
rm -rf VTK
rm -rf constant/cellToRegion
rm -rf 0/bottomWater
rm -rf 0/topAir
rm -rf 0/heater
rm -rf 0/leftSolid
rm -rf 0/rightSolid
rm -f 0/cellToRegion
rm -rf constant/bottomWater/polyMesh
rm -rf constant/topAir/polyMesh
rm -rf constant/heater/polyMesh
rm -rf constant/leftSolid/polyMesh
rm -rf constant/rightSolid/polyMesh
#------------------------------------------------------------------------------

View File

@ -0,0 +1,33 @@
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
. $WM_PROJECT_DIR/bin/tools/RunFunctions # Tutorial run functions
./Allrun.pre
# Remove lock file on interrupt
trap '\rm -f comms/OpenFOAM.lock 2>/dev/null' INT
#-- Run on single processor
#runApplication $(getApplication) &
# Simulated external solver
#runApplication ./externalSolver
# Decompose
runApplication decomposePar -allRegions
## Can verify parallel operation of createExternalCoupledPatchGeometry
# \rm -f log.createExternalCoupledPatchGeometry
# runParallel createExternalCoupledPatchGeometry \
# -regions '(topAir heater)' coupleGroup \
# -commsDir $PWD/comms
# Run OpenFOAM
runParallel $(getApplication) &
# Simulated external solver
runApplication ./externalSolver
# Reconstruct
runApplication reconstructPar -allRegions
#------------------------------------------------------------------------------

View File

@ -0,0 +1,30 @@
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
. $WM_PROJECT_DIR/bin/tools/RunFunctions # Tutorial run functions
runApplication blockMesh
runApplication topoSet
runApplication splitMeshRegions -cellZones -overwrite
# remove fluid fields from solid regions (important for post-processing)
for i in heater leftSolid rightSolid
do
rm -f 0*/$i/{nut,alphat,epsilon,k,U,p_rgh}
done
for i in bottomWater topAir heater leftSolid rightSolid
do
changeDictionary -region $i > log.changeDictionary.$i 2>&1
done
# Create coupling geometry
runApplication createExternalCoupledPatchGeometry \
-regions '(topAir heater)' coupleGroup
# echo
# echo "creating files for paraview post-processing"
# echo
# paraFoam -touchAll 2>/dev/null
#------------------------------------------------------------------------------

View File

@ -0,0 +1,3 @@
Modification of the heatTransfer chtMultiRegionFoam tutorial that demonstrates
the externalCoupled functionObject in combination with the ./externalSolver
script to simulate coupling to an external code.

View File

@ -0,0 +1,20 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class uniformDimensionedVectorField;
object g;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 1 -2 0 0 0 0];
value (0 -9.81 0);
// ************************************************************************* //

View File

@ -0,0 +1,22 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object radiationProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
radiation off;
radiationModel none;
// ************************************************************************* //

View File

@ -0,0 +1,50 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object thermophysicalProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
thermoType
{
type heRhoThermo;
mixture pureMixture;
transport const;
thermo hConst;
equationOfState rhoConst;
specie specie;
energy sensibleEnthalpy;
}
mixture
{
specie
{
molWeight 18;
}
equationOfState
{
rho 1000;
}
thermodynamics
{
Cp 4181;
Hf 0;
}
transport
{
mu 959e-6;
Pr 6.62;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,19 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object turbulenceProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
simulationType laminar;
// ************************************************************************* //

View File

@ -0,0 +1,23 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object radiationProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
radiation off;
radiationModel none;
// ************************************************************************* //

View File

@ -0,0 +1,52 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object thermophysicalProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
thermoType
{
type heSolidThermo;
mixture pureMixture;
transport constIso;
thermo hConst;
equationOfState rhoConst;
specie specie;
energy sensibleEnthalpy;
}
mixture
{
specie
{
molWeight 50;
}
transport
{
kappa 80;
}
thermodynamics
{
Hf 0;
Cp 450;
}
equationOfState
{
rho 8000;
}
}
// ************************************************************************* //

View File

@ -0,0 +1 @@
../heater/radiationProperties

View File

@ -0,0 +1 @@
../heater/thermophysicalProperties

View File

@ -0,0 +1,24 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object regionProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
regions
(
fluid (bottomWater topAir)
solid (heater leftSolid rightSolid)
);
// ************************************************************************* //

View File

@ -0,0 +1 @@
../heater/thermophysicalProperties

View File

@ -0,0 +1 @@
../bottomWater/g

View File

@ -0,0 +1 @@
../bottomWater/radiationProperties

View File

@ -0,0 +1,47 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object thermophysicalProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
thermoType
{
type heRhoThermo;
mixture pureMixture;
transport const;
thermo hConst;
equationOfState perfectGas;
specie specie;
energy sensibleEnthalpy;
}
mixture
{
specie
{
molWeight 28.9;
}
thermodynamics
{
Cp 1000;
Hf 0;
}
transport
{
mu 1.8e-05;
Pr 0.7;
}
}
// ************************************************************************* //

View File

@ -0,0 +1 @@
../bottomWater/turbulenceProperties

View File

@ -0,0 +1,156 @@
#!/bin/sh
#
# Dummy external solver to communicate with OpenFOAM via externalCoupled
# functionObject
#
# Functionality is hard-coded for this particular test case
# - patch temperatures increased by 1K on each step
#
cd ${0%/*} || exit 1 # Run from this directory
# Check for unassigned variables
set -u
echo "Executing dummy external solver"
commsDir="comms"
patchDir="heater_topAir/coupleGroup"
fieldName="T"
lockFile="${commsDir}/OpenFOAM.lock"
dataFile="${commsDir}/${patchDir}/${fieldName}"
waitSec=5
timeOut=100
nSteps=1000 # maximum number of time steps. Note: should be more than
# number of iterations on the OpenFOAM side
stopAt=300 # external solver signals OpenFOAM to stop
refGrad=0
valueFraction=1
# Remove any old junk
\rm -f $lockFile 2>/dev/null
log()
{
echo "External: $@"
}
# Create lock file to pass control to OpenFOAM
useMaster()
{
log "creating lock file '${lockFile}'"
echo "status=openfoam" >| ${lockFile}
}
# Lock file with special content to stop OpenFOAM master
stopMasterNow()
{
log "writeNow terminate via lock file '${lockFile}'"
echo "action=writeNow" >| ${lockFile}
}
init()
{
log "init - creating ${dataFile}.in"
cat /dev/null >| "${dataFile}.in"
# Hard-coded for patch of size 8 (heater/minY)
local n1=8
local refValue1=500
log "init - adding $n1 data elements with refValue $refValue1"
for i in $(seq 1 $n1)
do
echo "$refValue1 $refGrad $valueFraction"
done >> "${dataFile}.in"
# Hard-coded for patch of size 40 (topAir/minX)
local n2=40
local refValue2=300
log "init - adding $n2 data elements with refValue $refValue2"
for i in $(seq 1 $n2)
do
echo "$refValue2 $refGrad $valueFraction"
done >> "${dataFile}.in"
# Verify line count?
# log "init ($(wc -l ${dataFile}.in))"
# Give time for T.in file to flush
sleep 1
useMaster
}
# Create the comms directory
mkdir -p ${commsDir}/${patchDir}
# Tutorial case uses 'initByExternal' option, so we must provide initial values
init
totalWait=0
step=0
while [ $step -lt $nSteps ]
do
if [ -f $lockFile ]
then
if grep -q "status=done" ${lockFile}
then
log "found lock file '${lockFile}' with 'status=done' - finished"
break
elif [ -s $lockFile ]
then
log "found lock file '${lockFile}' containing '$(< $lockFile)' - waiting"
else
log "found lock file '${lockFile}' - waiting"
fi
totalWait=$(expr $totalWait + $waitSec)
if [ $totalWait -gt $timeOut ]
then
log "timeout"
break
else
sleep $waitSec
fi
else
totalWait=0
step=$(expr $step + 1)
log "step $step"
log "lock not present - taking control"
log "sleeping for $waitSec secs to simulate external process"
sleep $waitSec
log "updating ${dataFile}.in from ${dataFile}.out"
if [ -f "${dataFile}.out" ]
then
##awk '{if( $1 != "#" ){print $1+0.1 " 0 1"}}' \
awk '{if( $1 != "#" ){print $1 " 0 1"}}' \
${dataFile}.out >| ${dataFile}.in
else
log "Warning: no such file ${dataFile}.out"
fi
if [ "${stopAt:-0}" -eq $step ]
then
stopMasterNow
else
useMaster
fi
fi
done
log "done"
# Remove the lock file too
\rm -f $lockFile 2>/dev/null
#------------------------------------------------------------------------------

View File

@ -0,0 +1,3 @@
fvSolution is used for outer correctors specification.
fvSchemes is only so that pre-processing activities can proceed

View File

@ -0,0 +1,96 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object blockMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
scale 1;
vertices
(
(-0.1 -0.04 -0.05)
( 0.1 -0.04 -0.05)
( 0.1 0.04 -0.05)
(-0.1 0.04 -0.05)
(-0.1 -0.04 0.05)
( 0.1 -0.04 0.05)
( 0.1 0.04 0.05)
(-0.1 0.04 0.05)
);
blocks
(
hex (0 1 2 3 4 5 6 7) (30 10 10) simpleGrading (1 1 1)
);
edges
(
);
boundary
(
maxY
{
type wall;
faces
(
(3 7 6 2)
);
}
minX
{
type patch;
faces
(
(0 4 7 3)
);
}
maxX
{
type patch;
faces
(
(2 6 5 1)
);
}
minY
{
type wall;
faces
(
(1 5 4 0)
);
}
minZ
{
type wall;
faces
(
(0 3 2 1)
);
}
maxZ
{
type wall;
faces
(
(4 5 6 7)
);
}
);
mergePatchPairs
(
);
// ************************************************************************* //

View File

@ -0,0 +1,58 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object fvSchemes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
ddtSchemes
{
default steadyState;
}
gradSchemes
{
default Gauss linear;
}
divSchemes
{
default none;
div(phi,U) bounded Gauss upwind;
div(phi,K) bounded Gauss upwind;
div(phi,h) bounded Gauss upwind;
div(phi,k) bounded Gauss upwind;
div(phi,K) bounded Gauss upwind;
div(phi,epsilon) bounded Gauss upwind;
div(phi,R) bounded Gauss upwind;
div(R) Gauss linear;
div(Ji,Ii_h) Gauss linearUpwind grad(U);
div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear;
}
laplacianSchemes
{
default Gauss linear uncorrected;
}
interpolationSchemes
{
default linear;
}
snGradSchemes
{
default uncorrected;
}
// ************************************************************************* //

Some files were not shown because too many files have changed in this diff Show More