Non-Conformal Coupled (NCC): Conservative coupling of non-conforming patches
This major development provides coupling of patches which are
non-conformal, i.e. where the faces of one patch do not match the faces
of the other. The coupling is fully conservative and second order
accurate in space, unlike the Arbitrary Mesh Interface (AMI) and
associated ACMI and Repeat AMI methods which NCC replaces.
Description:
A non-conformal couple is a connection between a pair of boundary
patches formed by projecting one patch onto the other in a way that
fills the space between them. The intersection between the projected
surface and patch forms new faces that are incorporated into the finite
volume mesh. These new faces are created identically on both sides of
the couple, and therefore become equivalent to internal faces within the
mesh. The affected cells remain closed, meaning that the area vectors
sum to zero for all the faces of each cell. Consequently, the main
benefits of the finite volume method, i.e. conservation and accuracy,
are not undermined by the coupling.
A couple connects parts of mesh that are otherwise disconnected and can
be used in the following ways:
+ to simulate rotating geometries, e.g. a propeller or stirrer, in which
a part of the mesh rotates with the geometry and connects to a
surrounding mesh which is not moving;
+ to connect meshes that are generated separately, which do not conform
at their boundaries;
+ to connect patches which only partially overlap, in which the
non-overlapped section forms another boundary, e.g. a wall;
+ to simulate a case with a geometry which is periodically repeating by
creating multiple couples with different transformations between
patches.
The capability for simulating partial overlaps replaces the ACMI
functionality, currently provided by the 'cyclicACMI' patch type, and
which is unreliable unless the couple is perfectly flat. The capability
for simulating periodically repeating geometry replaces the Repeat AMI
functionality currently provided by the 'cyclicRepeatAMI' patch type.
Usage:
The process of meshing for NCC is very similar to existing processes for
meshing for AMI. Typically, a mesh is generated with an identifiable set
of internal faces which coincide with the surface through which the mesh
will be coupled. These faces are then duplicated by running the
'createBaffles' utility to create two boundary patches. The points are
then split using 'splitBaffles' in order to permit independent motion of
the patches.
In AMI, these patches are assigned the 'cyclicAMI' patch type, which
couples them using AMI interpolation methods.
With NCC, the patches remain non-coupled, e.g. a 'wall' type. Coupling
is instead achieved by running the new 'createNonConformalCouples'
utility, which creates additional coupled patches of type
'nonConformalCyclic'. These appear in the 'constant/polyMesh/boundary'
file with zero faces; they are populated with faces in the finite volume
mesh during the connection process in NCC.
For a single couple, such as that which separates the rotating and
stationary sections of a mesh, the utility can be called using the
non-coupled patch names as arguments, e.g.
createNonConformalCouples -overwrite rotatingZoneInner rotatingZoneOuter
where 'rotatingZoneInner' and 'rotatingZoneOuter' are the names of the
patches.
For multiple couples, and/or couples with transformations,
'createNonConformalCouples' should be run without arguments. Settings
will then be read from a configuration file named
'system/createNonConformalCouplesDict'. See
'$FOAM_ETC/caseDicts/annotated/createNonConformalCouplesDict' for
examples.
Boundary conditions must be specified for the non-coupled patches. For a
couple where the patches fully overlap, boundary conditions
corresponding to a slip wall are typically applied to fields, i.e
'movingWallSlipVelocity' (or 'slip' if the mesh is stationary) for
velocity U, 'zeroGradient' or 'fixedFluxPressure' for pressure p, and
'zeroGradient' for other fields. For a couple with
partially-overlapping patches, boundary conditions are applied which
physically represent the non-overlapped region, e.g. a no-slip wall.
Boundary conditions also need to be specified for the
'nonConformalCyclic' patches created by 'createNonConformalCouples'. It
is generally recommended that this is done by including the
'$FOAM_ETC/caseDicts/setConstraintTypes' file in the 'boundaryField'
section of each of the field files, e.g.
boundaryField
{
#includeEtc "caseDicts/setConstraintTypes"
inlet
{
...
}
...
}
For moving mesh cases, it may be necessary to correct the mesh fluxes
that are changed as a result of the connection procedure. If the
connected patches do not conform perfectly to the mesh motion, then
failure to correct the fluxes can result in noise in the pressure
solution.
Correction for the mesh fluxes is enabled by the 'correctMeshPhi' switch
in the 'PIMPLE' (or equivalent) section of 'system/fvSolution'. When it
is enabled, solver settings are required for 'MeshPhi'. The solution
just needs to distribute the error enough to dissipate the noise. A
smooth solver with a loose tolerance is typically sufficient, e.g. the
settings in 'system/fvSolution' shown below:
solvers
{
MeshPhi
{
solver smoothSolver;
smoother symGaussSeidel;
tolerance 1e-2;
relTol 0;
}
...
}
PIMPLE
{
correctMeshPhi yes;
...
}
The solution of 'MeshPhi' is an inexpensive computation since it is
applied only to a small subset of the mesh adjacent to the
couple. Conservation is maintained whether or not the mesh flux
correction is enabled, and regardless of the solution tolerance for
'MeshPhi'.
Advantages of NCC:
+ NCC maintains conservation which is required for many numerical
schemes and algorithms to operate effectively, in particular those
designed to maintain boundedness of a solution.
+ Closed-volume systems no longer suffer from accumulation or loss of
mass, poor convergence of the pressure equation, and/or concentration
of error in the reference cell.
+ Partially overlapped simulations are now possible on surfaces that are
not perfectly flat. The projection fills space so no overlaps or
spaces are generated inside contiguously overlapping sections, even if
those sections have sharp angles.
+ The finite volume faces created by NCC have geometrically accurate
centres. This makes the method second order accurate in space.
+ The polyhedral mesh no longer requires duplicate boundary faces to be
generated in order to run a partially overlapped simulation.
+ Lagrangian elements can now transfer across non-conformal couplings in
parallel.
+ Once the intersection has been computed and applied to the finite
volume mesh, it can use standard cyclic or processor cyclic finite
volume boundary conditions, with no need for additional patch types or
matrix interfaces.
+ Parallel communication is done using the standard
processor-patch-field system. This is more efficient than alternative
systems since it has been carefully optimised for use within the
linear solvers.
+ Coupled patches are disconnected prior to mesh motion and topology
change and reconnected afterwards. This simplifies the boundary
condition specification for mesh motion fields.
Resolved Bug Reports:
+ https://bugs.openfoam.org/view.php?id=663
+ https://bugs.openfoam.org/view.php?id=883
+ https://bugs.openfoam.org/view.php?id=887
+ https://bugs.openfoam.org/view.php?id=1337
+ https://bugs.openfoam.org/view.php?id=1388
+ https://bugs.openfoam.org/view.php?id=1422
+ https://bugs.openfoam.org/view.php?id=1829
+ https://bugs.openfoam.org/view.php?id=1841
+ https://bugs.openfoam.org/view.php?id=2274
+ https://bugs.openfoam.org/view.php?id=2561
+ https://bugs.openfoam.org/view.php?id=3817
Deprecation:
NCC replaces the functionality provided by AMI, ACMI and Repeat AMI.
ACMI and Repeat AMI are insufficiently reliable to warrant further
maintenance so are removed in an accompanying commit to OpenFOAM-dev.
AMI is more widely used so will be retained alongside NCC for the next
version release of OpenFOAM and then subsequently removed from
OpenFOAM-dev.
This commit is contained in:
@ -1,5 +1,4 @@
|
||||
decomposePar.C
|
||||
domainDecomposition.C
|
||||
dimFieldDecomposer.C
|
||||
fvFieldDecomposer.C
|
||||
pointFieldDecomposer.C
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
EXE_INC = \
|
||||
-I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/parallel/parallel/lnInclude \
|
||||
-I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
|
||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
||||
-I$(LIB_SRC)/regionModels/regionModel/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-ldynamicMesh \
|
||||
-lgenericPatchFields \
|
||||
-ldecompositionMethods -L$(FOAM_LIBBIN)/dummy -lmetisDecomp -lscotchDecomp \
|
||||
-lfiniteVolume \
|
||||
-lmeshTools\
|
||||
-lparallel \
|
||||
-ldecompositionMethods \
|
||||
-llagrangian \
|
||||
-lregionModels
|
||||
-lregionModels \
|
||||
-lgenericPatchFields
|
||||
|
||||
@ -79,6 +79,7 @@ Usage
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "processorRunTimes.H"
|
||||
#include "domainDecomposition.H"
|
||||
#include "decompositionMethod.H"
|
||||
#include "argList.H"
|
||||
@ -114,14 +115,12 @@ namespace Foam
|
||||
void decomposeUniform
|
||||
(
|
||||
const bool copyUniform,
|
||||
const domainDecomposition& decomposition,
|
||||
const Time& processorDb,
|
||||
const bool distributeUniform,
|
||||
const Time& runTime,
|
||||
const Time& procRunTime,
|
||||
const word& regionDir = word::null
|
||||
)
|
||||
{
|
||||
const Time& runTime = decomposition.mesh().time();
|
||||
|
||||
// Any uniform data to copy/link?
|
||||
const fileName uniformDir(regionDir/"uniform");
|
||||
|
||||
if (fileHandler().isDir(runTime.timePath()/uniformDir))
|
||||
@ -131,9 +130,9 @@ void decomposeUniform
|
||||
<< endl;
|
||||
|
||||
const fileName timePath =
|
||||
fileHandler().filePath(processorDb.timePath());
|
||||
fileHandler().filePath(procRunTime.timePath());
|
||||
|
||||
if (copyUniform || decomposition.distributed())
|
||||
if (copyUniform || distributeUniform)
|
||||
{
|
||||
if (!fileHandler().exists(timePath/uniformDir))
|
||||
{
|
||||
@ -171,9 +170,9 @@ void decomposeUniform
|
||||
}
|
||||
|
||||
|
||||
void writeDecomposition(const domainDecomposition& decomposition)
|
||||
void writeDecomposition(const domainDecomposition& meshes)
|
||||
{
|
||||
const labelList& procIds = decomposition.cellToProc();
|
||||
const labelList& procIds = meshes.cellToProc();
|
||||
|
||||
// Write the decomposition as labelList for use with 'manual'
|
||||
// decomposition method.
|
||||
@ -182,8 +181,8 @@ void writeDecomposition(const domainDecomposition& decomposition)
|
||||
IOobject
|
||||
(
|
||||
"cellDecomposition",
|
||||
decomposition.mesh().facesInstance(),
|
||||
decomposition.mesh(),
|
||||
meshes.completeMesh().facesInstance(),
|
||||
meshes.completeMesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
@ -203,12 +202,12 @@ void writeDecomposition(const domainDecomposition& decomposition)
|
||||
IOobject
|
||||
(
|
||||
"cellDist",
|
||||
decomposition.mesh().time().timeName(),
|
||||
decomposition.mesh(),
|
||||
meshes.completeMesh().time().timeName(),
|
||||
meshes.completeMesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
decomposition.mesh(),
|
||||
meshes.completeMesh(),
|
||||
dimless,
|
||||
scalarField(scalarList(procIds))
|
||||
);
|
||||
@ -309,18 +308,20 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Set time from database
|
||||
#include "createTime.H"
|
||||
Info<< "Create time\n" << endl;
|
||||
processorRunTimes runTimes(Foam::Time::controlDictName, args);
|
||||
|
||||
// Allow override of time
|
||||
instantList times = timeSelector::selectIfPresent(runTime, args);
|
||||
const instantList times = runTimes.selectComplete(args);
|
||||
|
||||
// Get region names
|
||||
const wordList regionNames(selectRegionNames(args, runTime));
|
||||
const wordList regionNames =
|
||||
selectRegionNames(args, runTimes.completeTime());
|
||||
|
||||
// Handle existing decomposition directories
|
||||
{
|
||||
// Determine the processor count from the directories
|
||||
label nProcs = fileHandler().nProcs(runTime.path());
|
||||
label nProcs = fileHandler().nProcs(runTimes.completeTime().path());
|
||||
|
||||
if (forceOverwrite)
|
||||
{
|
||||
@ -339,7 +340,7 @@ int main(int argc, char *argv[])
|
||||
(
|
||||
fileHandler().readDir
|
||||
(
|
||||
runTime.path(),
|
||||
runTimes.completeTime().path(),
|
||||
fileType::directory
|
||||
)
|
||||
);
|
||||
@ -379,12 +380,17 @@ int main(int argc, char *argv[])
|
||||
<< " domains, use the -force option or manually" << nl
|
||||
<< "remove processor directories before decomposing. e.g.,"
|
||||
<< nl
|
||||
<< " rm -rf " << runTime.path().c_str() << "/processor*"
|
||||
<< " rm -rf " << runTimes.completeTime().path().c_str()
|
||||
<< "/processor*"
|
||||
<< nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the decomposition dictionary
|
||||
const dictionary decomposeParDict =
|
||||
decompositionMethod::decomposeParDict(runTimes.completeTime());
|
||||
|
||||
// Decompose all regions
|
||||
forAll(regionNames, regioni)
|
||||
{
|
||||
@ -394,12 +400,12 @@ int main(int argc, char *argv[])
|
||||
Info<< "\n\nDecomposing mesh " << regionName << nl << endl;
|
||||
|
||||
// Determine the existing processor count directly
|
||||
label nProcs = fileHandler().nProcs(runTime.path(), regionDir);
|
||||
const label nProcs =
|
||||
fileHandler().nProcs(runTimes.completeTime().path(), regionDir);
|
||||
|
||||
// Get requested numberOfSubdomains
|
||||
const label nDomains =
|
||||
decompositionMethod::decomposeParDict(runTime)
|
||||
.lookup<label>("numberOfSubdomains");
|
||||
decomposeParDict.lookup<label>("numberOfSubdomains");
|
||||
|
||||
// Give file handler a chance to determine the output directory
|
||||
const_cast<fileOperation&>(fileHandler()).setNProcs(nDomains);
|
||||
@ -421,74 +427,70 @@ int main(int argc, char *argv[])
|
||||
Info<< "Using existing processor directories" << nl;
|
||||
}
|
||||
|
||||
Info<< "Create mesh" << endl;
|
||||
fvMesh mesh
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
regionName,
|
||||
runTime.timeName(),
|
||||
runTime,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
false
|
||||
);
|
||||
// Get flag to determine whether or not to distribute uniform data
|
||||
const label distributeUniform =
|
||||
decomposeParDict.lookupOrDefault<bool>("distributed", false);
|
||||
|
||||
// Create decomposition
|
||||
domainDecomposition decomposition(mesh);
|
||||
// Create meshes
|
||||
Info<< "Create mesh" << endl;
|
||||
domainDecomposition meshes(runTimes, regionName);
|
||||
meshes.readComplete();
|
||||
|
||||
// Read or generate a decomposition as necessary
|
||||
if (decomposeFieldsOnly)
|
||||
{
|
||||
decomposition.read();
|
||||
meshes.readProcs();
|
||||
if (!copyZero)
|
||||
{
|
||||
meshes.readAddressing();
|
||||
meshes.readUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decomposition.decompose();
|
||||
decomposition.write(decomposeSets);
|
||||
if (writeCellDist)
|
||||
{
|
||||
writeDecomposition(decomposition);
|
||||
}
|
||||
meshes.decompose();
|
||||
meshes.writeProcs(decomposeSets);
|
||||
if (writeCellDist) writeDecomposition(meshes);
|
||||
fileHandler().flush();
|
||||
}
|
||||
|
||||
// Field maps. These are preserved if decomposing multiple times.
|
||||
PtrList<fvFieldDecomposer> fieldDecomposerList
|
||||
(
|
||||
decomposition.nProcs()
|
||||
meshes.nProcs()
|
||||
);
|
||||
PtrList<dimFieldDecomposer> dimFieldDecomposerList
|
||||
(
|
||||
decomposition.nProcs()
|
||||
meshes.nProcs()
|
||||
);
|
||||
PtrList<pointFieldDecomposer> pointFieldDecomposerList
|
||||
(
|
||||
decomposition.nProcs()
|
||||
meshes.nProcs()
|
||||
);
|
||||
|
||||
// Loop over all times
|
||||
forAll(times, timeI)
|
||||
{
|
||||
// Set the time
|
||||
runTime.setTime(times[timeI], timeI);
|
||||
decomposition.setTime(times[timeI], timeI);
|
||||
runTimes.setTime(times[timeI], timeI);
|
||||
|
||||
Info<< "Time = " << runTime.userTimeName() << endl;
|
||||
Info<< "Time = " << runTimes.completeTime().userTimeName() << endl;
|
||||
|
||||
// Update the mesh
|
||||
const fvMesh::readUpdateState state = mesh.readUpdate();
|
||||
// Update the meshes, if necessary
|
||||
fvMesh::readUpdateState state = fvMesh::UNCHANGED;
|
||||
if (!decomposeFieldsOnly || !copyZero)
|
||||
{
|
||||
state = meshes.readUpdate();
|
||||
}
|
||||
|
||||
// Update the decomposition
|
||||
// Write the mesh out, if necessary
|
||||
if (decomposeFieldsOnly)
|
||||
{
|
||||
decomposition.readUpdate();
|
||||
// Nothing to do
|
||||
}
|
||||
else if (state == fvMesh::POINTS_MOVED)
|
||||
{
|
||||
decomposition.writePoints();
|
||||
meshes.writeProcs(false);
|
||||
}
|
||||
else if
|
||||
(
|
||||
@ -496,12 +498,9 @@ int main(int argc, char *argv[])
|
||||
|| state == fvMesh::TOPO_PATCH_CHANGE
|
||||
)
|
||||
{
|
||||
decomposition.decompose();
|
||||
decomposition.write(decomposeSets);
|
||||
if (writeCellDist)
|
||||
{
|
||||
writeDecomposition(decomposition);
|
||||
}
|
||||
meshes.writeProcs(decomposeSets);
|
||||
if (writeCellDist) writeDecomposition(meshes);
|
||||
fileHandler().flush();
|
||||
}
|
||||
|
||||
// Clear the field maps if there has been topology change
|
||||
@ -511,7 +510,7 @@ int main(int argc, char *argv[])
|
||||
|| state == fvMesh::TOPO_PATCH_CHANGE
|
||||
)
|
||||
{
|
||||
for (label proci = 0; proci < decomposition.nProcs(); proci++)
|
||||
for (label proci = 0; proci < meshes.nProcs(); proci++)
|
||||
{
|
||||
fieldDecomposerList.set(proci, nullptr);
|
||||
dimFieldDecomposerList.set(proci, nullptr);
|
||||
@ -528,43 +527,38 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
// Copy the field files from the <time> directory to the
|
||||
// processor*/<time> directories without altering them
|
||||
const fileName completeTimePath =
|
||||
runTimes.completeTime().timePath();
|
||||
|
||||
fileName prevTimePath;
|
||||
for (label proci = 0; proci < decomposition.nProcs(); proci++)
|
||||
fileName prevProcTimePath;
|
||||
for (label proci = 0; proci < meshes.nProcs(); proci++)
|
||||
{
|
||||
Time processorDb
|
||||
(
|
||||
Time::controlDictName,
|
||||
args.rootPath(),
|
||||
args.caseName()
|
||||
/fileName(word("processor") + name(proci))
|
||||
);
|
||||
processorDb.setTime(runTime);
|
||||
const Time& procRunTime =
|
||||
meshes.procMeshes()[proci].time();
|
||||
|
||||
if (fileHandler().isDir(runTime.timePath()))
|
||||
if (fileHandler().isDir(completeTimePath))
|
||||
{
|
||||
const fileName timePath
|
||||
const fileName procTimePath
|
||||
(
|
||||
fileHandler().objectPath
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"",
|
||||
processorDb.timeName(),
|
||||
processorDb
|
||||
procRunTime.timeName(),
|
||||
procRunTime
|
||||
),
|
||||
word::null
|
||||
)
|
||||
);
|
||||
|
||||
if (timePath != prevTimePath)
|
||||
if (procTimePath != prevProcTimePath)
|
||||
{
|
||||
Info<< "Processor " << proci
|
||||
<< ": copying " << runTime.timePath() << nl
|
||||
<< " to " << timePath << endl;
|
||||
fileHandler().cp(runTime.timePath(), timePath);
|
||||
|
||||
prevTimePath = timePath;
|
||||
<< ": copying " << completeTimePath << nl
|
||||
<< " to " << procTimePath << endl;
|
||||
fileHandler().cp(completeTimePath, procTimePath);
|
||||
prevProcTimePath = procTimePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -574,49 +568,73 @@ int main(int argc, char *argv[])
|
||||
// Decompose the fields
|
||||
|
||||
// Search for list of objects for this time
|
||||
IOobjectList objects(mesh, runTime.timeName());
|
||||
IOobjectList objects
|
||||
(
|
||||
meshes.completeMesh(),
|
||||
runTimes.completeTime().timeName()
|
||||
);
|
||||
|
||||
// Construct the vol fields
|
||||
PtrList<volScalarField> volScalarFields;
|
||||
readFields(mesh, objects, volScalarFields);
|
||||
readFields(meshes.completeMesh(), objects, volScalarFields);
|
||||
PtrList<volVectorField> volVectorFields;
|
||||
readFields(mesh, objects, volVectorFields);
|
||||
readFields(meshes.completeMesh(), objects, volVectorFields);
|
||||
PtrList<volSphericalTensorField> volSphericalTensorFields;
|
||||
readFields(mesh, objects, volSphericalTensorFields);
|
||||
readFields
|
||||
(
|
||||
meshes.completeMesh(),
|
||||
objects,
|
||||
volSphericalTensorFields
|
||||
);
|
||||
PtrList<volSymmTensorField> volSymmTensorFields;
|
||||
readFields(mesh, objects, volSymmTensorFields);
|
||||
readFields(meshes.completeMesh(), objects, volSymmTensorFields);
|
||||
PtrList<volTensorField> volTensorFields;
|
||||
readFields(mesh, objects, volTensorFields);
|
||||
readFields(meshes.completeMesh(), objects, volTensorFields);
|
||||
|
||||
// Construct the dimensioned fields
|
||||
PtrList<DimensionedField<scalar, volMesh>> dimScalarFields;
|
||||
readFields(mesh, objects, dimScalarFields);
|
||||
readFields(meshes.completeMesh(), objects, dimScalarFields);
|
||||
PtrList<DimensionedField<vector, volMesh>> dimVectorFields;
|
||||
readFields(mesh, objects, dimVectorFields);
|
||||
readFields(meshes.completeMesh(), objects, dimVectorFields);
|
||||
PtrList<DimensionedField<sphericalTensor, volMesh>>
|
||||
dimSphericalTensorFields;
|
||||
readFields(mesh, objects, dimSphericalTensorFields);
|
||||
readFields
|
||||
(
|
||||
meshes.completeMesh(),
|
||||
objects,
|
||||
dimSphericalTensorFields
|
||||
);
|
||||
PtrList<DimensionedField<symmTensor, volMesh>>
|
||||
dimSymmTensorFields;
|
||||
readFields(mesh, objects, dimSymmTensorFields);
|
||||
readFields(meshes.completeMesh(), objects, dimSymmTensorFields);
|
||||
PtrList<DimensionedField<tensor, volMesh>> dimTensorFields;
|
||||
readFields(mesh, objects, dimTensorFields);
|
||||
readFields(meshes.completeMesh(), objects, dimTensorFields);
|
||||
|
||||
// Construct the surface fields
|
||||
PtrList<surfaceScalarField> surfaceScalarFields;
|
||||
readFields(mesh, objects, surfaceScalarFields);
|
||||
readFields(meshes.completeMesh(), objects, surfaceScalarFields);
|
||||
PtrList<surfaceVectorField> surfaceVectorFields;
|
||||
readFields(mesh, objects, surfaceVectorFields);
|
||||
readFields(meshes.completeMesh(), objects, surfaceVectorFields);
|
||||
PtrList<surfaceSphericalTensorField>
|
||||
surfaceSphericalTensorFields;
|
||||
readFields(mesh, objects, surfaceSphericalTensorFields);
|
||||
readFields
|
||||
(
|
||||
meshes.completeMesh(),
|
||||
objects,
|
||||
surfaceSphericalTensorFields
|
||||
);
|
||||
PtrList<surfaceSymmTensorField> surfaceSymmTensorFields;
|
||||
readFields(mesh, objects, surfaceSymmTensorFields);
|
||||
readFields
|
||||
(
|
||||
meshes.completeMesh(),
|
||||
objects,
|
||||
surfaceSymmTensorFields
|
||||
);
|
||||
PtrList<surfaceTensorField> surfaceTensorFields;
|
||||
readFields(mesh, objects, surfaceTensorFields);
|
||||
readFields(meshes.completeMesh(), objects, surfaceTensorFields);
|
||||
|
||||
// Construct the point fields
|
||||
const pointMesh& pMesh = pointMesh::New(mesh);
|
||||
const pointMesh& pMesh = pointMesh::New(meshes.completeMesh());
|
||||
PtrList<pointScalarField> pointScalarFields;
|
||||
readFields(pMesh, objects, pointScalarFields);
|
||||
PtrList<pointVectorField> pointVectorFields;
|
||||
@ -633,7 +651,7 @@ int main(int argc, char *argv[])
|
||||
(
|
||||
fileHandler().readDir
|
||||
(
|
||||
runTime.timePath()/cloud::prefix,
|
||||
runTimes.completeTime().timePath()/cloud::prefix,
|
||||
fileType::directory
|
||||
)
|
||||
);
|
||||
@ -672,8 +690,8 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
IOobjectList sprayObjs
|
||||
(
|
||||
mesh,
|
||||
runTime.timeName(),
|
||||
meshes.completeMesh(),
|
||||
runTimes.completeTime().timeName(),
|
||||
cloud::prefix/cloudDirs[i],
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
@ -695,7 +713,7 @@ int main(int argc, char *argv[])
|
||||
cloudI,
|
||||
new Cloud<indexedParticle>
|
||||
(
|
||||
mesh,
|
||||
meshes.completeMesh(),
|
||||
cloudDirs[i],
|
||||
false
|
||||
)
|
||||
@ -707,7 +725,7 @@ int main(int argc, char *argv[])
|
||||
cloudI,
|
||||
new List<SLList<indexedParticle*>*>
|
||||
(
|
||||
mesh.nCells(),
|
||||
meshes.completeMesh().nCells(),
|
||||
static_cast<SLList<indexedParticle*>*>(nullptr)
|
||||
)
|
||||
);
|
||||
@ -726,7 +744,11 @@ int main(int argc, char *argv[])
|
||||
label celli = iter().cell();
|
||||
|
||||
// Check
|
||||
if (celli < 0 || celli >= mesh.nCells())
|
||||
if
|
||||
(
|
||||
celli < 0
|
||||
|| celli >= meshes.completeMesh().nCells()
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Illegal cell number " << celli
|
||||
@ -735,10 +757,11 @@ int main(int argc, char *argv[])
|
||||
<< " at position "
|
||||
<< iter().position() << nl
|
||||
<< "Cell number should be between 0 and "
|
||||
<< mesh.nCells()-1 << nl
|
||||
<< meshes.completeMesh().nCells()-1 << nl
|
||||
<< "On this mesh the particle should"
|
||||
<< " be in cell "
|
||||
<< mesh.findCell(iter().position())
|
||||
<< meshes.completeMesh().findCell
|
||||
(iter().position())
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
@ -754,8 +777,8 @@ int main(int argc, char *argv[])
|
||||
// Read fields
|
||||
IOobjectList lagrangianObjects
|
||||
(
|
||||
mesh,
|
||||
runTime.timeName(),
|
||||
meshes.completeMesh(),
|
||||
runTimes.completeTime().timeName(),
|
||||
cloud::prefix/cloudDirs[cloudI],
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
@ -856,7 +879,7 @@ int main(int argc, char *argv[])
|
||||
Info<< endl;
|
||||
|
||||
// split the fields over processors
|
||||
for (label proci = 0; proci < decomposition.nProcs(); proci++)
|
||||
for (label proci = 0; proci < meshes.nProcs(); proci++)
|
||||
{
|
||||
Info<< "Processor " << proci << ": field transfer" << endl;
|
||||
|
||||
@ -869,10 +892,11 @@ int main(int argc, char *argv[])
|
||||
proci,
|
||||
new fvFieldDecomposer
|
||||
(
|
||||
mesh,
|
||||
decomposition.procMeshes()[proci],
|
||||
decomposition.procFaceAddressing()[proci],
|
||||
decomposition.procCellAddressing()[proci]
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes()[proci],
|
||||
meshes.procFaceAddressing()[proci],
|
||||
meshes.procCellAddressing()[proci],
|
||||
meshes.procFaceAddressingBf()[proci]
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -916,10 +940,10 @@ int main(int argc, char *argv[])
|
||||
proci,
|
||||
new dimFieldDecomposer
|
||||
(
|
||||
mesh,
|
||||
decomposition.procMeshes()[proci],
|
||||
decomposition.procFaceAddressing()[proci],
|
||||
decomposition.procCellAddressing()[proci]
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes()[proci],
|
||||
meshes.procFaceAddressing()[proci],
|
||||
meshes.procCellAddressing()[proci]
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -949,7 +973,7 @@ int main(int argc, char *argv[])
|
||||
)
|
||||
{
|
||||
const pointMesh& procPMesh =
|
||||
pointMesh::New(decomposition.procMeshes()[proci]);
|
||||
pointMesh::New(meshes.procMeshes()[proci]);
|
||||
|
||||
if (!pointFieldDecomposerList.set(proci))
|
||||
{
|
||||
@ -960,7 +984,7 @@ int main(int argc, char *argv[])
|
||||
(
|
||||
pMesh,
|
||||
procPMesh,
|
||||
decomposition.procPointAddressing()[proci]
|
||||
meshes.procPointAddressing()[proci]
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -989,10 +1013,10 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
lagrangianFieldDecomposer fieldDecomposer
|
||||
(
|
||||
mesh,
|
||||
decomposition.procMeshes()[proci],
|
||||
decomposition.procFaceAddressing()[proci],
|
||||
decomposition.procCellAddressing()[proci],
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes()[proci],
|
||||
meshes.procFaceAddressing()[proci],
|
||||
meshes.procCellAddressing()[proci],
|
||||
cloudDirs[cloudI],
|
||||
lagrangianPositions[cloudI],
|
||||
cellParticles[cloudI]
|
||||
@ -1069,8 +1093,9 @@ int main(int argc, char *argv[])
|
||||
decomposeUniform
|
||||
(
|
||||
copyUniform,
|
||||
decomposition,
|
||||
decomposition.procMeshes()[proci].time(),
|
||||
distributeUniform,
|
||||
runTimes.completeTime(),
|
||||
meshes.procMeshes()[proci].time(),
|
||||
regionDir
|
||||
);
|
||||
|
||||
@ -1082,8 +1107,9 @@ int main(int argc, char *argv[])
|
||||
decomposeUniform
|
||||
(
|
||||
copyUniform,
|
||||
decomposition,
|
||||
decomposition.procMeshes()[proci].time()
|
||||
distributeUniform,
|
||||
runTimes.completeTime(),
|
||||
meshes.procMeshes()[proci].time()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,241 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
|
||||
\\/ 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::domainDecomposition
|
||||
|
||||
Description
|
||||
Automatic domain decomposition class for finite-volume meshes
|
||||
|
||||
SourceFiles
|
||||
domainDecomposition.C
|
||||
decomposeMesh.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef domainDecomposition_H
|
||||
#define domainDecomposition_H
|
||||
|
||||
#include "fvMesh.H"
|
||||
#include "volFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class domainDecomposition Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class domainDecomposition
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Reference to the complete mesh
|
||||
const fvMesh& mesh_;
|
||||
|
||||
//- Number of processors in decomposition
|
||||
const label nProcs_;
|
||||
|
||||
//- Optional: points at the facesInstance
|
||||
autoPtr<pointIOField> facesInstancePointsPtr_;
|
||||
|
||||
//- Is the decomposition data to be distributed for each processor
|
||||
bool distributed_;
|
||||
|
||||
|
||||
// Processor mesh to complete mesh addressing
|
||||
|
||||
//- Labels of points for each processor
|
||||
labelListList procPointAddressing_;
|
||||
|
||||
//- Labels of faces for each processor
|
||||
// Note: Face turning index is stored as the sign on addressing
|
||||
// Only the processor boundary faces are affected: if the sign of
|
||||
// the index is negative, the processor face is the reverse of the
|
||||
// original face. In order to do this properly, all face
|
||||
// indices will be incremented by 1 and the decremented as
|
||||
// necessary to avoid the problem of face number zero having no
|
||||
// sign.
|
||||
List<DynamicList<label>> procFaceAddressing_;
|
||||
|
||||
//- Labels of cells for each processor
|
||||
labelListList procCellAddressing_;
|
||||
|
||||
|
||||
//- Processor times
|
||||
PtrList<Time> procRunTimes_;
|
||||
|
||||
//- Processor meshes
|
||||
PtrList<fvMesh> procMeshes_;
|
||||
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Call the decomposition method and return the processor index that
|
||||
// each cell is being distributed to
|
||||
labelList distributeCells();
|
||||
|
||||
//- Mark all elements with value or -2 if occur twice
|
||||
static void mark
|
||||
(
|
||||
const labelList& zoneElems,
|
||||
const label zoneI,
|
||||
labelList& elementToZone
|
||||
);
|
||||
|
||||
//- Add face to inter-processor patch
|
||||
void addInterProcFace
|
||||
(
|
||||
const label facei,
|
||||
const label ownerProc,
|
||||
const label nbrProc,
|
||||
List<Map<label>>&,
|
||||
List<DynamicList<DynamicList<label>>>&
|
||||
) const;
|
||||
|
||||
//- Generate sub patch info for processor cyclics
|
||||
template<class BinaryOp>
|
||||
inline void processInterCyclics
|
||||
(
|
||||
const labelList& cellToProc,
|
||||
const polyBoundaryMesh& patches,
|
||||
List<DynamicList<DynamicList<label>>>& interPatchFaces,
|
||||
List<Map<label>>& procNbrToInterPatch,
|
||||
List<labelListList>& subPatchIDs,
|
||||
List<labelListList>& subPatchStarts,
|
||||
bool owner,
|
||||
BinaryOp bop
|
||||
) const;
|
||||
|
||||
//- Validate that the decomposition has been generated or read
|
||||
void validate() const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("domainDecomposition");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from reference to fvMesh
|
||||
domainDecomposition(const fvMesh& mesh);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~domainDecomposition();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Access the global mesh
|
||||
const fvMesh& mesh() const
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
//- Return the number of processors in the decomposition
|
||||
label nProcs() const
|
||||
{
|
||||
return nProcs_;
|
||||
}
|
||||
|
||||
//- Is the decomposition data to be distributed for each processor?
|
||||
bool distributed() const
|
||||
{
|
||||
return distributed_;
|
||||
}
|
||||
|
||||
//- Access the labels of points for each processor
|
||||
const labelListList& procPointAddressing() const
|
||||
{
|
||||
validate();
|
||||
return procPointAddressing_;
|
||||
}
|
||||
|
||||
//- Access the labels of faces for each processor (see notes above)
|
||||
const List<DynamicList<label>>& procFaceAddressing() const
|
||||
{
|
||||
validate();
|
||||
return procFaceAddressing_;
|
||||
}
|
||||
|
||||
//- Access the labels of cells for each processor
|
||||
const labelListList& procCellAddressing() const
|
||||
{
|
||||
validate();
|
||||
return procCellAddressing_;
|
||||
}
|
||||
|
||||
//- Return the processor meshes
|
||||
const PtrList<fvMesh>& procMeshes() const
|
||||
{
|
||||
validate();
|
||||
return procMeshes_;
|
||||
}
|
||||
|
||||
//- Generate the decomposition
|
||||
void decompose();
|
||||
|
||||
//- Reset the time
|
||||
void setTime(const instant&, const label newIndex);
|
||||
|
||||
//- Read additional (faceInstance) points, if necessary
|
||||
void readPoints();
|
||||
|
||||
//- Read in the decomposition addressing
|
||||
void readAddressing();
|
||||
|
||||
//- Read in the meshes and the decomposition
|
||||
void read();
|
||||
|
||||
//- Read update the meshes and the decomposition
|
||||
fvMesh::readUpdateState readUpdate();
|
||||
|
||||
//- Return the distribution as an FV field for writing
|
||||
labelList cellToProc() const;
|
||||
|
||||
//- Read additional (faceInstance) points, if necessary
|
||||
void writePoints() const;
|
||||
|
||||
//- Write the decomposition addressing
|
||||
void writeAddressing() const;
|
||||
|
||||
//- Write the decomposed meshes and associated data
|
||||
void write(const bool decomposeSets) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -25,95 +25,38 @@ License
|
||||
|
||||
#include "fvFieldDecomposer.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::labelList Foam::fvFieldDecomposer::patchFieldDecomposer::alignAddressing
|
||||
Foam::label Foam::fvFieldDecomposer::completePatchID
|
||||
(
|
||||
const labelUList& addressingSlice,
|
||||
const label addressingOffset
|
||||
const label procPatchi
|
||||
) const
|
||||
{
|
||||
labelList addressing(addressingSlice.size());
|
||||
const fvPatch& procPatch = procMesh_.boundary()[procPatchi];
|
||||
|
||||
forAll(addressing, i)
|
||||
if (procPatchi < completeMesh_.boundary().size())
|
||||
{
|
||||
// Subtract one to align addressing.
|
||||
addressing[i] = addressingSlice[i] - (addressingOffset + 1);
|
||||
return procPatchi;
|
||||
}
|
||||
else if (isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
return refCast<const processorCyclicFvPatch>(procPatch).referPatchID();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return addressing;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fvFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
|
||||
(
|
||||
const labelUList& addressingSlice,
|
||||
const label addressingOffset
|
||||
const labelUList& addressing
|
||||
)
|
||||
:
|
||||
labelList(alignAddressing(addressingSlice, addressingOffset)),
|
||||
directFvPatchFieldMapper(static_cast<const labelList&>(*this))
|
||||
{}
|
||||
|
||||
|
||||
Foam::labelList Foam::fvFieldDecomposer::processorVolPatchFieldDecomposer::
|
||||
alignAddressing
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelUList& addressingSlice
|
||||
) const
|
||||
{
|
||||
labelList addressing(addressingSlice.size());
|
||||
|
||||
const labelList& own = mesh.faceOwner();
|
||||
const labelList& neighb = mesh.faceNeighbour();
|
||||
|
||||
forAll(addressing, i)
|
||||
{
|
||||
// Subtract one to align addressing.
|
||||
label ai = mag(addressingSlice[i]) - 1;
|
||||
|
||||
if (ai < neighb.size())
|
||||
{
|
||||
// This is a regular face. it has been an internal face
|
||||
// of the original mesh and now it has become a face
|
||||
// on the parallel boundary.
|
||||
// Give face the value of the neighbour.
|
||||
|
||||
if (addressingSlice[i] >= 0)
|
||||
{
|
||||
// I have the owner so use the neighbour value
|
||||
addressing[i] = neighb[ai];
|
||||
}
|
||||
else
|
||||
{
|
||||
addressing[i] = own[ai];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a face that used to be on a cyclic boundary
|
||||
// but has now become a parallel patch face. I cannot
|
||||
// do the interpolation properly (I would need to look
|
||||
// up the different (face) list of data), so I will
|
||||
// just grab the value from the owner cell
|
||||
|
||||
addressing[i] = own[ai];
|
||||
}
|
||||
}
|
||||
|
||||
return addressing;
|
||||
}
|
||||
|
||||
|
||||
Foam::fvFieldDecomposer::processorVolPatchFieldDecomposer::
|
||||
processorVolPatchFieldDecomposer
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelUList& addressingSlice
|
||||
)
|
||||
:
|
||||
labelList(alignAddressing(mesh, addressingSlice)),
|
||||
labelList(mag(addressing) - 1),
|
||||
directFvPatchFieldMapper(static_cast<const labelList&>(*this))
|
||||
{}
|
||||
|
||||
@ -123,34 +66,22 @@ Foam::fvFieldDecomposer::fvFieldDecomposer
|
||||
const fvMesh& completeMesh,
|
||||
const fvMesh& procMesh,
|
||||
const labelList& faceAddressing,
|
||||
const labelList& cellAddressing
|
||||
const labelList& cellAddressing,
|
||||
const surfaceLabelField::Boundary& faceAddressingBf
|
||||
)
|
||||
:
|
||||
completeMesh_(completeMesh),
|
||||
procMesh_(procMesh),
|
||||
faceAddressing_(faceAddressing),
|
||||
cellAddressing_(cellAddressing),
|
||||
patchFieldDecomposers_(procMesh_.boundary().size()),
|
||||
processorVolPatchFieldDecomposers_(procMesh_.boundary().size())
|
||||
faceAddressingBf_(faceAddressingBf),
|
||||
patchFieldDecomposers_(procMesh_.boundary().size())
|
||||
{
|
||||
forAll(procMesh_.boundary(), procPatchi)
|
||||
{
|
||||
const fvPatch& procPatch = procMesh.boundary()[procPatchi];
|
||||
const label completePatchi = completePatchID(procPatchi);
|
||||
|
||||
// Determine the index of the corresponding complete patch
|
||||
label completePatchi = -1;
|
||||
if (procPatchi < completeMesh_.boundary().size())
|
||||
{
|
||||
completePatchi = procPatchi;
|
||||
}
|
||||
else if (isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
completePatchi =
|
||||
refCast<const processorCyclicPolyPatch>
|
||||
(procPatch.patch()).referPatchID();
|
||||
}
|
||||
|
||||
// If there is a corresponding complete patch, then create a mapper
|
||||
// If there is a corresponding complete patch then create a patch mapper
|
||||
if (completePatchi >= 0)
|
||||
{
|
||||
patchFieldDecomposers_.set
|
||||
@ -158,22 +89,7 @@ Foam::fvFieldDecomposer::fvFieldDecomposer
|
||||
procPatchi,
|
||||
new patchFieldDecomposer
|
||||
(
|
||||
procPatch.patchSlice(faceAddressing_),
|
||||
completeMesh_.boundaryMesh()[completePatchi].start()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// If this is a processor patch then create a processor mapper
|
||||
if (procPatchi >= completeMesh_.boundary().size())
|
||||
{
|
||||
processorVolPatchFieldDecomposers_.set
|
||||
(
|
||||
procPatchi,
|
||||
new processorVolPatchFieldDecomposer
|
||||
(
|
||||
completeMesh_,
|
||||
procPatch.patchSlice(faceAddressing_)
|
||||
faceAddressingBf[completePatchi]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -63,52 +63,12 @@ public:
|
||||
public labelList,
|
||||
public directFvPatchFieldMapper
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
labelList alignAddressing
|
||||
(
|
||||
const labelUList& addressingSlice,
|
||||
const label addressingOffset
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given addressing
|
||||
patchFieldDecomposer
|
||||
(
|
||||
const labelUList& addressingSlice,
|
||||
const label addressingOffset
|
||||
);
|
||||
};
|
||||
|
||||
//- Processor patch field decomposer class. Maps either owner or
|
||||
// neighbour data (no interpolate anymore - processorFvPatchField
|
||||
// holds neighbour data)
|
||||
class processorVolPatchFieldDecomposer
|
||||
:
|
||||
public labelList,
|
||||
public directFvPatchFieldMapper
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
labelList alignAddressing
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelUList& addressingSlice
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Construct given addressing
|
||||
processorVolPatchFieldDecomposer
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelUList& addressingSlice
|
||||
);
|
||||
patchFieldDecomposer(const labelUList& addressing);
|
||||
};
|
||||
|
||||
|
||||
@ -128,23 +88,35 @@ private:
|
||||
//- Reference to cell addressing
|
||||
const labelList& cellAddressing_;
|
||||
|
||||
//- Reference to face addressing boundary field
|
||||
const surfaceLabelField::Boundary& faceAddressingBf_;
|
||||
|
||||
//- List of patch field decomposers
|
||||
PtrList<patchFieldDecomposer> patchFieldDecomposers_;
|
||||
|
||||
//- ...
|
||||
PtrList<processorVolPatchFieldDecomposer>
|
||||
processorVolPatchFieldDecomposers_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Helper: map & optionally flip a (face) field
|
||||
//- Convert a processor patch to the corresponding complete patch index
|
||||
label completePatchID(const label procPatchi) const;
|
||||
|
||||
//- Map cell values to faces
|
||||
template<class Type>
|
||||
static tmp<Field<Type>> mapField
|
||||
static tmp<Field<Type>> mapCellToFace
|
||||
(
|
||||
const labelUList& owner,
|
||||
const labelUList& neighbour,
|
||||
const Field<Type>& field,
|
||||
const labelUList& addressing
|
||||
);
|
||||
|
||||
//- Map face values to faces
|
||||
template<class Type>
|
||||
static tmp<Field<Type>> mapFaceToFace
|
||||
(
|
||||
const Field<Type>& field,
|
||||
const labelUList& mapAndSign,
|
||||
const bool applyFlip
|
||||
const labelUList& addressing,
|
||||
const bool isFlux
|
||||
);
|
||||
|
||||
|
||||
@ -158,7 +130,8 @@ public:
|
||||
const fvMesh& completeMesh,
|
||||
const fvMesh& procMesh,
|
||||
const labelList& faceAddressing,
|
||||
const labelList& cellAddressing
|
||||
const labelList& cellAddressing,
|
||||
const surfaceLabelField::Boundary& faceAddressingBf
|
||||
);
|
||||
|
||||
//- Disallow default bitwise copy construction
|
||||
|
||||
@ -33,35 +33,50 @@ License
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>> Foam::fvFieldDecomposer::mapField
|
||||
Foam::tmp<Foam::Field<Type>> Foam::fvFieldDecomposer::mapCellToFace
|
||||
(
|
||||
const labelUList& owner,
|
||||
const labelUList& neighbour,
|
||||
const Field<Type>& field,
|
||||
const labelUList& mapAndSign,
|
||||
const bool applyFlip
|
||||
const labelUList& addressing
|
||||
)
|
||||
{
|
||||
tmp<Field<Type>> tfld(new Field<Type>(mapAndSign.size()));
|
||||
tmp<Field<Type>> tfld(new Field<Type>(addressing.size()));
|
||||
Field<Type>& fld = tfld.ref();
|
||||
|
||||
if (applyFlip)
|
||||
forAll(addressing, i)
|
||||
{
|
||||
forAll(mapAndSign, i)
|
||||
{
|
||||
if (mapAndSign[i] < 0)
|
||||
{
|
||||
fld[i] = -field[-mapAndSign[i] - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
fld[i] = field[mapAndSign[i] - 1];
|
||||
}
|
||||
}
|
||||
fld[i] =
|
||||
field
|
||||
[
|
||||
addressing[i] > 0
|
||||
? neighbour[addressing[i] - 1]
|
||||
: owner[- addressing[i] + 1]
|
||||
];
|
||||
}
|
||||
else
|
||||
|
||||
return tfld;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type>> Foam::fvFieldDecomposer::mapFaceToFace
|
||||
(
|
||||
const Field<Type>& field,
|
||||
const labelUList& addressing,
|
||||
const bool isFlux
|
||||
)
|
||||
{
|
||||
tmp<Field<Type>> tfld(new Field<Type>(addressing.size()));
|
||||
Field<Type>& fld = tfld.ref();
|
||||
|
||||
forAll(addressing, i)
|
||||
{
|
||||
// Ignore face flipping
|
||||
fld.map(field, mag(mapAndSign) - 1);
|
||||
fld[i] =
|
||||
(isFlux && addressing[i] < 0 ? -1 : +1)
|
||||
*field[mag(addressing[i]) - 1];
|
||||
}
|
||||
|
||||
return tfld;
|
||||
}
|
||||
|
||||
@ -74,9 +89,8 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
const bool allowUnknownPatchFields
|
||||
) const
|
||||
{
|
||||
// 1. Create the complete field with dummy patch fields
|
||||
// Create dummy patch fields
|
||||
PtrList<fvPatchField<Type>> patchFields(procMesh_.boundary().size());
|
||||
|
||||
forAll(procMesh_.boundary(), procPatchi)
|
||||
{
|
||||
patchFields.set
|
||||
@ -91,7 +105,7 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
);
|
||||
}
|
||||
|
||||
// Create the field for the processor
|
||||
// Create the processor field with the dummy patch fields
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh>> tresF
|
||||
(
|
||||
new GeometricField<Type, fvPatchField, volMesh>
|
||||
@ -113,35 +127,17 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
);
|
||||
GeometricField<Type, fvPatchField, volMesh>& resF = tresF.ref();
|
||||
|
||||
|
||||
// 2. Change the fvPatchFields to the correct type using a mapper
|
||||
// constructor (with reference to the now correct internal field)
|
||||
|
||||
// Change the patch fields to the correct type using a mapper constructor
|
||||
// (with reference to the now correct internal field)
|
||||
typename GeometricField<Type, fvPatchField, volMesh>::
|
||||
Boundary& bf = resF.boundaryFieldRef();
|
||||
|
||||
forAll(bf, procPatchi)
|
||||
{
|
||||
const fvPatch& procPatch = procMesh_.boundary()[procPatchi];
|
||||
|
||||
// Determine the index of the corresponding complete patch
|
||||
label completePatchi = -1;
|
||||
if (procPatchi < completeMesh_.boundary().size())
|
||||
{
|
||||
completePatchi = procPatchi;
|
||||
}
|
||||
else if (isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
const label referPatchi =
|
||||
refCast<const processorCyclicPolyPatch>
|
||||
(procPatch.patch()).referPatchID();
|
||||
if (field.boundaryField()[referPatchi].overridesConstraint())
|
||||
{
|
||||
completePatchi = referPatchi;
|
||||
}
|
||||
}
|
||||
const label completePatchi = completePatchID(procPatchi);
|
||||
|
||||
if (completePatchi != -1)
|
||||
if (completePatchi == procPatchi)
|
||||
{
|
||||
bf.set
|
||||
(
|
||||
@ -157,6 +153,10 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
}
|
||||
else if (isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
const label nbrCompletePatchi =
|
||||
refCast<const processorCyclicFvPatch>(procPatch)
|
||||
.referPatch().nbrPatchID();
|
||||
|
||||
bf.set
|
||||
(
|
||||
procPatchi,
|
||||
@ -164,9 +164,12 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
(
|
||||
procPatch,
|
||||
resF(),
|
||||
processorVolPatchFieldDecomposers_[procPatchi]
|
||||
mapCellToFace
|
||||
(
|
||||
field.primitiveField()
|
||||
labelUList(),
|
||||
completeMesh_.lduAddr().patchAddr(nbrCompletePatchi),
|
||||
field.primitiveField(),
|
||||
faceAddressingBf_[procPatchi]
|
||||
)
|
||||
)
|
||||
);
|
||||
@ -180,9 +183,12 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
(
|
||||
procPatch,
|
||||
resF(),
|
||||
processorVolPatchFieldDecomposers_[procPatchi]
|
||||
mapCellToFace
|
||||
(
|
||||
field.primitiveField()
|
||||
completeMesh_.owner(),
|
||||
completeMesh_.neighbour(),
|
||||
field.primitiveField(),
|
||||
faceAddressingBf_[procPatchi]
|
||||
)
|
||||
)
|
||||
);
|
||||
@ -206,7 +212,6 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
}
|
||||
}
|
||||
|
||||
// Create the field for the processor
|
||||
return tresF;
|
||||
}
|
||||
|
||||
@ -218,34 +223,14 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>& field
|
||||
) const
|
||||
{
|
||||
// Problem with addressing when a processor patch picks up both internal
|
||||
// faces and faces from cyclic boundaries. This is a bit of a hack, but
|
||||
// I cannot find a better solution without making the internal storage
|
||||
// mechanism for surfaceFields correspond to the one of faces in polyMesh
|
||||
// (i.e. using slices)
|
||||
Field<Type> allFaceField(field.mesh().nFaces());
|
||||
const SubList<label> faceAddressingIf
|
||||
(
|
||||
faceAddressing_,
|
||||
procMesh_.nInternalFaces()
|
||||
);
|
||||
|
||||
forAll(field.primitiveField(), i)
|
||||
{
|
||||
allFaceField[i] = field.primitiveField()[i];
|
||||
}
|
||||
|
||||
forAll(field.boundaryField(), patchi)
|
||||
{
|
||||
const Field<Type> & p = field.boundaryField()[patchi];
|
||||
|
||||
const label patchStart = field.mesh().boundaryMesh()[patchi].start();
|
||||
|
||||
forAll(p, i)
|
||||
{
|
||||
allFaceField[patchStart + i] = p[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 1. Create the complete field with dummy patch fields
|
||||
// Create dummy patch fields
|
||||
PtrList<fvsPatchField<Type>> patchFields(procMesh_.boundary().size());
|
||||
|
||||
forAll(procMesh_.boundary(), procPatchi)
|
||||
{
|
||||
patchFields.set
|
||||
@ -260,6 +245,7 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
);
|
||||
}
|
||||
|
||||
// Create the processor field with the dummy patch fields
|
||||
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>> tresF
|
||||
(
|
||||
new GeometricField<Type, fvsPatchField, surfaceMesh>
|
||||
@ -275,14 +261,10 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
),
|
||||
procMesh_,
|
||||
field.dimensions(),
|
||||
mapField
|
||||
mapFaceToFace
|
||||
(
|
||||
field,
|
||||
labelList::subList
|
||||
(
|
||||
faceAddressing_,
|
||||
procMesh_.nInternalFaces()
|
||||
),
|
||||
faceAddressingIf,
|
||||
isFlux(field)
|
||||
),
|
||||
patchFields
|
||||
@ -290,18 +272,17 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
);
|
||||
GeometricField<Type, fvsPatchField, surfaceMesh>& resF = tresF.ref();
|
||||
|
||||
|
||||
// 2. Change the fvsPatchFields to the correct type using a mapper
|
||||
// constructor (with reference to the now correct internal field)
|
||||
|
||||
// Change the patch fields to the correct type using a mapper constructor
|
||||
// (with reference to the now correct internal field)
|
||||
typename GeometricField<Type, fvsPatchField, surfaceMesh>::
|
||||
Boundary& bf = resF.boundaryFieldRef();
|
||||
|
||||
forAll(procMesh_.boundary(), procPatchi)
|
||||
{
|
||||
const fvPatch& procPatch = procMesh_.boundary()[procPatchi];
|
||||
|
||||
if (procPatchi < completeMesh_.boundary().size())
|
||||
const label completePatchi = completePatchID(procPatchi);
|
||||
|
||||
if (completePatchi == procPatchi)
|
||||
{
|
||||
bf.set
|
||||
(
|
||||
@ -317,7 +298,6 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
}
|
||||
else if (isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
// Do our own mapping. Avoids a lot of mapping complexity.
|
||||
bf.set
|
||||
(
|
||||
procPatchi,
|
||||
@ -325,10 +305,10 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
(
|
||||
procPatch,
|
||||
resF(),
|
||||
mapField
|
||||
mapFaceToFace
|
||||
(
|
||||
allFaceField,
|
||||
procPatch.patchSlice(faceAddressing_),
|
||||
field.boundaryField()[completePatchi],
|
||||
faceAddressingBf_[procPatchi],
|
||||
isFlux(field)
|
||||
)
|
||||
)
|
||||
@ -336,7 +316,6 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
}
|
||||
else if (isA<processorFvPatch>(procPatch))
|
||||
{
|
||||
// Do our own mapping. Avoids a lot of mapping complexity.
|
||||
bf.set
|
||||
(
|
||||
procPatchi,
|
||||
@ -344,10 +323,10 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
(
|
||||
procPatch,
|
||||
resF(),
|
||||
mapField
|
||||
mapFaceToFace
|
||||
(
|
||||
allFaceField,
|
||||
procPatch.patchSlice(faceAddressing_),
|
||||
field.primitiveField(),
|
||||
faceAddressingBf_[procPatchi],
|
||||
isFlux(field)
|
||||
)
|
||||
)
|
||||
@ -360,7 +339,6 @@ Foam::fvFieldDecomposer::decomposeField
|
||||
}
|
||||
}
|
||||
|
||||
// Create the field for the processor
|
||||
return tresF;
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
reconstructPar.C
|
||||
fvFieldReconstructor.C
|
||||
pointFieldReconstructor.C
|
||||
reconstructLagrangianPositions.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/reconstructPar
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
EXE_INC = \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
||||
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/parallel/reconstruct/reconstruct/lnInclude \
|
||||
-I$(LIB_SRC)/parallel/parallel/lnInclude \
|
||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
||||
-I$(LIB_SRC)/regionModels/regionModel/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lfiniteVolume \
|
||||
-lgenericPatchFields \
|
||||
-llagrangian \
|
||||
-ldynamicMesh \
|
||||
-lmeshTools \
|
||||
-lreconstruct \
|
||||
-lregionModels
|
||||
-lparallel \
|
||||
-llagrangian \
|
||||
-lregionModels \
|
||||
-lgenericPatchFields
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
{
|
||||
// Foam version 2.1 changes the addressing of faces in faceProcAddressing
|
||||
// The following code checks and modifies the addressing for cases where
|
||||
// the decomposition has been done with the foam2.0 and earlier tools, but
|
||||
// the reconstruction is attempted with version 2.1 or later
|
||||
|
||||
label minFaceIndex = labelMax;
|
||||
|
||||
PtrList<labelIOList>& faceProcAddressing = procMeshes.faceProcAddressing();
|
||||
|
||||
forAll(faceProcAddressing, proci)
|
||||
{
|
||||
const labelList& curFaceAddr = faceProcAddressing[proci];
|
||||
|
||||
forAll(curFaceAddr, facei)
|
||||
{
|
||||
if (mag(curFaceAddr[facei]) < minFaceIndex)
|
||||
{
|
||||
minFaceIndex = mag(curFaceAddr[facei]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minFaceIndex < 1)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "parallel decomposition addressing." << endl
|
||||
<< "It looks like you are trying to reconstruct the case "
|
||||
<< "decomposed with an earlier version of FOAM, which could\n"
|
||||
<< "potentially cause compatibility problems. The code will "
|
||||
<< "attempt to update the addressing automatically; in case of\n"
|
||||
<< "failure, please repeat the decomposition of the case using "
|
||||
<< "the current version fo decomposePar"
|
||||
<< endl;
|
||||
|
||||
forAll(faceProcAddressing, proci)
|
||||
{
|
||||
labelList& curFaceAddr = faceProcAddressing[proci];
|
||||
|
||||
forAll(curFaceAddr, facei)
|
||||
{
|
||||
curFaceAddr[facei] += sign(curFaceAddr[facei]);
|
||||
}
|
||||
|
||||
faceProcAddressing[proci].write();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
|
||||
\\/ 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 "fvFieldReconstructor.H"
|
||||
#include "processorCyclicFvPatch.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::label Foam::fvFieldReconstructor::completePatchID
|
||||
(
|
||||
const label proci,
|
||||
const label procPatchi
|
||||
) const
|
||||
{
|
||||
const fvPatch& procPatch = procMeshes_[proci].boundary()[procPatchi];
|
||||
|
||||
if (procPatchi < completeMesh_.boundary().size())
|
||||
{
|
||||
return procPatchi;
|
||||
}
|
||||
else if (isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
return refCast<const processorCyclicFvPatch>(procPatch).referPatchID();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fvFieldReconstructor::fvFieldReconstructor
|
||||
(
|
||||
const fvMesh& completeMesh,
|
||||
const PtrList<fvMesh>& procMeshes,
|
||||
const labelListList& faceProcAddressing,
|
||||
const labelListList& cellProcAddressing,
|
||||
const PtrList<surfaceLabelField::Boundary>& faceProcAddressingBf
|
||||
)
|
||||
:
|
||||
completeMesh_(completeMesh),
|
||||
procMeshes_(procMeshes),
|
||||
faceProcAddressing_(faceProcAddressing),
|
||||
cellProcAddressing_(cellProcAddressing),
|
||||
faceProcAddressingBf_(faceProcAddressingBf),
|
||||
nReconstructed_(0)
|
||||
{
|
||||
forAll(procMeshes_, proci)
|
||||
{
|
||||
const fvMesh& procMesh = procMeshes_[proci];
|
||||
|
||||
if
|
||||
(
|
||||
faceProcAddressing[proci].size() != procMesh.nFaces()
|
||||
|| cellProcAddressing[proci].size() != procMesh.nCells()
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Size of maps does not correspond to size of mesh"
|
||||
<< " for processor " << proci << endl
|
||||
<< "faceProcAddressing : " << faceProcAddressing[proci].size()
|
||||
<< " nFaces : " << procMesh.nFaces() << endl
|
||||
<< "cellProcAddressing : " << cellProcAddressing[proci].size()
|
||||
<< " nCell : " << procMesh.nCells() << endl
|
||||
<< " nFaces : " << procMesh.boundary().size()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,229 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
|
||||
\\/ 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::fvFieldReconstructor
|
||||
|
||||
Description
|
||||
Finite volume reconstructor for volume and surface fields.
|
||||
|
||||
SourceFiles
|
||||
fvFieldReconstructor.C
|
||||
fvFieldReconstructorReconstructFields.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef fvFieldReconstructor_H
|
||||
#define fvFieldReconstructor_H
|
||||
|
||||
#include "PtrList.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "fvPatchFieldMapper.H"
|
||||
#include "setSizeFieldMapper.H"
|
||||
#include "labelIOList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class fvFieldReconstructor Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class fvFieldReconstructor
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Reconstructed mesh reference
|
||||
const fvMesh& completeMesh_;
|
||||
|
||||
//- List of processor meshes
|
||||
const PtrList<fvMesh>& procMeshes_;
|
||||
|
||||
//- List of processor face addressing lists
|
||||
const labelListList& faceProcAddressing_;
|
||||
|
||||
//- List of processor cell addressing lists
|
||||
const labelListList& cellProcAddressing_;
|
||||
|
||||
//- Boundary field of face addressing
|
||||
const PtrList<surfaceLabelField::Boundary>& faceProcAddressingBf_;
|
||||
|
||||
//- Number of fields reconstructed
|
||||
label nReconstructed_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Convert a processor patch to the corresponding complete patch index
|
||||
label completePatchID(const label proci, const label procPatchi) const;
|
||||
|
||||
//- ...
|
||||
template<class Type>
|
||||
static void rmapFaceToFace
|
||||
(
|
||||
Field<Type>& toField,
|
||||
const Field<Type>& fromField,
|
||||
const labelUList& addressing,
|
||||
const bool isFlux
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Mapper for sizing only - does not do any actual mapping.
|
||||
class fvPatchFieldReconstructor
|
||||
:
|
||||
public fvPatchFieldMapper,
|
||||
public setSizeFieldMapper
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given size
|
||||
fvPatchFieldReconstructor(const label size)
|
||||
:
|
||||
setSizeFieldMapper(size)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
fvFieldReconstructor
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const PtrList<fvMesh>& procMeshes,
|
||||
const labelListList& faceProcAddressing,
|
||||
const labelListList& cellProcAddressing,
|
||||
const PtrList<surfaceLabelField::Boundary>& faceProcAddressingBf
|
||||
);
|
||||
|
||||
//- Disallow default bitwise copy construction
|
||||
fvFieldReconstructor(const fvFieldReconstructor&) = delete;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return number of fields reconstructed
|
||||
label nReconstructed() const
|
||||
{
|
||||
return nReconstructed_;
|
||||
}
|
||||
|
||||
//- Reconstruct volume internal field
|
||||
template<class Type>
|
||||
tmp<DimensionedField<Type, volMesh>>
|
||||
reconstructFvVolumeInternalField
|
||||
(
|
||||
const IOobject& fieldIoObject,
|
||||
const PtrList<DimensionedField<Type, volMesh>>& procFields
|
||||
) const;
|
||||
|
||||
//- Read and reconstruct volume internal field
|
||||
template<class Type>
|
||||
tmp<DimensionedField<Type, volMesh>>
|
||||
reconstructFvVolumeInternalField(const IOobject& fieldIoObject) const;
|
||||
|
||||
|
||||
//- Reconstruct volume field
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh>>
|
||||
reconstructFvVolumeField
|
||||
(
|
||||
const IOobject& fieldIoObject,
|
||||
const PtrList<GeometricField<Type, fvPatchField, volMesh>>&
|
||||
) const;
|
||||
|
||||
//- Read and reconstruct volume field
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh>>
|
||||
reconstructFvVolumeField(const IOobject& fieldIoObject) const;
|
||||
|
||||
|
||||
//- Reconstruct surface field
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
|
||||
reconstructFvSurfaceField
|
||||
(
|
||||
const IOobject& fieldIoObject,
|
||||
const PtrList<GeometricField<Type, fvsPatchField, surfaceMesh>>&
|
||||
) const;
|
||||
|
||||
//- Read and reconstruct surface field
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
|
||||
reconstructFvSurfaceField(const IOobject& fieldIoObject) const;
|
||||
|
||||
//- Read, reconstruct and write all/selected volume internal fields
|
||||
template<class Type>
|
||||
void reconstructFvVolumeInternalFields
|
||||
(
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
);
|
||||
|
||||
//- Read, reconstruct and write all/selected volume fields
|
||||
template<class Type>
|
||||
void reconstructFvVolumeFields
|
||||
(
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
);
|
||||
|
||||
//- Read, reconstruct and write all/selected surface fields
|
||||
template<class Type>
|
||||
void reconstructFvSurfaceFields
|
||||
(
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
);
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const fvFieldReconstructor&) = delete;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "fvFieldReconstructorReconstructFields.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,556 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
|
||||
\\/ 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 "fvFieldReconstructor.H"
|
||||
#include "Time.H"
|
||||
#include "PtrList.H"
|
||||
#include "fvPatchFields.H"
|
||||
#include "emptyFvPatch.H"
|
||||
#include "emptyFvPatchField.H"
|
||||
#include "emptyFvsPatchField.H"
|
||||
#include "processorCyclicFvPatch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::fvFieldReconstructor::rmapFaceToFace
|
||||
(
|
||||
Field<Type>& toField,
|
||||
const Field<Type>& fromField,
|
||||
const labelUList& addressing,
|
||||
const bool isFlux
|
||||
)
|
||||
{
|
||||
forAll(addressing, i)
|
||||
{
|
||||
toField[mag(addressing[i]) - 1] =
|
||||
(isFlux && addressing[i] < 0 ? -1 : +1)*fromField[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh>>
|
||||
Foam::fvFieldReconstructor::reconstructFvVolumeInternalField
|
||||
(
|
||||
const IOobject& fieldIoObject,
|
||||
const PtrList<DimensionedField<Type, volMesh>>& procFields
|
||||
) const
|
||||
{
|
||||
// Create the internalField
|
||||
Field<Type> internalField(completeMesh_.nCells());
|
||||
|
||||
forAll(procMeshes_, proci)
|
||||
{
|
||||
const DimensionedField<Type, volMesh>& procField = procFields[proci];
|
||||
|
||||
// Set the cell values in the reconstructed field
|
||||
internalField.rmap
|
||||
(
|
||||
procField.field(),
|
||||
cellProcAddressing_[proci]
|
||||
);
|
||||
}
|
||||
|
||||
return tmp<DimensionedField<Type, volMesh>>
|
||||
(
|
||||
new DimensionedField<Type, volMesh>
|
||||
(
|
||||
fieldIoObject,
|
||||
completeMesh_,
|
||||
procFields[0].dimensions(),
|
||||
internalField
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::DimensionedField<Type, Foam::volMesh>>
|
||||
Foam::fvFieldReconstructor::reconstructFvVolumeInternalField
|
||||
(
|
||||
const IOobject& fieldIoObject
|
||||
) const
|
||||
{
|
||||
PtrList<DimensionedField<Type, volMesh>>
|
||||
procFields(procMeshes_.size());
|
||||
|
||||
forAll(procMeshes_, proci)
|
||||
{
|
||||
procFields.set
|
||||
(
|
||||
proci,
|
||||
new DimensionedField<Type, volMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldIoObject.name(),
|
||||
procMeshes_[proci].time().timeName(),
|
||||
procMeshes_[proci],
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
procMeshes_[proci]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return reconstructFvVolumeInternalField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldIoObject.name(),
|
||||
completeMesh_.time().timeName(),
|
||||
completeMesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
procFields
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
|
||||
Foam::fvFieldReconstructor::reconstructFvVolumeField
|
||||
(
|
||||
const IOobject& fieldIoObject,
|
||||
const PtrList<GeometricField<Type, fvPatchField, volMesh>>& procFields
|
||||
) const
|
||||
{
|
||||
// Create the internalField
|
||||
Field<Type> internalField(completeMesh_.nCells());
|
||||
|
||||
// Create the patch fields
|
||||
PtrList<fvPatchField<Type>> patchFields(completeMesh_.boundary().size());
|
||||
|
||||
forAll(procFields, proci)
|
||||
{
|
||||
const GeometricField<Type, fvPatchField, volMesh>& procField =
|
||||
procFields[proci];
|
||||
|
||||
// Set the cell values in the reconstructed field
|
||||
internalField.rmap
|
||||
(
|
||||
procField.primitiveField(),
|
||||
cellProcAddressing_[proci]
|
||||
);
|
||||
|
||||
// Set the boundary patch values in the reconstructed field
|
||||
forAll(procField.boundaryField(), procPatchi)
|
||||
{
|
||||
const fvPatch& procPatch =
|
||||
procMeshes_[proci].boundary()[procPatchi];
|
||||
|
||||
const label completePatchi = completePatchID(proci, procPatchi);
|
||||
|
||||
if (completePatchi == procPatchi)
|
||||
{
|
||||
if (!patchFields(completePatchi))
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
completePatchi,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
procField.boundaryField()[procPatchi],
|
||||
completeMesh_.boundary()[completePatchi],
|
||||
DimensionedField<Type, volMesh>::null(),
|
||||
fvPatchFieldReconstructor
|
||||
(
|
||||
completeMesh_.boundary()[completePatchi].size()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
patchFields[completePatchi].rmap
|
||||
(
|
||||
procField.boundaryField()[procPatchi],
|
||||
faceProcAddressingBf_[proci][procPatchi] - 1
|
||||
);
|
||||
}
|
||||
else if (isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
if (!patchFields(completePatchi))
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
completePatchi,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
completeMesh_.boundary()[completePatchi].type(),
|
||||
completeMesh_.boundary()[completePatchi],
|
||||
DimensionedField<Type, volMesh>::null()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
patchFields[completePatchi].rmap
|
||||
(
|
||||
procField.boundaryField()[procPatchi],
|
||||
faceProcAddressingBf_[proci][procPatchi] - 1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct and return the field
|
||||
return tmp<GeometricField<Type, fvPatchField, volMesh>>
|
||||
(
|
||||
new GeometricField<Type, fvPatchField, volMesh>
|
||||
(
|
||||
fieldIoObject,
|
||||
completeMesh_,
|
||||
procFields[0].dimensions(),
|
||||
internalField,
|
||||
patchFields
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
|
||||
Foam::fvFieldReconstructor::reconstructFvVolumeField
|
||||
(
|
||||
const IOobject& fieldIoObject
|
||||
) const
|
||||
{
|
||||
PtrList<GeometricField<Type, fvPatchField, volMesh>>
|
||||
procFields(procMeshes_.size());
|
||||
|
||||
forAll(procMeshes_, proci)
|
||||
{
|
||||
procFields.set
|
||||
(
|
||||
proci,
|
||||
new GeometricField<Type, fvPatchField, volMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldIoObject.name(),
|
||||
procMeshes_[proci].time().timeName(),
|
||||
procMeshes_[proci],
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
procMeshes_[proci]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return reconstructFvVolumeField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldIoObject.name(),
|
||||
completeMesh_.time().timeName(),
|
||||
completeMesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
procFields
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
|
||||
Foam::fvFieldReconstructor::reconstructFvSurfaceField
|
||||
(
|
||||
const IOobject& fieldIoObject,
|
||||
const PtrList<GeometricField<Type, fvsPatchField, surfaceMesh>>& procFields
|
||||
) const
|
||||
{
|
||||
// Create the internalField
|
||||
Field<Type> internalField(completeMesh_.nInternalFaces());
|
||||
|
||||
// Create the patch fields
|
||||
PtrList<fvsPatchField<Type>> patchFields(completeMesh_.boundary().size());
|
||||
|
||||
forAll(procMeshes_, proci)
|
||||
{
|
||||
const GeometricField<Type, fvsPatchField, surfaceMesh>& procField =
|
||||
procFields[proci];
|
||||
|
||||
// Set the internal face values in the reconstructed field
|
||||
rmapFaceToFace
|
||||
(
|
||||
internalField,
|
||||
procField.primitiveField(),
|
||||
SubList<label>
|
||||
(
|
||||
faceProcAddressing_[proci],
|
||||
procMeshes_[proci].nInternalFaces()
|
||||
),
|
||||
isFlux(procFields[proci])
|
||||
);
|
||||
|
||||
// Set the boundary patch values in the reconstructed field
|
||||
forAll(procField.boundaryField(), procPatchi)
|
||||
{
|
||||
const fvPatch& procPatch =
|
||||
procMeshes_[proci].boundary()[procPatchi];
|
||||
|
||||
const label completePatchi = completePatchID(proci, procPatchi);
|
||||
|
||||
if (completePatchi == procPatchi)
|
||||
{
|
||||
if (!patchFields(completePatchi))
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
completePatchi,
|
||||
fvsPatchField<Type>::New
|
||||
(
|
||||
procField.boundaryField()[procPatchi],
|
||||
completeMesh_.boundary()[completePatchi],
|
||||
DimensionedField<Type, surfaceMesh>::null(),
|
||||
fvPatchFieldReconstructor
|
||||
(
|
||||
completeMesh_.boundary()[completePatchi].size()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
patchFields[completePatchi].rmap
|
||||
(
|
||||
procField.boundaryField()[procPatchi],
|
||||
faceProcAddressingBf_[proci][procPatchi] - 1
|
||||
);
|
||||
}
|
||||
else if (isA<processorCyclicFvPatch>(procPatch))
|
||||
{
|
||||
if (!patchFields(completePatchi))
|
||||
{
|
||||
patchFields.set
|
||||
(
|
||||
completePatchi,
|
||||
fvsPatchField<Type>::New
|
||||
(
|
||||
completeMesh_.boundary()[completePatchi].type(),
|
||||
completeMesh_.boundary()[completePatchi],
|
||||
DimensionedField<Type, surfaceMesh>::null()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
patchFields[completePatchi].rmap
|
||||
(
|
||||
procField.boundaryField()[procPatchi],
|
||||
faceProcAddressingBf_[proci][procPatchi] - 1
|
||||
);
|
||||
}
|
||||
else if (isA<processorFvPatch>(procPatch))
|
||||
{
|
||||
rmapFaceToFace
|
||||
(
|
||||
internalField,
|
||||
procField.boundaryField()[procPatchi],
|
||||
faceProcAddressingBf_[proci][procPatchi],
|
||||
isFlux(procFields[proci])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct and return the field
|
||||
return tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
|
||||
(
|
||||
new GeometricField<Type, fvsPatchField, surfaceMesh>
|
||||
(
|
||||
fieldIoObject,
|
||||
completeMesh_,
|
||||
procFields[0].dimensions(),
|
||||
internalField,
|
||||
patchFields
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
|
||||
Foam::fvFieldReconstructor::reconstructFvSurfaceField
|
||||
(
|
||||
const IOobject& fieldIoObject
|
||||
) const
|
||||
{
|
||||
PtrList<GeometricField<Type, fvsPatchField, surfaceMesh>>
|
||||
procFields(procMeshes_.size());
|
||||
|
||||
forAll(procMeshes_, proci)
|
||||
{
|
||||
procFields.set
|
||||
(
|
||||
proci,
|
||||
new GeometricField<Type, fvsPatchField, surfaceMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldIoObject.name(),
|
||||
procMeshes_[proci].time().timeName(),
|
||||
procMeshes_[proci],
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
procMeshes_[proci]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return reconstructFvSurfaceField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldIoObject.name(),
|
||||
completeMesh_.time().timeName(),
|
||||
completeMesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
procFields
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::fvFieldReconstructor::reconstructFvVolumeInternalFields
|
||||
(
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
)
|
||||
{
|
||||
const word& fieldClassName = DimensionedField<Type, volMesh>::typeName;
|
||||
|
||||
IOobjectList fields = objects.lookupClass(fieldClassName);
|
||||
|
||||
if (fields.size())
|
||||
{
|
||||
Info<< " Reconstructing " << fieldClassName << "s\n" << endl;
|
||||
|
||||
forAllConstIter(IOobjectList, fields, fieldIter)
|
||||
{
|
||||
if
|
||||
(
|
||||
selectedFields.empty()
|
||||
|| selectedFields.found(fieldIter()->name())
|
||||
)
|
||||
{
|
||||
Info<< " " << fieldIter()->name() << endl;
|
||||
|
||||
reconstructFvVolumeInternalField<Type>(*fieldIter())().write();
|
||||
|
||||
nReconstructed_++;
|
||||
}
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::fvFieldReconstructor::reconstructFvVolumeFields
|
||||
(
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
)
|
||||
{
|
||||
const word& fieldClassName =
|
||||
GeometricField<Type, fvPatchField, volMesh>::typeName;
|
||||
|
||||
IOobjectList fields = objects.lookupClass(fieldClassName);
|
||||
|
||||
if (fields.size())
|
||||
{
|
||||
Info<< " Reconstructing " << fieldClassName << "s\n" << endl;
|
||||
|
||||
forAllConstIter(IOobjectList, fields, fieldIter)
|
||||
{
|
||||
if
|
||||
(
|
||||
selectedFields.empty()
|
||||
|| selectedFields.found(fieldIter()->name())
|
||||
)
|
||||
{
|
||||
Info<< " " << fieldIter()->name() << endl;
|
||||
|
||||
reconstructFvVolumeField<Type>(*fieldIter())().write();
|
||||
|
||||
nReconstructed_++;
|
||||
}
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::fvFieldReconstructor::reconstructFvSurfaceFields
|
||||
(
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
)
|
||||
{
|
||||
const word& fieldClassName =
|
||||
GeometricField<Type, fvsPatchField, surfaceMesh>::typeName;
|
||||
|
||||
IOobjectList fields = objects.lookupClass(fieldClassName);
|
||||
|
||||
if (fields.size())
|
||||
{
|
||||
Info<< " Reconstructing " << fieldClassName << "s\n" << endl;
|
||||
|
||||
forAllConstIter(IOobjectList, fields, fieldIter)
|
||||
{
|
||||
if
|
||||
(
|
||||
selectedFields.empty()
|
||||
|| selectedFields.found(fieldIter()->name())
|
||||
)
|
||||
{
|
||||
Info<< " " << fieldIter()->name() << endl;
|
||||
|
||||
reconstructFvSurfaceField<Type>(*fieldIter())().write();
|
||||
|
||||
nReconstructed_++;
|
||||
}
|
||||
}
|
||||
Info<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,93 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
|
||||
\\/ 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 "pointFieldReconstructor.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointFieldReconstructor::pointFieldReconstructor
|
||||
(
|
||||
const pointMesh& completeMesh,
|
||||
const PtrList<pointMesh>& procMeshes,
|
||||
const labelListList& pointProcAddressing
|
||||
)
|
||||
:
|
||||
completeMesh_(completeMesh),
|
||||
procMeshes_(procMeshes),
|
||||
pointProcAddressing_(pointProcAddressing),
|
||||
patchPointAddressing_(procMeshes.size()),
|
||||
nReconstructed_(0)
|
||||
{
|
||||
// Inverse-addressing of the patch point labels.
|
||||
labelList pointMap(completeMesh_.size(), -1);
|
||||
|
||||
// Create the pointPatch addressing
|
||||
forAll(procMeshes_, proci)
|
||||
{
|
||||
const pointMesh& procMesh = procMeshes_[proci];
|
||||
|
||||
patchPointAddressing_[proci].setSize(procMesh.boundary().size());
|
||||
|
||||
forAll(procMesh.boundary(), patchi)
|
||||
{
|
||||
if (patchi < completeMesh_.boundary().size())
|
||||
{
|
||||
labelList& procPatchAddr = patchPointAddressing_[proci][patchi];
|
||||
procPatchAddr.setSize(procMesh.boundary()[patchi].size(), -1);
|
||||
|
||||
const labelList& patchPointLabels =
|
||||
completeMesh_.boundary()[patchi].meshPoints();
|
||||
|
||||
// Create the inverse-addressing of the patch point labels.
|
||||
forAll(patchPointLabels, pointi)
|
||||
{
|
||||
pointMap[patchPointLabels[pointi]] = pointi;
|
||||
}
|
||||
|
||||
const labelList& procPatchPoints =
|
||||
procMesh.boundary()[patchi].meshPoints();
|
||||
|
||||
forAll(procPatchPoints, pointi)
|
||||
{
|
||||
procPatchAddr[pointi] =
|
||||
pointMap
|
||||
[
|
||||
pointProcAddressing_[proci][procPatchPoints[pointi]]
|
||||
];
|
||||
}
|
||||
|
||||
if (procPatchAddr.size() && min(procPatchAddr) < 0)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Incomplete patch point addressing"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,150 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
|
||||
\\/ 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::pointFieldReconstructor
|
||||
|
||||
Description
|
||||
Point field reconstructor.
|
||||
|
||||
SourceFiles
|
||||
pointFieldReconstructor.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef pointFieldReconstructor_H
|
||||
#define pointFieldReconstructor_H
|
||||
|
||||
#include "pointMesh.H"
|
||||
#include "pointFields.H"
|
||||
#include "pointPatchFieldMapper.H"
|
||||
#include "setSizeFieldMapper.H"
|
||||
#include "IOobjectList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class pointFieldReconstructor Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class pointFieldReconstructor
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Reconstructed mesh reference
|
||||
const pointMesh& completeMesh_;
|
||||
|
||||
//- List of processor meshes
|
||||
const PtrList<pointMesh>& procMeshes_;
|
||||
|
||||
//- List of processor point addressing lists
|
||||
const labelListList& pointProcAddressing_;
|
||||
|
||||
//- Point patch addressing
|
||||
labelListListList patchPointAddressing_;
|
||||
|
||||
//- Number of fields reconstructed
|
||||
label nReconstructed_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Mapper for sizing only - does not do any actual mapping.
|
||||
class pointPatchFieldReconstructor
|
||||
:
|
||||
public pointPatchFieldMapper,
|
||||
public setSizeFieldMapper
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given size
|
||||
pointPatchFieldReconstructor(const label size)
|
||||
:
|
||||
setSizeFieldMapper(size)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
pointFieldReconstructor
|
||||
(
|
||||
const pointMesh& mesh,
|
||||
const PtrList<pointMesh>& procMeshes,
|
||||
const labelListList& pointProcAddressing
|
||||
);
|
||||
|
||||
//- Disallow default bitwise copy construction
|
||||
pointFieldReconstructor(const pointFieldReconstructor&) = delete;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return number of fields reconstructed
|
||||
label nReconstructed() const
|
||||
{
|
||||
return nReconstructed_;
|
||||
}
|
||||
|
||||
//- Reconstruct field
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, pointPatchField, pointMesh>>
|
||||
reconstructField(const IOobject& fieldIoObject);
|
||||
|
||||
//- Reconstruct and write all fields
|
||||
template<class Type>
|
||||
void reconstructFields
|
||||
(
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
);
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const pointFieldReconstructor&) = delete;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "pointFieldReconstructorReconstructFields.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,180 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
|
||||
\\/ 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 "pointFieldReconstructor.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh>>
|
||||
Foam::pointFieldReconstructor::reconstructField(const IOobject& fieldIoObject)
|
||||
{
|
||||
// Read the field for all the processors
|
||||
PtrList<GeometricField<Type, pointPatchField, pointMesh>> procFields
|
||||
(
|
||||
procMeshes_.size()
|
||||
);
|
||||
|
||||
forAll(procMeshes_, proci)
|
||||
{
|
||||
procFields.set
|
||||
(
|
||||
proci,
|
||||
new GeometricField<Type, pointPatchField, pointMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldIoObject.name(),
|
||||
procMeshes_[proci]().time().timeName(),
|
||||
procMeshes_[proci](),
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
procMeshes_[proci]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Create the internalField
|
||||
Field<Type> internalField(completeMesh_.size());
|
||||
|
||||
// Create the patch fields
|
||||
PtrList<pointPatchField<Type>> patchFields(completeMesh_.boundary().size());
|
||||
|
||||
|
||||
forAll(procMeshes_, proci)
|
||||
{
|
||||
const GeometricField<Type, pointPatchField, pointMesh>&
|
||||
procField = procFields[proci];
|
||||
|
||||
// Get processor-to-global addressing for use in rmap
|
||||
const labelList& procToGlobalAddr = pointProcAddressing_[proci];
|
||||
|
||||
// Set the cell values in the reconstructed field
|
||||
internalField.rmap
|
||||
(
|
||||
procField.primitiveField(),
|
||||
procToGlobalAddr
|
||||
);
|
||||
|
||||
// Set the boundary patch values in the reconstructed field
|
||||
forAll(procField.boundaryField(), patchi)
|
||||
{
|
||||
// Get patch index of the original patch
|
||||
const label curBPatch =
|
||||
patchi < completeMesh_.boundary().size() ? patchi : -1;
|
||||
|
||||
// check if the boundary patch is not a processor patch
|
||||
if (curBPatch != -1)
|
||||
{
|
||||
if (!patchFields(curBPatch))
|
||||
{
|
||||
patchFields.set(
|
||||
curBPatch,
|
||||
pointPatchField<Type>::New
|
||||
(
|
||||
procField.boundaryField()[patchi],
|
||||
completeMesh_.boundary()[curBPatch],
|
||||
DimensionedField<Type, pointMesh>::null(),
|
||||
pointPatchFieldReconstructor
|
||||
(
|
||||
completeMesh_.boundary()[curBPatch].size()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
patchFields[curBPatch].rmap
|
||||
(
|
||||
procField.boundaryField()[patchi],
|
||||
patchPointAddressing_[proci][patchi]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct and write the field
|
||||
// setting the internalField and patchFields
|
||||
return tmp<GeometricField<Type, pointPatchField, pointMesh>>
|
||||
(
|
||||
new GeometricField<Type, pointPatchField, pointMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldIoObject.name(),
|
||||
completeMesh_().time().timeName(),
|
||||
completeMesh_(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
completeMesh_,
|
||||
procFields[0].dimensions(),
|
||||
internalField,
|
||||
patchFields
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Reconstruct and write all point fields
|
||||
template<class Type>
|
||||
void Foam::pointFieldReconstructor::reconstructFields
|
||||
(
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
)
|
||||
{
|
||||
word fieldClassName
|
||||
(
|
||||
GeometricField<Type, pointPatchField, pointMesh>::typeName
|
||||
);
|
||||
|
||||
IOobjectList fields = objects.lookupClass(fieldClassName);
|
||||
|
||||
if (fields.size())
|
||||
{
|
||||
Info<< " Reconstructing " << fieldClassName << "s\n" << endl;
|
||||
|
||||
forAllConstIter(IOobjectList, fields, fieldIter)
|
||||
{
|
||||
if
|
||||
(
|
||||
!selectedFields.size()
|
||||
|| selectedFields.found(fieldIter()->name())
|
||||
)
|
||||
{
|
||||
Info<< " " << fieldIter()->name() << endl;
|
||||
|
||||
reconstructField<Type>(*fieldIter())().write();
|
||||
}
|
||||
}
|
||||
|
||||
Info<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,117 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
|
||||
\\/ 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/>.
|
||||
|
||||
InClass
|
||||
Foam::reconstructLagrangian
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
reconstructLagrangianPositions.C
|
||||
reconstructLagrangianFields.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef reconstructLagrangian_H
|
||||
#define reconstructLagrangian_H
|
||||
|
||||
#include "cloud.H"
|
||||
#include "polyMesh.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "CompactIOField.H"
|
||||
#include "fvMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
void reconstructLagrangianPositions
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const word& cloudName,
|
||||
const PtrList<fvMesh>& meshes,
|
||||
const labelListList& faceProcAddressing,
|
||||
const labelListList& cellProcAddressing
|
||||
);
|
||||
|
||||
|
||||
template<class Type>
|
||||
tmp<IOField<Type>> reconstructLagrangianField
|
||||
(
|
||||
const word& cloudName,
|
||||
const polyMesh& mesh,
|
||||
const PtrList<fvMesh>& meshes,
|
||||
const word& fieldName
|
||||
);
|
||||
|
||||
|
||||
template<class Type>
|
||||
tmp<CompactIOField<Field<Type>, Type>> reconstructLagrangianFieldField
|
||||
(
|
||||
const word& cloudName,
|
||||
const polyMesh& mesh,
|
||||
const PtrList<fvMesh>& meshes,
|
||||
const word& fieldName
|
||||
);
|
||||
|
||||
|
||||
template<class Type>
|
||||
void reconstructLagrangianFields
|
||||
(
|
||||
const word& cloudName,
|
||||
const polyMesh& mesh,
|
||||
const PtrList<fvMesh>& meshes,
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
);
|
||||
|
||||
|
||||
template<class Type>
|
||||
void reconstructLagrangianFieldFields
|
||||
(
|
||||
const word& cloudName,
|
||||
const polyMesh& mesh,
|
||||
const PtrList<fvMesh>& meshes,
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "reconstructLagrangianFields.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,273 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
|
||||
\\/ 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 "IOField.H"
|
||||
#include "CompactIOField.H"
|
||||
#include "Time.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::IOField<Type>> Foam::reconstructLagrangianField
|
||||
(
|
||||
const word& cloudName,
|
||||
const polyMesh& mesh,
|
||||
const PtrList<fvMesh>& meshes,
|
||||
const word& fieldName
|
||||
)
|
||||
{
|
||||
// Construct empty field on mesh
|
||||
tmp<IOField<Type>> tfield
|
||||
(
|
||||
new IOField<Type>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
mesh.time().timeName(),
|
||||
cloud::prefix/cloudName,
|
||||
mesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
Field<Type>(0)
|
||||
)
|
||||
);
|
||||
Field<Type>& field = tfield.ref();
|
||||
|
||||
forAll(meshes, i)
|
||||
{
|
||||
// Check object on local mesh
|
||||
typeIOobject<IOField<Type>> localIOobject
|
||||
(
|
||||
fieldName,
|
||||
meshes[i].time().timeName(),
|
||||
cloud::prefix/cloudName,
|
||||
meshes[i],
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
);
|
||||
|
||||
if (localIOobject.headerOk())
|
||||
{
|
||||
IOField<Type> fieldi(localIOobject);
|
||||
|
||||
label offset = field.size();
|
||||
field.setSize(offset + fieldi.size());
|
||||
|
||||
forAll(fieldi, j)
|
||||
{
|
||||
field[offset + j] = fieldi[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tfield;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::CompactIOField<Foam::Field<Type>, Type>>
|
||||
Foam::reconstructLagrangianFieldField
|
||||
(
|
||||
const word& cloudName,
|
||||
const polyMesh& mesh,
|
||||
const PtrList<fvMesh>& meshes,
|
||||
const word& fieldName
|
||||
)
|
||||
{
|
||||
// Construct empty field on mesh
|
||||
tmp<CompactIOField<Field<Type>, Type >> tfield
|
||||
(
|
||||
new CompactIOField<Field<Type>, Type>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
fieldName,
|
||||
mesh.time().timeName(),
|
||||
cloud::prefix/cloudName,
|
||||
mesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
Field<Field<Type>>(0)
|
||||
)
|
||||
);
|
||||
Field<Field<Type>>& field = tfield.ref();
|
||||
|
||||
forAll(meshes, i)
|
||||
{
|
||||
// No type checking is done to handle CompactIOField and IOField
|
||||
IOobject localIOobject
|
||||
(
|
||||
fieldName,
|
||||
meshes[i].time().timeName(),
|
||||
cloud::prefix/cloudName,
|
||||
meshes[i],
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
);
|
||||
|
||||
if (localIOobject.headerOk())
|
||||
{
|
||||
CompactIOField<Field<Type>, Type> fieldi(localIOobject);
|
||||
|
||||
label offset = field.size();
|
||||
field.setSize(offset + fieldi.size());
|
||||
|
||||
forAll(fieldi, j)
|
||||
{
|
||||
field[offset + j] = fieldi[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tfield;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::reconstructLagrangianFields
|
||||
(
|
||||
const word& cloudName,
|
||||
const polyMesh& mesh,
|
||||
const PtrList<fvMesh>& meshes,
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
)
|
||||
{
|
||||
const word fieldClassName(IOField<Type>::typeName);
|
||||
|
||||
IOobjectList fields = objects.lookupClass(fieldClassName);
|
||||
|
||||
if (fields.size())
|
||||
{
|
||||
Info<< " Reconstructing lagrangian "
|
||||
<< fieldClassName << "s\n" << endl;
|
||||
|
||||
forAllConstIter(IOobjectList, fields, fieldIter)
|
||||
{
|
||||
if
|
||||
(
|
||||
selectedFields.empty()
|
||||
|| selectedFields.found(fieldIter()->name())
|
||||
)
|
||||
{
|
||||
Info<< " " << fieldIter()->name() << endl;
|
||||
reconstructLagrangianField<Type>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
meshes,
|
||||
fieldIter()->name()
|
||||
)().write();
|
||||
}
|
||||
}
|
||||
|
||||
Info<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
void Foam::reconstructLagrangianFieldFields
|
||||
(
|
||||
const word& cloudName,
|
||||
const polyMesh& mesh,
|
||||
const PtrList<fvMesh>& meshes,
|
||||
const IOobjectList& objects,
|
||||
const HashSet<word>& selectedFields
|
||||
)
|
||||
{
|
||||
{
|
||||
const word fieldClassName(CompactIOField<Field<Type>, Type>::typeName);
|
||||
|
||||
IOobjectList fields = objects.lookupClass(fieldClassName);
|
||||
|
||||
if (fields.size())
|
||||
{
|
||||
Info<< " Reconstructing lagrangian "
|
||||
<< fieldClassName << "s\n" << endl;
|
||||
|
||||
forAllConstIter(IOobjectList, fields, fieldIter)
|
||||
{
|
||||
if
|
||||
(
|
||||
selectedFields.empty()
|
||||
|| selectedFields.found(fieldIter()->name())
|
||||
)
|
||||
{
|
||||
Info<< " " << fieldIter()->name() << endl;
|
||||
reconstructLagrangianFieldField<Type>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
meshes,
|
||||
fieldIter()->name()
|
||||
)().write();
|
||||
}
|
||||
}
|
||||
|
||||
Info<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const word fieldClassName(IOField<Field<Type>>::typeName);
|
||||
|
||||
IOobjectList fields = objects.lookupClass(fieldClassName);
|
||||
|
||||
if (fields.size())
|
||||
{
|
||||
Info<< " Reconstructing lagrangian "
|
||||
<< fieldClassName << "s\n" << endl;
|
||||
|
||||
forAllConstIter(IOobjectList, fields, fieldIter)
|
||||
{
|
||||
if
|
||||
(
|
||||
selectedFields.empty()
|
||||
|| selectedFields.found(fieldIter()->name())
|
||||
)
|
||||
{
|
||||
Info<< " " << fieldIter()->name() << endl;
|
||||
reconstructLagrangianFieldField<Type>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
meshes,
|
||||
fieldIter()->name()
|
||||
)().write();
|
||||
}
|
||||
}
|
||||
|
||||
Info<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,83 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
|
||||
\\/ 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 "reconstructLagrangian.H"
|
||||
#include "labelIOList.H"
|
||||
#include "passiveParticleCloud.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::reconstructLagrangianPositions
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const word& cloudName,
|
||||
const PtrList<fvMesh>& meshes,
|
||||
const labelListList& faceProcAddressing,
|
||||
const labelListList& cellProcAddressing
|
||||
)
|
||||
{
|
||||
passiveParticleCloud lagrangianPositions
|
||||
(
|
||||
mesh,
|
||||
cloudName,
|
||||
IDLList<passiveParticle>()
|
||||
);
|
||||
|
||||
forAll(meshes, i)
|
||||
{
|
||||
const labelList& cellMap = cellProcAddressing[i];
|
||||
const labelList& faceMap = faceProcAddressing[i];
|
||||
|
||||
Cloud<passiveParticle> lpi(meshes[i], cloudName, false);
|
||||
|
||||
forAllConstIter(Cloud<passiveParticle>, lpi, iter)
|
||||
{
|
||||
const passiveParticle& ppi = iter();
|
||||
|
||||
const label mappedCell = cellMap[ppi.cell()];
|
||||
|
||||
// Inverting sign if necessary and subtracting 1 from
|
||||
// faceProcAddressing
|
||||
label mappedTetFace = mag(faceMap[ppi.tetFace()]) - 1;
|
||||
|
||||
lagrangianPositions.append
|
||||
(
|
||||
new passiveParticle
|
||||
(
|
||||
mesh,
|
||||
ppi.coordinates(),
|
||||
mappedCell,
|
||||
mappedTetFace,
|
||||
ppi.procTetPt(mesh, mappedCell, mappedTetFace)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
IOPosition<Cloud<passiveParticle>>(lagrangianPositions).write();
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -32,21 +32,15 @@ Description
|
||||
|
||||
#include "argList.H"
|
||||
#include "timeSelector.H"
|
||||
|
||||
#include "fvCFD.H"
|
||||
#include "IOobjectList.H"
|
||||
#include "processorMeshes.H"
|
||||
#include "processorRunTimes.H"
|
||||
#include "domainDecomposition.H"
|
||||
#include "regionProperties.H"
|
||||
#include "fvFieldReconstructor.H"
|
||||
#include "pointFieldReconstructor.H"
|
||||
#include "reconstructLagrangian.H"
|
||||
|
||||
#include "cellSet.H"
|
||||
#include "faceSet.H"
|
||||
#include "pointSet.H"
|
||||
|
||||
#include "hexRef8Data.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
@ -120,7 +114,6 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
|
||||
HashSet<word> selectedFields;
|
||||
if (args.optionFound("fields"))
|
||||
@ -144,7 +137,6 @@ int main(int argc, char *argv[])
|
||||
<< nl << endl;
|
||||
}
|
||||
|
||||
|
||||
const bool noReconstructSets = args.optionFound("noSets");
|
||||
|
||||
if (noReconstructSets)
|
||||
@ -153,7 +145,6 @@ int main(int argc, char *argv[])
|
||||
<< nl << endl;
|
||||
}
|
||||
|
||||
|
||||
HashSet<word> selectedLagrangianFields;
|
||||
if (args.optionFound("lagrangianFields"))
|
||||
{
|
||||
@ -168,12 +159,20 @@ int main(int argc, char *argv[])
|
||||
args.optionLookup("lagrangianFields")() >> selectedLagrangianFields;
|
||||
}
|
||||
|
||||
const wordList regionNames(selectRegionNames(args, runTime));
|
||||
// Set time from database
|
||||
Info<< "Create time\n" << endl;
|
||||
processorRunTimes runTimes(Foam::Time::controlDictName, args);
|
||||
|
||||
// Allow override of time
|
||||
const instantList times = runTimes.selectProc(args);
|
||||
|
||||
// Get region names
|
||||
const wordList regionNames =
|
||||
selectRegionNames(args, runTimes.procTimes()[0]);
|
||||
|
||||
// Determine the processor count
|
||||
const label nProcs =
|
||||
fileHandler().nProcs(args.path(), regionDir(regionNames[0]));
|
||||
|
||||
if (!nProcs)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
@ -184,38 +183,12 @@ int main(int argc, char *argv[])
|
||||
// Warn fileHandler of number of processors
|
||||
const_cast<fileOperation&>(fileHandler()).setNProcs(nProcs);
|
||||
|
||||
// Create the processor databases
|
||||
PtrList<Time> databases(nProcs);
|
||||
|
||||
forAll(databases, proci)
|
||||
{
|
||||
databases.set
|
||||
(
|
||||
proci,
|
||||
new Time
|
||||
(
|
||||
Time::controlDictName,
|
||||
args.rootPath(),
|
||||
args.caseName()/fileName(word("processor") + name(proci))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Use the times list from the master processor
|
||||
// and select a subset based on the command-line options
|
||||
instantList timeDirs = timeSelector::select
|
||||
(
|
||||
databases[0].times(),
|
||||
args
|
||||
);
|
||||
|
||||
// Note that we do not set the runTime time so it is still the
|
||||
// one set through the controlDict. The -time option
|
||||
// only affects the selected set of times from processor0.
|
||||
// - can be illogical
|
||||
// + any point motion handled through mesh.readUpdate
|
||||
|
||||
if (timeDirs.empty())
|
||||
if (times.empty())
|
||||
{
|
||||
WarningInFunction << "No times selected" << endl;
|
||||
exit(1);
|
||||
@ -226,130 +199,76 @@ int main(int argc, char *argv[])
|
||||
instantList masterTimeDirs;
|
||||
if (newTimes)
|
||||
{
|
||||
masterTimeDirs = runTime.times();
|
||||
masterTimeDirs = runTimes.completeTime().times();
|
||||
}
|
||||
|
||||
HashSet<word> masterTimeDirSet(2*masterTimeDirs.size());
|
||||
forAll(masterTimeDirs, i)
|
||||
{
|
||||
masterTimeDirSet.insert(masterTimeDirs[i].name());
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
newTimes
|
||||
&& regionNames.size() == 1
|
||||
&& regionNames[0] == fvMesh::defaultRegion
|
||||
&& haveAllTimes(masterTimeDirSet, timeDirs)
|
||||
&& haveAllTimes(masterTimeDirSet, times)
|
||||
)
|
||||
{
|
||||
Info<< "All times already reconstructed.\n\nEnd\n" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set all times on processor meshes equal to reconstructed mesh
|
||||
forAll(databases, proci)
|
||||
{
|
||||
databases[proci].setTime(runTime);
|
||||
}
|
||||
|
||||
// Reconstruct all regions
|
||||
forAll(regionNames, regioni)
|
||||
{
|
||||
const word& regionName = regionNames[regioni];
|
||||
const word& regionDir = Foam::regionDir(regionName);
|
||||
|
||||
Info<< "\n\nReconstructing fields for mesh " << regionName << nl
|
||||
<< endl;
|
||||
|
||||
fvMesh mesh
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
regionName,
|
||||
runTime.timeName(),
|
||||
runTime,
|
||||
IOobject::MUST_READ
|
||||
),
|
||||
false
|
||||
);
|
||||
|
||||
|
||||
// Read all meshes and addressing to reconstructed mesh
|
||||
processorMeshes procMeshes(databases, regionName);
|
||||
|
||||
|
||||
// Check face addressing for meshes that have been decomposed
|
||||
// with a very old foam version
|
||||
#include "checkFaceAddressingComp.H"
|
||||
// Create meshes
|
||||
Info<< "\n\nReconstructing fields for mesh " << regionName
|
||||
<< nl << endl;
|
||||
domainDecomposition meshes(runTimes, regionName);
|
||||
meshes.readComplete();
|
||||
meshes.readProcs();
|
||||
meshes.readAddressing();
|
||||
meshes.readUpdate();
|
||||
|
||||
// Loop over all times
|
||||
forAll(timeDirs, timei)
|
||||
forAll(times, timei)
|
||||
{
|
||||
if (newTimes && masterTimeDirSet.found(timeDirs[timei].name()))
|
||||
if (newTimes && masterTimeDirSet.found(times[timei].name()))
|
||||
{
|
||||
Info<< "Skipping time " << timeDirs[timei].name()
|
||||
Info<< "Skipping time " << times[timei].name()
|
||||
<< endl << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set the time
|
||||
runTimes.setTime(times[timei], timei);
|
||||
|
||||
// Set time for global database
|
||||
runTime.setTime(timeDirs[timei], timei);
|
||||
Info<< "Time = " << runTimes.completeTime().userTimeName()
|
||||
<< nl << endl;
|
||||
|
||||
Info<< "Time = " << runTime.userTimeName() << endl << endl;
|
||||
|
||||
// Set time for all databases
|
||||
forAll(databases, proci)
|
||||
// Update the meshes
|
||||
const fvMesh::readUpdateState state = meshes.readUpdate();
|
||||
if (state == fvMesh::POINTS_MOVED)
|
||||
{
|
||||
databases[proci].setTime(timeDirs[timei], timei);
|
||||
meshes.writeComplete(false);
|
||||
}
|
||||
|
||||
// Check if any new meshes need to be read.
|
||||
fvMesh::readUpdateState meshStat = mesh.readUpdate();
|
||||
fvMesh::readUpdateState procStat = procMeshes.readUpdate();
|
||||
if
|
||||
(
|
||||
meshStat != procStat
|
||||
|
||||
// Allowed status difference. Mesh has moved in parallel, but
|
||||
// the change has not yet been reconstructed.
|
||||
&& !(
|
||||
meshStat == fvMesh::UNCHANGED
|
||||
&& procStat == fvMesh::POINTS_MOVED
|
||||
)
|
||||
|
||||
// Allowed status difference. Mesh has changed topology in both
|
||||
// cases, and this has lead to new processor interfaces
|
||||
// (probably). These interfaces are compatible with a
|
||||
// reconstructed mesh in which patches have not changed.
|
||||
&& !(
|
||||
meshStat == fvMesh::TOPO_CHANGE
|
||||
&& procStat == fvMesh::TOPO_PATCH_CHANGE
|
||||
)
|
||||
state == fvMesh::TOPO_CHANGE
|
||||
|| state == fvMesh::TOPO_PATCH_CHANGE
|
||||
)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "readUpdate for the reconstructed mesh:"
|
||||
<< meshStat << nl
|
||||
<< "readUpdate for the processor meshes :"
|
||||
<< procStat << nl
|
||||
<< "These should be equal or your addressing"
|
||||
<< " might be incorrect."
|
||||
<< " Please check your time directories for any "
|
||||
<< "mesh directories." << endl;
|
||||
}
|
||||
|
||||
// Reconstruct and write the points for moving mesh cases
|
||||
if (procStat == fvMesh::POINTS_MOVED)
|
||||
{
|
||||
procMeshes.reconstructPoints(mesh);
|
||||
meshes.writeComplete(!noReconstructSets);
|
||||
}
|
||||
|
||||
// Get list of objects from processor0 database
|
||||
IOobjectList objects
|
||||
(
|
||||
procMeshes.meshes()[0],
|
||||
databases[0].timeName()
|
||||
meshes.procMeshes()[0],
|
||||
runTimes.procTimes()[0].timeName()
|
||||
);
|
||||
|
||||
if (!noFields)
|
||||
@ -359,10 +278,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
fvFieldReconstructor fvReconstructor
|
||||
(
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
procMeshes.faceProcAddressing(),
|
||||
procMeshes.cellProcAddressing()
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
meshes.procFaceAddressing(),
|
||||
meshes.procCellAddressing(),
|
||||
meshes.procFaceAddressingBf()
|
||||
);
|
||||
|
||||
fvReconstructor.reconstructFvVolumeInternalFields<scalar>
|
||||
@ -454,23 +374,23 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
Info<< "Reconstructing point fields" << nl << endl;
|
||||
|
||||
const pointMesh& pMesh = pointMesh::New(mesh);
|
||||
PtrList<pointMesh> pMeshes(procMeshes.meshes().size());
|
||||
|
||||
forAll(pMeshes, proci)
|
||||
const pointMesh& completePMesh =
|
||||
pointMesh::New(meshes.completeMesh());
|
||||
PtrList<pointMesh> procPMeshes(nProcs);
|
||||
forAll(procPMeshes, proci)
|
||||
{
|
||||
pMeshes.set
|
||||
procPMeshes.set
|
||||
(
|
||||
proci,
|
||||
new pointMesh(procMeshes.meshes()[proci])
|
||||
new pointMesh(meshes.procMeshes()[proci])
|
||||
);
|
||||
}
|
||||
|
||||
pointFieldReconstructor pointReconstructor
|
||||
(
|
||||
pMesh,
|
||||
pMeshes,
|
||||
procMeshes.pointProcAddressing()
|
||||
completePMesh,
|
||||
procPMeshes,
|
||||
meshes.procPointAddressing()
|
||||
);
|
||||
|
||||
pointReconstructor.reconstructFields<scalar>
|
||||
@ -517,15 +437,15 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
HashTable<IOobjectList> cloudObjects;
|
||||
|
||||
forAll(databases, proci)
|
||||
forAll(runTimes.procTimes(), proci)
|
||||
{
|
||||
fileName lagrangianDir
|
||||
(
|
||||
fileHandler().filePath
|
||||
(
|
||||
databases[proci].timePath()
|
||||
/ regionDir
|
||||
/ cloud::prefix
|
||||
runTimes.procTimes()[proci].timePath()
|
||||
/regionDir
|
||||
/cloud::prefix
|
||||
)
|
||||
);
|
||||
|
||||
@ -551,8 +471,8 @@ int main(int argc, char *argv[])
|
||||
// Do local scan for valid cloud objects
|
||||
IOobjectList sprayObjs
|
||||
(
|
||||
procMeshes.meshes()[proci],
|
||||
databases[proci].timeName(),
|
||||
meshes.procMeshes()[proci],
|
||||
runTimes.procTimes()[proci].timeName(),
|
||||
cloud::prefix/cloudDirs[i]
|
||||
);
|
||||
|
||||
@ -567,16 +487,13 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (cloudObjects.size())
|
||||
{
|
||||
// Pass2: reconstruct the cloud
|
||||
forAllConstIter(HashTable<IOobjectList>, cloudObjects, iter)
|
||||
{
|
||||
const word cloudName = string::validate<word>
|
||||
(
|
||||
iter.key()
|
||||
);
|
||||
const word cloudName =
|
||||
string::validate<word>(iter.key());
|
||||
|
||||
// Objects (on arbitrary processor)
|
||||
const IOobjectList& sprayObjs = iter();
|
||||
@ -586,105 +503,105 @@ int main(int argc, char *argv[])
|
||||
|
||||
reconstructLagrangianPositions
|
||||
(
|
||||
mesh,
|
||||
meshes.completeMesh(),
|
||||
cloudName,
|
||||
procMeshes.meshes(),
|
||||
procMeshes.faceProcAddressing(),
|
||||
procMeshes.cellProcAddressing()
|
||||
meshes.procMeshes(),
|
||||
meshes.procFaceAddressing(),
|
||||
meshes.procCellAddressing()
|
||||
);
|
||||
reconstructLagrangianFields<label>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFieldFields<label>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFields<scalar>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFieldFields<scalar>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFields<vector>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFieldFields<vector>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFields<sphericalTensor>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFieldFields<sphericalTensor>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFields<symmTensor>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFieldFields<symmTensor>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFields<tensor>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
reconstructLagrangianFieldFields<tensor>
|
||||
(
|
||||
cloudName,
|
||||
mesh,
|
||||
procMeshes.meshes(),
|
||||
meshes.completeMesh(),
|
||||
meshes.procMeshes(),
|
||||
sprayObjs,
|
||||
selectedLagrangianFields
|
||||
);
|
||||
@ -696,278 +613,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!noReconstructSets)
|
||||
{
|
||||
// Scan to find all sets
|
||||
HashTable<label> cSetNames;
|
||||
HashTable<label> fSetNames;
|
||||
HashTable<label> pSetNames;
|
||||
|
||||
forAll(procMeshes.meshes(), proci)
|
||||
{
|
||||
const fvMesh& procMesh = procMeshes.meshes()[proci];
|
||||
|
||||
// Note: look at sets in current time only or between
|
||||
// mesh and current time?. For now current time. This will
|
||||
// miss out on sets in intermediate times that have not
|
||||
// been reconstructed.
|
||||
IOobjectList objects
|
||||
(
|
||||
procMesh,
|
||||
databases[0].timeName(), // procMesh.facesInstance()
|
||||
polyMesh::meshSubDir/"sets"
|
||||
);
|
||||
|
||||
IOobjectList cSets(objects.lookupClass(cellSet::typeName));
|
||||
forAllConstIter(IOobjectList, cSets, iter)
|
||||
{
|
||||
cSetNames.insert(iter.key(), cSetNames.size());
|
||||
}
|
||||
|
||||
IOobjectList fSets(objects.lookupClass(faceSet::typeName));
|
||||
forAllConstIter(IOobjectList, fSets, iter)
|
||||
{
|
||||
fSetNames.insert(iter.key(), fSetNames.size());
|
||||
}
|
||||
IOobjectList pSets(objects.lookupClass(pointSet::typeName));
|
||||
forAllConstIter(IOobjectList, pSets, iter)
|
||||
{
|
||||
pSetNames.insert(iter.key(), pSetNames.size());
|
||||
}
|
||||
}
|
||||
|
||||
if (cSetNames.size() || fSetNames.size() || pSetNames.size())
|
||||
{
|
||||
// Construct all sets
|
||||
PtrList<cellSet> cellSets(cSetNames.size());
|
||||
PtrList<faceSet> faceSets(fSetNames.size());
|
||||
PtrList<pointSet> pointSets(pSetNames.size());
|
||||
|
||||
Info<< "Reconstructing sets:" << endl;
|
||||
if (cSetNames.size())
|
||||
{
|
||||
Info<< " cellSets "
|
||||
<< cSetNames.sortedToc() << endl;
|
||||
}
|
||||
if (fSetNames.size())
|
||||
{
|
||||
Info<< " faceSets "
|
||||
<< fSetNames.sortedToc() << endl;
|
||||
}
|
||||
if (pSetNames.size())
|
||||
{
|
||||
Info<< " pointSets "
|
||||
<< pSetNames.sortedToc() << endl;
|
||||
}
|
||||
|
||||
// Load sets
|
||||
forAll(procMeshes.meshes(), proci)
|
||||
{
|
||||
const fvMesh& procMesh = procMeshes.meshes()[proci];
|
||||
|
||||
IOobjectList objects
|
||||
(
|
||||
procMesh,
|
||||
databases[0].timeName(),
|
||||
polyMesh::meshSubDir/"sets"
|
||||
);
|
||||
|
||||
// cellSets
|
||||
const labelList& cellMap =
|
||||
procMeshes.cellProcAddressing()[proci];
|
||||
|
||||
IOobjectList cSets
|
||||
(
|
||||
objects.lookupClass(cellSet::typeName)
|
||||
);
|
||||
|
||||
forAllConstIter(IOobjectList, cSets, iter)
|
||||
{
|
||||
// Load cellSet
|
||||
const cellSet procSet(*iter());
|
||||
label setI = cSetNames[iter.key()];
|
||||
if (!cellSets.set(setI))
|
||||
{
|
||||
cellSets.set
|
||||
(
|
||||
setI,
|
||||
new cellSet
|
||||
(
|
||||
mesh,
|
||||
iter.key(),
|
||||
procSet.size()
|
||||
)
|
||||
);
|
||||
}
|
||||
cellSet& cSet = cellSets[setI];
|
||||
cSet.instance() = runTime.timeName();
|
||||
|
||||
forAllConstIter(cellSet, procSet, iter)
|
||||
{
|
||||
cSet.insert(cellMap[iter.key()]);
|
||||
}
|
||||
}
|
||||
|
||||
// faceSets
|
||||
const labelList& faceMap =
|
||||
procMeshes.faceProcAddressing()[proci];
|
||||
|
||||
IOobjectList fSets
|
||||
(
|
||||
objects.lookupClass(faceSet::typeName)
|
||||
);
|
||||
|
||||
forAllConstIter(IOobjectList, fSets, iter)
|
||||
{
|
||||
// Load faceSet
|
||||
const faceSet procSet(*iter());
|
||||
label setI = fSetNames[iter.key()];
|
||||
if (!faceSets.set(setI))
|
||||
{
|
||||
faceSets.set
|
||||
(
|
||||
setI,
|
||||
new faceSet
|
||||
(
|
||||
mesh,
|
||||
iter.key(),
|
||||
procSet.size()
|
||||
)
|
||||
);
|
||||
}
|
||||
faceSet& fSet = faceSets[setI];
|
||||
fSet.instance() = runTime.timeName();
|
||||
|
||||
forAllConstIter(faceSet, procSet, iter)
|
||||
{
|
||||
fSet.insert(mag(faceMap[iter.key()])-1);
|
||||
}
|
||||
}
|
||||
// pointSets
|
||||
const labelList& pointMap =
|
||||
procMeshes.pointProcAddressing()[proci];
|
||||
|
||||
IOobjectList pSets
|
||||
(
|
||||
objects.lookupClass(pointSet::typeName)
|
||||
);
|
||||
forAllConstIter(IOobjectList, pSets, iter)
|
||||
{
|
||||
// Load pointSet
|
||||
const pointSet propSet(*iter());
|
||||
label setI = pSetNames[iter.key()];
|
||||
if (!pointSets.set(setI))
|
||||
{
|
||||
pointSets.set
|
||||
(
|
||||
setI,
|
||||
new pointSet
|
||||
(
|
||||
mesh,
|
||||
iter.key(),
|
||||
propSet.size()
|
||||
)
|
||||
);
|
||||
}
|
||||
pointSet& pSet = pointSets[setI];
|
||||
pSet.instance() = runTime.timeName();
|
||||
|
||||
forAllConstIter(pointSet, propSet, iter)
|
||||
{
|
||||
pSet.insert(pointMap[iter.key()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write sets
|
||||
forAll(cellSets, i)
|
||||
{
|
||||
cellSets[i].write();
|
||||
}
|
||||
forAll(faceSets, i)
|
||||
{
|
||||
faceSets[i].write();
|
||||
}
|
||||
forAll(pointSets, i)
|
||||
{
|
||||
pointSets[i].write();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reconstruct refinement data
|
||||
{
|
||||
PtrList<hexRef8Data> procData(procMeshes.meshes().size());
|
||||
|
||||
forAll(procMeshes.meshes(), procI)
|
||||
{
|
||||
const fvMesh& procMesh = procMeshes.meshes()[procI];
|
||||
|
||||
procData.set
|
||||
(
|
||||
procI,
|
||||
new hexRef8Data
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"dummy",
|
||||
procMesh.time().timeName(),
|
||||
polyMesh::meshSubDir,
|
||||
procMesh,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Combine individual parts
|
||||
|
||||
const PtrList<labelIOList>& cellAddr =
|
||||
procMeshes.cellProcAddressing();
|
||||
|
||||
UPtrList<const labelList> cellMaps(cellAddr.size());
|
||||
forAll(cellAddr, i)
|
||||
{
|
||||
cellMaps.set(i, &cellAddr[i]);
|
||||
}
|
||||
|
||||
const PtrList<labelIOList>& pointAddr =
|
||||
procMeshes.pointProcAddressing();
|
||||
|
||||
UPtrList<const labelList> pointMaps(pointAddr.size());
|
||||
forAll(pointAddr, i)
|
||||
{
|
||||
pointMaps.set(i, &pointAddr[i]);
|
||||
}
|
||||
|
||||
UPtrList<const hexRef8Data> procRefs(procData.size());
|
||||
forAll(procData, i)
|
||||
{
|
||||
procRefs.set(i, &procData[i]);
|
||||
}
|
||||
|
||||
hexRef8Data
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"dummy",
|
||||
mesh.time().timeName(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
cellMaps,
|
||||
pointMaps,
|
||||
procRefs
|
||||
).write();
|
||||
}
|
||||
|
||||
// If there is a "uniform" directory in the time region
|
||||
// directory copy from the master processor
|
||||
{
|
||||
@ -975,13 +620,17 @@ int main(int argc, char *argv[])
|
||||
(
|
||||
fileHandler().filePath
|
||||
(
|
||||
databases[0].timePath()/regionDir/"uniform"
|
||||
runTimes.procTimes()[0].timePath()/regionDir/"uniform"
|
||||
)
|
||||
);
|
||||
|
||||
if (!uniformDir0.empty() && fileHandler().isDir(uniformDir0))
|
||||
{
|
||||
fileHandler().cp(uniformDir0, runTime.timePath()/regionDir);
|
||||
fileHandler().cp
|
||||
(
|
||||
uniformDir0,
|
||||
runTimes.completeTime().timePath()/regionDir
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -993,13 +642,17 @@ int main(int argc, char *argv[])
|
||||
(
|
||||
fileHandler().filePath
|
||||
(
|
||||
databases[0].timePath()/"uniform"
|
||||
runTimes.procTimes()[0].timePath()/"uniform"
|
||||
)
|
||||
);
|
||||
|
||||
if (!uniformDir0.empty() && fileHandler().isDir(uniformDir0))
|
||||
{
|
||||
fileHandler().cp(uniformDir0, runTime.timePath());
|
||||
fileHandler().cp
|
||||
(
|
||||
uniformDir0,
|
||||
runTimes.completeTime().timePath()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user