mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: improve startup time for foamToEnsight conversion (issue #240).
Old code:
Found 10990 time steps
Search for moving mesh ... no moving mesh detected.
Startup in 329.09 s
Updated:
Found 10990 time steps
Search for moving mesh ... no moving mesh detected.
Startup in 1.6 s
- Cause was checking "polyMesh/points" via an IOobject.
Short-circuit with a check for a polyMesh/ directory first.
Limit the check to the master-node as well to further reduce
load on the file-system.
------------------------------
ENH: improve per-step conversion times for foamToEnsight.
Old code:
Converting 11001 time steps
Time [0] = 0 Wrote in 1.53 s
Time [1] = 1 Wrote in 1.52 s
...
Time [100] = 100 Elapsed time 205.35 s
Updated:
Converting 11001 time steps
Time [0] = 0 Wrote in 1.4 s
Time [1] = 1 Wrote in 0.07 s
...
Time [100] = 100 Elapsed time 42.4 s
- Speedup by hashing test results from the first conversion step
instead of checking each time.
Check data on all nodes to avoid problems with incomplete writes.
------------------------------
BUG: moving mesh detection failed for foamToEnsightParts
- adjusted to agree with updated foamToEnsight
------------------------------
Note:
- foamToEnsightParts (serial) still has about twice the throughput of
foamToEnsight.
This commit is contained in:
@ -1,21 +1,33 @@
|
||||
// ignore special fields or fields that we don't handle
|
||||
//
|
||||
bool variableGood = true;
|
||||
for (label n1=0; n1<timeDirs.size() && variableGood; ++n1)
|
||||
// ignore special fields (_0 fields),
|
||||
// ignore fields we don't handle,
|
||||
// ignore fields that are not available for all time-steps
|
||||
|
||||
// hash by field-name in fieldsToUse
|
||||
if (!fieldsToUse.found(fieldName))
|
||||
{
|
||||
// ignore _0 fields
|
||||
if (fieldName.size() > 2 && fieldName(fieldName.size() - 2, 2) == "_0")
|
||||
bool variableGood = false;
|
||||
|
||||
forAll(timeDirs, n1)
|
||||
{
|
||||
variableGood = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
variableGood = IOobject
|
||||
variableGood =
|
||||
(
|
||||
fieldName,
|
||||
timeDirs[n1].name(),
|
||||
mesh,
|
||||
IOobject::NO_READ
|
||||
).typeHeaderOk<volScalarField>(false);
|
||||
fieldName.size() > 2 && fieldName(fieldName.size() - 2, 2) == "_0"
|
||||
? false
|
||||
: IOobject
|
||||
(
|
||||
fieldName,
|
||||
timeDirs[n1].name(),
|
||||
mesh,
|
||||
IOobject::NO_READ
|
||||
).typeHeaderOk<volScalarField>(false)
|
||||
);
|
||||
|
||||
if (variableGood)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
reduce(variableGood, andOp<bool>());
|
||||
fieldsToUse.set(fieldName, variableGood);
|
||||
}
|
||||
|
||||
@ -1,27 +1,48 @@
|
||||
// check for "points" in any of the result directories
|
||||
|
||||
bool meshMoving = false;
|
||||
if (timeDirs.size() > 1)
|
||||
|
||||
if (timeDirs.size() > 1 && Pstream::master())
|
||||
{
|
||||
// We already loaded a mesh (usually from constant). See if any other
|
||||
// points files
|
||||
// We already loaded a mesh (usually from constant).
|
||||
// See if any other "polyMesh/points" files exist too.
|
||||
|
||||
const fileName& baseDir = mesh.time().path();
|
||||
|
||||
Info<< "Search for moving mesh ... " << flush;
|
||||
forAll(timeDirs, timeI)
|
||||
{
|
||||
if (timeDirs[timeI].name() != mesh.pointsInstance())
|
||||
{
|
||||
meshMoving = IOobject
|
||||
meshMoving =
|
||||
(
|
||||
timeDirs[timeI].name() != mesh.pointsInstance()
|
||||
&& isDir(baseDir/timeDirs[timeI].name()/polyMesh::meshSubDir)
|
||||
&& IOobject
|
||||
(
|
||||
"points",
|
||||
timeDirs[timeI].name(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::NO_READ
|
||||
).typeHeaderOk<pointIOField>(true);
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false // no register
|
||||
).typeHeaderOk<pointIOField>(true)
|
||||
);
|
||||
|
||||
if (meshMoving)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (meshMoving)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (meshMoving)
|
||||
{
|
||||
Info<< "found." << nl
|
||||
<< " Writing meshes for every timestep." << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "none detected." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
reduce(meshMoving, orOp<bool>());
|
||||
|
||||
@ -189,7 +189,7 @@ int main(int argc, char *argv[])
|
||||
#include "setRootCase.H"
|
||||
|
||||
// default to binary output, unless otherwise specified
|
||||
const enum IOstream::streamFormat format =
|
||||
const IOstream::streamFormat format =
|
||||
(
|
||||
args.optionFound("ascii")
|
||||
? IOstream::ASCII
|
||||
@ -255,7 +255,9 @@ int main(int argc, char *argv[])
|
||||
if (Pstream::master())
|
||||
{
|
||||
fileName caseFileName = args.globalCaseName() + ".case";
|
||||
Info<< nl << "write case: " << caseFileName.c_str() << endl;
|
||||
|
||||
Info<< "Converting " << timeDirs.size() << " time steps" << nl
|
||||
<< "Ensight case: " << caseFileName.c_str() << endl;
|
||||
|
||||
// The case file is always ASCII
|
||||
ensightCaseFilePtr = new OFstream
|
||||
@ -333,12 +335,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
#include "checkMeshMoving.H"
|
||||
|
||||
if (meshMoving)
|
||||
{
|
||||
Info<< "Detected a moving mesh (multiple polyMesh/points files)."
|
||||
<< " Writing meshes for every timestep." << endl;
|
||||
}
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
// test the pre-check variable if there is a moving mesh
|
||||
@ -400,6 +396,11 @@ int main(int argc, char *argv[])
|
||||
cloudNames = allCloudNames.sortedToc();
|
||||
}
|
||||
|
||||
// ignore special fields (_0 fields),
|
||||
// ignore fields we don't handle,
|
||||
// ignore fields that are not available for all time-steps
|
||||
HashTable<bool> fieldsToUse;
|
||||
|
||||
HashTable<HashTable<word>> allCloudFields;
|
||||
forAll(cloudNames, cloudNo)
|
||||
{
|
||||
@ -451,6 +452,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "Startup in "
|
||||
<< timer.cpuTimeIncrement() << " s, "
|
||||
<< mem.update().size() << " kB" << nl << endl;
|
||||
|
||||
label nTimeSteps = 0;
|
||||
forAll(timeDirs, timeIndex)
|
||||
{
|
||||
@ -515,7 +520,7 @@ int main(int argc, char *argv[])
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~
|
||||
Info<< "Write volume field (";
|
||||
|
||||
for (label i=0; i<nVolFieldTypes; i++)
|
||||
for (label i=0; i<nVolFieldTypes; ++i)
|
||||
{
|
||||
wordList fieldNames = objects.names(volFieldTypes[i]);
|
||||
|
||||
@ -534,7 +539,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
#include "checkData.H"
|
||||
|
||||
if (!variableGood)
|
||||
if (!fieldsToUse[fieldName])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -719,9 +724,14 @@ int main(int argc, char *argv[])
|
||||
ensightCaseFile
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not currently handle this type - blacklist for the future.
|
||||
fieldsToUse.set(fieldName, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Info<< " )" << endl;
|
||||
Info<< " )" << nl;
|
||||
|
||||
|
||||
// Cloud field data output
|
||||
@ -808,12 +818,12 @@ int main(int argc, char *argv[])
|
||||
);
|
||||
}
|
||||
}
|
||||
Info<< " )" << endl;
|
||||
Info<< " )" << nl;
|
||||
}
|
||||
|
||||
Info<< "Wrote in "
|
||||
<< timer.cpuTimeIncrement() << " s, "
|
||||
<< mem.update().size() << " kB" << nl << endl;
|
||||
<< mem.update().size() << " kB" << nl << nl;
|
||||
}
|
||||
|
||||
#include "ensightCaseTail.H"
|
||||
|
||||
@ -2,18 +2,47 @@
|
||||
// - could restrict to the selected times
|
||||
|
||||
bool hasMovingMesh = false;
|
||||
if (timeDirs.size() > 1)
|
||||
|
||||
if (timeDirs.size() > 1 && Pstream::master())
|
||||
{
|
||||
hasMovingMesh = true;
|
||||
for (label i=0; i < timeDirs.size() && hasMovingMesh; ++i)
|
||||
// We already loaded a mesh (usually from constant).
|
||||
// See if any other "polyMesh/points" files exist too.
|
||||
|
||||
const fileName& baseDir = mesh.time().path();
|
||||
|
||||
Info<< "Search for moving mesh ... " << flush;
|
||||
forAll(timeDirs, timeI)
|
||||
{
|
||||
hasMovingMesh = IOobject
|
||||
hasMovingMesh =
|
||||
(
|
||||
"points",
|
||||
timeDirs[i].name(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::NO_READ
|
||||
).typeHeaderOk<pointIOField>(true);
|
||||
isDir(baseDir/timeDirs[timeI].name()/polyMesh::meshSubDir)
|
||||
&& IOobject
|
||||
(
|
||||
"points",
|
||||
timeDirs[timeI].name(),
|
||||
polyMesh::meshSubDir,
|
||||
mesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false // no register
|
||||
).typeHeaderOk<pointIOField>(true)
|
||||
);
|
||||
|
||||
if (hasMovingMesh)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasMovingMesh)
|
||||
{
|
||||
Info<< "found." << nl
|
||||
<< " Writing meshes for every timestep." << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "none detected." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
reduce(hasMovingMesh, orOp<bool>());
|
||||
|
||||
@ -149,11 +149,12 @@ int main(int argc, char *argv[])
|
||||
instantList timeDirs = timeSelector::select0(runTime, args);
|
||||
|
||||
// default to binary output, unless otherwise specified
|
||||
IOstream::streamFormat format = IOstream::BINARY;
|
||||
if (args.optionFound("ascii"))
|
||||
{
|
||||
format = IOstream::ASCII;
|
||||
}
|
||||
const IOstream::streamFormat format =
|
||||
(
|
||||
args.optionFound("ascii")
|
||||
? IOstream::ASCII
|
||||
: IOstream::BINARY
|
||||
);
|
||||
|
||||
// control for renumbering iterations
|
||||
label indexingNumber = 0;
|
||||
@ -204,6 +205,11 @@ int main(int argc, char *argv[])
|
||||
regionPrefix = regionName;
|
||||
}
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
Info<< "Converting " << timeDirs.size() << " time steps" << endl;
|
||||
}
|
||||
|
||||
// Construct the list of ensight parts for the entire mesh
|
||||
ensightParts partsList(mesh);
|
||||
|
||||
@ -244,6 +250,9 @@ int main(int argc, char *argv[])
|
||||
cloudTimesUsed.insert(cloudIter.key(), DynamicList<label>());
|
||||
}
|
||||
|
||||
Info<< "Startup in "
|
||||
<< timer.cpuTimeIncrement() << " s, "
|
||||
<< mem.update().size() << " kB" << nl << endl;
|
||||
|
||||
forAll(timeDirs, timeI)
|
||||
{
|
||||
|
||||
@ -39,5 +39,5 @@
|
||||
}
|
||||
|
||||
timeIndices.insert(timeIndex, timeDirs[timeI].value());
|
||||
Info<< "\nTime [" << timeIndex << "] = " << runTime.timeName() << nl;
|
||||
Info<< nl << "Time [" << timeIndex << "] = " << runTime.timeName() << nl;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user