ENH: Lagrangian - provided backwards compatibility for cases using the

old "positions" file form

The change to barycentric-based tracking changed the contents of the
cloud "positions" file to a new format comprising the barycentric
co-ordinates and other cell position-based info.  This broke
backwards compatibility, providing no option to restart old cases
(v1706 and earlier), and caused difficulties for dependent code, e.g.
for post-processing utilities that could only infer the contents only
after reading.

The barycentric position info is now written to a file called
"coordinates" with provision to restart old cases for which only the
"positions" file is available. Related utilities, e.g. for parallel
running and data conversion have been updated to be able to support both
file types.

To write the "positions" file by default, use set the following option
in the InfoSwitches section of the controlDict:

    writeLagrangianPositions 1;
This commit is contained in:
Andrew Heather
2017-09-13 13:13:36 +01:00
parent 87e3da80ec
commit 2defba00a9
60 changed files with 475 additions and 185 deletions

View File

@ -35,8 +35,8 @@ if (timeDirs.size() && !noLagrangian)
cloudPrefix/cloudName
);
// Clouds always have "positions"
if (cloudObjs.found("positions"))
// Clouds always have "positions" (v1706 and lower) or "coordinates"
if (cloudObjs.found("positions") || cloudObjs.found("coordinates"))
{
// Save the cloud fields on a per cloud basis
auto fieldsPerCloud = cloudFields(cloudName);
@ -52,9 +52,10 @@ if (timeDirs.size() && !noLagrangian)
}
}
// Prune out "positions" again since it gets treated specially
// Prune out geometry again since it gets treated specially
forAllIters(cloudFields, cloudIter)
{
cloudIter().erase("coordinates");
cloudIter().erase("positions");
}
@ -74,4 +75,5 @@ if (cloudNames.size())
cloudNames.writeList(Info) << endl;
}
// ************************************************************************* //

View File

@ -65,7 +65,7 @@ void Foam::ensightSerialCloud::writePositions
forAllConstIter(Cloud<passiveParticle>, cloudPtr(), elmnt)
{
const vector& p = elmnt().position();
const vector p(elmnt().position());
os.write(p.x());
os.write(p.y());
@ -79,7 +79,7 @@ void Foam::ensightSerialCloud::writePositions
label parcelId = 0;
forAllConstIter(Cloud<passiveParticle>, cloudPtr(), elmnt)
{
const vector& p = elmnt().position();
const vector p(elmnt().position());
os.write(++parcelId, 8); // unusual width
os.write(p.x());

View File

@ -60,16 +60,16 @@ if (timeDirs.size())
cloudPrefix/cloudName
);
bool hasPositions = false;
bool hasCoordinates = false;
forAllConstIter(IOobjectList, objs, fieldIter)
{
const IOobject obj = *fieldIter();
const word& fieldName = obj.name();
const word& fieldType = obj.headerClassName();
if (fieldName == "positions")
if (fieldName == "positions" || fieldName == "coordinates")
{
hasPositions = true;
hasCoordinates = true;
}
else if (cloudFieldTypes.found(fieldType))
{
@ -79,7 +79,7 @@ if (timeDirs.size())
}
// drop this cloud if it has no positions or is otherwise empty
if (!hasPositions || cloudIter().empty())
if (!hasCoordinates || cloudIter().empty())
{
Info<< "removing cloud " << cloudName << endl;
cloudFields.erase(cloudIter);

View File

@ -381,8 +381,13 @@ int main(int argc, char *argv[])
cloudPrefix/cloudName
);
// Check that the positions field is present for this time
if (!cloudObjs.found("positions"))
// Check that the positions/coordinates field is present for this
// time
if
(
!cloudObjs.found("positions")
|| !cloudObjs.found("coordinates")
)
{
continue;
}

View File

@ -62,7 +62,7 @@ for (label i=0; i < nTypes; i++)
if (fieldTypes[i] == cloud::prefix)
{
IOobject lagrangianHeader
IOobject positionsHeader
(
"positions",
runTime.timeName(),
@ -71,9 +71,22 @@ for (label i=0; i < nTypes; i++)
IOobject::NO_READ
);
IOobject coordinatesHeader
(
"coordinates",
runTime.timeName(),
cloud::prefix,
mesh,
IOobject::NO_READ
);
if
(
lagrangianHeader.typeHeaderOk<IOPosition<Cloud<passiveParticle>>>
positionsHeader.typeHeaderOk<IOPosition<Cloud<passiveParticle>>>
(
false
)
|| coordinatesHeader.typeHeaderOk<IOPosition<Cloud<passiveParticle>>>
(
false
)

View File

@ -1168,8 +1168,9 @@ int main(int argc, char *argv[])
);
IOobject* positionsPtr = sprayObjs.lookup("positions");
IOobject* coordinatesPtr = sprayObjs.lookup("coordinates");
if (positionsPtr)
if (positionsPtr || coordinatesPtr)
{
mkDir(fvPath/cloud::prefix/cloudDirs[cloudI]);

View File

@ -23,10 +23,8 @@ if (timeDirs.size() && !noLagrangian)
fileName::DIRECTORY
);
forAll(cloudDirs, cloudI)
for (const word& cloudName : cloudDirs)
{
const word& cloudName = cloudDirs[cloudI];
IOobjectList cloudObjs
(
mesh,
@ -34,8 +32,8 @@ if (timeDirs.size() && !noLagrangian)
cloudPrefix/cloudName
);
// clouds always require "positions"
if (cloudObjs.found("positions"))
// Clouds always require "positions"/"coordinates"
if (cloudObjs.found("positions") || cloudObjs.found("coordinates"))
{
if (allCloudDirs.insert(cloudName))
{
@ -60,9 +58,9 @@ if (cloudNames.size())
{
// complete the echo information
Info<< "(";
forAll(cloudNames, cloudNo)
for (const word& cloudName : cloudNames)
{
Info<< ' ' << cloudNames[cloudNo];
Info<< ' ' << cloudName;
}
Info<< " ) " << endl;
}

View File

@ -1344,7 +1344,7 @@ int main(int argc, char *argv[])
cloud::prefix/cloudName
);
if (sprayObjs.found("positions"))
if (sprayObjs.found("positions") || sprayObjs.found("coordinates"))
{
wordList labelNames(sprayObjs.names(labelIOField::typeName));
Info<< " labels :";