Newer
Older
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
-------------------------------------------------------------------------------
Copyright (C) 2015-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify i
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::functionObjects::externalCoupled
Provides a simple file-based communication interface for explicit coupling
with an external application, so that data is transferred to- and from
OpenFOAM. The data exchange employs specialised boundary conditions to
provide either one-way or two-way coupling models.
The coupling is through plain text files where OpenFOAM boundary data
is read/written as one line per face (data from all processors collated):
# Patch: <patch name>
<fld1> <fld2> .. <fldn> //face0
<fld1> <fld2> .. <fldn> //face1
..
<fld1> <fld2> .. <fldn> //faceN
where the actual entries depend on the boundary condition type:
- mixed: value, snGrad, refValue, refGrad, valueFraction
- externalCoupledMixed: output of writeDataMaster
- other: value, snGrad
These text files are located in a user specified communications directory
which gets read/written on the master processor only.
In the communications directory the structure will be:
<regionsName>/<patchGroup>/<fieldName>.[in|out]
(where \c regionsName is either the name of a single region or a composite
of multiple region names)
At start-up, the boundary creates a lock file, i.e.:
... to signal the external source to wait. During the function object
execution the boundary values are written to files (one per region,
per patch(group), per field), e.g.
<regionsName>/<patchGroup>/<fieldName>.out
The lock file is then removed, instructing the external source to take
control of the program execution. When ready, the external program
should create the return values, e.g. to files
<regionsName>/<patchGroup>/<fieldName>.in
... and then reinstate the lock file. The function object will then
read these values, apply them to the boundary conditions and pass
program execution back to OpenFOAM.
Usage
Minimal example by using \c system/controlDict.functions:
// Mandatory entries (unmodifiable)
libs (fieldFunctionObjects);
commsDir "<case>/comms";
"(region1|region0)" // Name of region(s)
{
TPatchGroup // Name of patch(group)
{
readFields (p); // List of fields to read
writeFields (T); // List of fields to write
}
}
}
initByExternal true;
// Optional entries (runtime modifiable)
waitInterval 1;
timeOut 100;
statusDone done; // Any arbitrary status=... value
calcFrequency 1;
// Optional (inherited) entries
...
This reads/writes (on the master processor) the directory:
\verbatim
comms/region0_region1/TPatchGroup/
patchPoints (collected points)
patchFaces (collected faces)
p.in (input file of p, written by external application)
T.out (output file of T, written by OpenFOAM)
The patchPoints/patchFaces files denote the (collated) geometry
which will be written if it does not exist yet or can be written as
a preprocessing step using the createExternalCoupledPatchGeometry
application.
The entries comprise:
\table
Property | Description | Type | Req'd | Dflt
type | Type name: externalCoupled | word | yes | -
libs | Library name: fieldFunctionObjects | word | yes | -
commsDir | Communication directory | word | yes | -
regions | The regions to couple | word | yes | -
initByExternal | Initialization values supplied by external app <!--
--> | bool | yes | -
waitInterval | Wait interval in [s] | label | no | 1
timeOut | Timeout in [s] | label | no | 100*waitInterval
statusDone | Lockfile status=... on termination | word | no | done
calcFrequency | Calculation frequency | label | no | 1
\endtable
The inherited entries are elaborated in:
- \link timeFunctionObject.H \endlink
Usage by the \c postProcess utility is not available.
See also
- Foam::functionObject
- Foam::functionObjects::timeFunctionObject
- Foam::externalFileCouple
- ExtendedCodeGuide::functionObjects::field::externalCoupled
externalCoupled.C
externalCoupledTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef functionObjects_externalCoupled_H
#define functionObjects_externalCoupled_H
#include "timeFunctionObject.H"
#include "externalFileCoupler.H"
#include "wordRes.H"
#include "UPtrList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{

Mark OLESEN
committed
// Forward Declarations
class IFstream;
namespace functionObjects
{
/*---------------------------------------------------------------------------*\

Mark OLESEN
committed
Class externalCoupled Declaration
\*---------------------------------------------------------------------------*/
class externalCoupled
public functionObjects::timeFunctionObject,
public externalFileCoupler
// Private Member Data
//- Calculation frequency
label calcFrequency_;
//- The last timeIndex when coupling was triggered
label lastTrigger_;
//- Names of (composite) regions
DynamicList<word> regionGroupNames_;
// Per (composite) region the names of the regions
DynamicList<wordList> regionGroupRegions_;
// Per (composite) region the indices of the group information
HashTable<labelList> regionToGroups_;
// Per group the names of the patches/patchGroups
DynamicList<wordRe> groupNames_;
// Per group the names of the fields to read
DynamicList<wordList> groupReadFields_;
// Per group the names of the fields to write
DynamicList<wordList> groupWriteFields_;
//- Initialised coupling
bool initialisedCoupling_;
// Private Member Functions
//- Return the file path to the communications directory for the region
static fileName groupDir
(
const fileName& commsDir,
const word& regionsName,
const wordRe& groupName
);
//- Read data for a single region, single field
template<class Type>
bool readData
(
const UPtrList<const fvMesh>& meshes,
const wordRe& groupName,
const word& fieldName
);
//- Write data for a single region, single field
template<class Type>
bool writeData
(
const UPtrList<const fvMesh>& meshes,
const wordRe& groupName,
const word& fieldName
) const;
void initCoupling();
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
//- Read (and distribute) scalar columns from stream. Every processor
// gets nRows (= patch size) of these. Note: could make its argument
// ISstream& but then would need additional logic to construct valid
// stream on all processors.
void readColumns
(
const label nRows,
const label nColumns,
autoPtr<IFstream>& masterFilePtr,
List<scalarField>& data
) const;
//- Read (and distribute) lines from stream. Every processor
// gets nRows (= patch size) of these. Data kept as stream (instead
// of strings) for ease of interfacing to readData routines that take
// an Istream.
void readLines
(
const label nRows,
autoPtr<IFstream>& masterFilePtr,
OStringStream& data
) const;
//- Helper: append data from all processors onto master
template<class Type>
static tmp<Field<Type>> gatherAndCombine(const Field<Type>& fld);
static void checkOrder(const wordList& regionNames);
//- Perform the coupling with necessary initialization etc.
void performCoupling();
public:
//- Runtime type information
TypeName("externalCoupled");
//- Name of patch key, e.g. '// Patch:' when looking for start of patch data
//- Inherited variable for logging
using functionObject::log;
// Constructors
//- Construct given time and dictionary
externalCoupled
(
const word& name,
const Time& runTime,
const dictionary& dict
);
//- No copy construct
externalCoupled(const externalCoupled&) = delete;
//- No copy assignment
void operator=(const externalCoupled&) = delete;
virtual ~externalCoupled() = default;
// Member Functions
// Function object control
//- 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();
//- Read and set the function object if its data have changed
virtual bool read(const dictionary& dict);
//- Write, currently a no-op
virtual bool write();
// File creation, removal
//- Write data files (all regions, all fields) from master (OpenFOAM)
virtual void writeDataMaster() const;
//- Read data files (all regions, all fields) on master (OpenFOAM)
virtual void readDataMaster();
//- Remove data files written by master (OpenFOAM)
virtual void removeDataMaster() const;
//- Remove data files written by slave (external code)
virtual void removeDataSlave() const;
// Other
//- Create single name by appending words (in sorted order),
static word compositeName(const wordList&);
//- Write geometry for the group as region/patch
static void writeGeometry
(
const UPtrList<const fvMesh>& meshes,
const fileName& commsDir,
const wordRe& groupName
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace functionObjects
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "externalCoupledTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //