diff --git a/applications/solvers/incompressible/shallowWaterFoam/createFields.H b/applications/solvers/incompressible/shallowWaterFoam/createFields.H index 7e323166dd4d3d93b8da0f902cb0a8ebdeaaac02..aa121410c817cecc306e4a8c44dfbebbddcb7ff1 100644 --- a/applications/solvers/incompressible/shallowWaterFoam/createFields.H +++ b/applications/solvers/incompressible/shallowWaterFoam/createFields.H @@ -20,7 +20,7 @@ volScalarField h0 IOobject ( "h0", - runTime.findInstance("polyMesh", "points"), + runTime.findInstance(polyMesh::meshSubDir, "points"), mesh, IOobject::READ_IF_PRESENT ), diff --git a/applications/utilities/mesh/conversion/fluentMeshToFoam/fluentMeshToFoam.L b/applications/utilities/mesh/conversion/fluentMeshToFoam/fluentMeshToFoam.L index 30f337f17ba79aafb58bef69fb6c32cbb899ed25..d8e193f9a4452eca4ccbfe2e03f3550243c5d24c 100644 --- a/applications/utilities/mesh/conversion/fluentMeshToFoam/fluentMeshToFoam.L +++ b/applications/utilities/mesh/conversion/fluentMeshToFoam/fluentMeshToFoam.L @@ -1698,7 +1698,7 @@ int main(int argc, char *argv[]) fileName bczf ( runTime.path()/runTime.constant() - /"polyMesh"/"boundaryAdjacentCellZones" + /polyMesh::meshSubDir/"boundaryAdjacentCellZones" ); OFstream boundaryCellZonesFile(bczf); diff --git a/src/OpenFOAM/db/IOobject/IOobject.H b/src/OpenFOAM/db/IOobject/IOobject.H index a4a922a3755d7622f106a92dd39891a4e1de5d20..ec18145cbe9187a0e3ee23723d205f84f00fff2c 100644 --- a/src/OpenFOAM/db/IOobject/IOobject.H +++ b/src/OpenFOAM/db/IOobject/IOobject.H @@ -39,30 +39,30 @@ Description \par Read options Define what is done on object construction and explicit reads: + - \par NO_READ + Do not read - \par MUST_READ Object must be read from Istream on construction. \n - Error if Istream does not exist or can't be read. + Error if Istream does not exist or cannot be read. Does not check timestamp or re-read. - \par MUST_READ_IF_MODIFIED Object must be read from Istream on construction. \n - Error if Istream does not exist or can't be read. If object is + Error if Istream does not exist or cannot be read. If object is registered its timestamp will be checked every timestep and possibly re-read. - \par READ_IF_PRESENT - Read object from Istream if Istream exists, otherwise don't. \n - Error only if Istream exists but can't be read. + Read object from Istream, but only if Istream exists. \n + Error only if Istream exists but cannot be read. Does not check timestamp or re-read. - - \par NO_READ - Don't read \par Write options Define what is done on object destruction and explicit writes: + - \par NO_WRITE + No automatic writing, but can be written explicitly - \par AUTO_WRITE Object is written automatically when requested to by the objectRegistry. - - \par NO_WRITE - No automatic write on destruction but can be written explicitly When serializing, the IOobject characteristics are typically written as a \c FoamFile header, which is a sub-dictionary with the following @@ -95,8 +95,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef IOobject_H -#define IOobject_H +#ifndef Foam_IOobject_H +#define Foam_IOobject_H #include "fileName.H" #include "typeInfo.H" @@ -135,17 +135,17 @@ public: //- Enumeration defining the read options enum readOption : char { - MUST_READ, - MUST_READ_IF_MODIFIED, - READ_IF_PRESENT, - NO_READ + NO_READ = 0, + MUST_READ = 1, + MUST_READ_IF_MODIFIED = 3, + READ_IF_PRESENT = 4 }; //- Enumeration defining the write options enum writeOption : char { - AUTO_WRITE = 0, - NO_WRITE = 1 + NO_WRITE = 0, + AUTO_WRITE = 0x10 }; //- Enumeration defining the file checking options diff --git a/src/OpenFOAM/db/Time/Time.C b/src/OpenFOAM/db/Time/Time.C index 9ec468502d96cd28e86a99c60fd20ee5243bf1bf..522295285294e08f58584d7476f5800bb3aae100 100644 --- a/src/OpenFOAM/db/Time/Time.C +++ b/src/OpenFOAM/db/Time/Time.C @@ -801,14 +801,8 @@ Foam::word Foam::Time::findInstance const word& stopInstance ) const { - IOobject startIO - ( - name, // name might be empty! - timeName(), - dir, - *this, - rOpt - ); + // Note: name might be empty! + IOobject startIO(name, timeName(), dir, *this, rOpt); IOobject io ( diff --git a/src/OpenFOAM/db/Time/Time.H b/src/OpenFOAM/db/Time/Time.H index 75f0a01eae6f5ad5dd1d9fdb23f4ff1be416ace6..d19b87d761470f101df0a632ad2ed7b865714a82 100644 --- a/src/OpenFOAM/db/Time/Time.H +++ b/src/OpenFOAM/db/Time/Time.H @@ -38,8 +38,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef Time_H -#define Time_H +#ifndef Foam_Time_H +#define Foam_Time_H #include "TimePaths.H" #include "objectRegistry.H" @@ -420,10 +420,15 @@ public: //- Read the objects that have been modified void readModifiedObjects(); - //- Return the location of "dir" containing the file "name". - //- (eg, used in reading mesh data) - // If name is null, search for the directory "dir" only. - // Does not search beyond stopInstance (if set) or constant. + //- Return time instance (location) of \em dir that contains + //- the file \em name (eg, used in reading mesh data). + // When \em is empty, searches for directory \em dir only. + // Does not search beyond stopInstance (if set) or \em constant. + // + // \note If the instance cannot be found, returns the + // stopInstance (if set and reached) or \em constant. + // FatalError if it cannot be found and readOpt is + // (MUST_READ or MUST_READ_IF_MODIFIED). word findInstance ( const fileName& dir, diff --git a/src/OpenFOAM/db/regIOobject/regIOobject.H b/src/OpenFOAM/db/regIOobject/regIOobject.H index 94fef1cabf8c244215d9beee90de8f3ab49c8585..a02e5f9170ad95de640f1b4ff8f77da654a3e085 100644 --- a/src/OpenFOAM/db/regIOobject/regIOobject.H +++ b/src/OpenFOAM/db/regIOobject/regIOobject.H @@ -297,7 +297,7 @@ public: // (e.g. IOdictionary) virtual fileName filePath() const; - //- Read and check header info + //- Read and check header info. Does not check the headerClassName. bool headerOk(); //- Return Istream and check object type against that given diff --git a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C index fd144b6a4f3fdf56e0885824a3f43629438fbae3..f8af19d9da0a5a3df40f092636b43aecfec1d058 100644 --- a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C +++ b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C @@ -1006,7 +1006,6 @@ Foam::IOobject Foam::fileOperation::findInstance ) const { const Time& time = startIO.time(); - IOobject io(startIO); // Note: - if name is empty, just check the directory itself @@ -1025,120 +1024,140 @@ Foam::IOobject Foam::fileOperation::findInstance return io; } - // Search back through the time directories to find the first time - // that is less than or equal to the current time + // Handling failures afterwards + const bool exitIfMissing + ( + startIO.readOpt() == IOobject::MUST_READ + || startIO.readOpt() == IOobject::MUST_READ_IF_MODIFIED + ); - instantList ts = time.times(); - label instanceI = ts.size()-1; + enum failureCodes { FAILED_STOPINST = 1, FAILED_CONSTINST = 2 }; + int failed(0); - for (; instanceI >= 0; --instanceI) - { - if (ts[instanceI].value() <= startValue) - { - break; - } - } + instantList ts = time.times(); - // Found the time, continue from here - for (; instanceI >= 0; --instanceI) { - io.instance() = ts[instanceI].name(); + label instIndex = ts.size()-1; - // Shortcut: if actual directory is the timeName we've already tested it - if - ( - io.instance() == startIO.instance() - && io.instance() != stopInstance - ) + // Backward search for first time that is <= startValue + for (; instIndex >= 0; --instIndex) { - continue; - } - - if (exists(io)) - { - DebugInFunction - << "Found exact match for \"" << io.name() - << "\" in " << io.instance()/io.local() - << endl; - - return io; + if (ts[instIndex].value() <= startValue) + { + break; + } } - // Check if hit minimum instance - if (io.instance() == stopInstance) + // Continue (forward) searching from here + for (; instIndex >= 0; --instIndex) { - DebugInFunction - << "Hit stopInstance " << stopInstance << endl; + io.instance() = ts[instIndex].name(); + // Shortcut: if actual directory is the timeName we've + // already tested it if ( - startIO.readOpt() == IOobject::MUST_READ - || startIO.readOpt() == IOobject::MUST_READ_IF_MODIFIED + io.instance() == startIO.instance() + && io.instance() != stopInstance ) { - if (io.name().empty()) + continue; + } + + if (exists(io)) + { + DebugInFunction + << "Found exact match for \"" << io.name() + << "\" in " << io.instance()/io.local() + << endl; + + return io; + } + + // Check if hit minimum instance + if (io.instance() == stopInstance) + { + DebugInFunction + << "Hit stopInstance " << stopInstance << endl; + + if (exitIfMissing) { - FatalErrorInFunction - << "Cannot find directory " - << io.local() << " in times " << startIO.instance() - << " down to " << stopInstance - << exit(FatalError); + failed = failureCodes::FAILED_STOPINST; } else { - FatalErrorInFunction - << "Cannot find file \"" << io.name() - << "\" in directory " << io.local() - << " in times " << startIO.instance() - << " down to " << stopInstance - << exit(FatalError); + return io; } + break; } - - return io; } - } - // Times usually already includes 'constant' so would have been checked - // above. - // However, re-test under these conditions: - // - Times is empty. - // Sometimes this can happen (eg, decomposePar with collated) - // - Times[0] is not constant - // - The startValue is negative (eg, kivaTest). - // This plays havoc with the reverse search, causing it to miss 'constant' - if - ( - ts.empty() - || ts.first().name() != time.constant() - || startValue < 0 - ) - { - io.instance() = time.constant(); - if (exists(io)) + // times() usually already includes the constant() so would + // have been checked above. However, re-test under these conditions: + // - times() is empty. Sometimes this can happen (e.g. decomposePar + // with collated) + // - times()[0] is not constant + // - Times is empty. + // Sometimes this can happen (eg, decomposePar with collated) + // - Times[0] is not constant + // - The startValue is negative (eg, kivaTest). + // This plays havoc with the reverse search, causing it to miss + // 'constant' + + if + ( + !failed + && (ts.empty() || ts[0].name() != time.constant() || startValue < 0) + ) { - DebugInFunction - << "Found constant match for \"" << io.name() - << "\" in " << io.instance()/io.local() - << endl; + io.instance() = time.constant(); + + if (exists(io)) + { + DebugInFunction + << "Found constant match for \"" << io.name() + << "\" in " << io.instance()/io.local() + << endl; - return io; + return io; + } } } - if - ( - startIO.readOpt() == IOobject::MUST_READ - || startIO.readOpt() == IOobject::MUST_READ_IF_MODIFIED - ) + if (!failed && exitIfMissing) + { + failed = failureCodes::FAILED_CONSTINST; + } + + // Handle failures + // ~~~~~~~~~~~~~~~ + + if (failed) { - FatalErrorInFunction - << "Cannot find file \"" << io.name() << "\" in directory " - << io.local() << " in times " << startIO.instance() - << " down to " << time.constant() - << exit(FatalError); + FatalErrorInFunction << "Cannot find"; + + if (!io.name().empty()) + { + FatalError + << " file \"" << io.name() << "\" in"; + } + + FatalError + << " directory " + << io.local() << " in times " + << startIO.instance() << " down to "; + + if (failed == failureCodes::FAILED_STOPINST) + { + FatalError << stopInstance; + } + else + { + FatalError << "constant"; + } + FatalError << exit(FatalError); } return io; @@ -1225,7 +1244,8 @@ Foam::label Foam::fileOperation::nProcs { WarningInFunction << "Defunct collated naming: " << processorsBaseDir << nl - << "Manually rename with the decomposition number. Eg," << nl << nl + << "Manually rename with the decomposition number. Eg," + << nl << nl << " mv processors processors16" << nl << nl << "...returning 1" << endl; diff --git a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H index 6c0e2c4db51858866b6be9f2d549ed9f7108532e..465f33d8f01d493afb1272c9357abea01a87b999 100644 --- a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H +++ b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H @@ -535,9 +535,10 @@ public: //- Get sorted list of times virtual instantList findTimes(const fileName&, const word&) const; - //- Find instance where IOobject is. Fails if cannot be found - // and readOpt() is MUST_READ/MUST_READ_IF_MODIFIED. Otherwise - // returns stopInstance. + //- Find instance where IOobject is. + // FatalError if it cannot be found and readOpt is + // (MUST_READ or MUST_READ_IF_MODIFIED). + // Otherwise it returns the stopInstance. virtual IOobject findInstance ( const IOobject& io, diff --git a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C index e985abd4a077acdc03131ce2ad119fd5e8d673bf..a2599f2fb293e3acdf4101c131ee25096b1fb7e2 100644 --- a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C +++ b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C @@ -1443,9 +1443,7 @@ Foam::fileOperations::masterUncollatedFileOperation::findInstance << endl; } - const Time& time = startIO.time(); - IOobject io(startIO); // Note: - if name is empty, just check the directory itself @@ -1486,36 +1484,45 @@ Foam::fileOperations::masterUncollatedFileOperation::findInstance } - // Search back through the time directories to find the time - // closest to and lower than current time + // Handling failures afterwards + const bool exitIfMissing + ( + startIO.readOpt() == IOobject::MUST_READ + || startIO.readOpt() == IOobject::MUST_READ_IF_MODIFIED + ); + + enum failureCodes { FAILED_STOPINST = 1, FAILED_CONSTINST = 2 }; + int failed(0); instantList ts = time.times(); + // if (Pstream::master(comm_)) if (Pstream::master(UPstream::worldComm)) { const bool oldParRun(Pstream::parRun(false)); - label instanceI; + label instIndex = ts.size()-1; - for (instanceI = ts.size()-1; instanceI >= 0; --instanceI) + // Backward search for first time that is <= startValue + for (; instIndex >= 0; --instIndex) { - if (ts[instanceI].value() <= startValue) + if (ts[instIndex].value() <= startValue) { break; } } - // continue searching from here - for (; instanceI >= 0; --instanceI) + // Continue (forward) searching from here + for (; instIndex >= 0; --instIndex) { // Shortcut: if actual directory is the timeName we've // already tested it - if (ts[instanceI].name() == time.timeName()) + if (ts[instIndex].name() == time.timeName()) { continue; } - io.instance() = ts[instanceI].name(); + io.instance() = ts[instIndex].name(); if (exists(pDirs, io)) { foundInstance = io.instance(); @@ -1530,97 +1537,115 @@ Foam::fileOperations::masterUncollatedFileOperation::findInstance } // Check if hit minimum instance - if (ts[instanceI].name() == stopInstance) + if (io.instance() == stopInstance) { - if - ( - startIO.readOpt() == IOobject::MUST_READ - || startIO.readOpt() == IOobject::MUST_READ_IF_MODIFIED - ) - { - if (io.name().empty()) - { - FatalErrorInFunction - << "Cannot find directory " - << io.local() << " in times " << time.timeName() - << " down to " << stopInstance - << exit(FatalError); - } - else - { - FatalErrorInFunction - << "Cannot find file \"" << io.name() - << "\" in directory " << io.local() - << " in times " << time.timeName() - << " down to " << stopInstance - << exit(FatalError); - } - } - foundInstance = io.instance(); if (debug) { Pout<< "masterUncollatedFileOperation::findInstance :" - << " name:" << io.name() << " local:" << io.local() - << " found at stopinstance:" << io.instance() << endl; + << " name:" << io.name() + << " local:" << io.local() + << " at stop-instance:" << io.instance() << endl; + } + + if (exitIfMissing) + { + failed = failureCodes::FAILED_STOPINST; + } + else + { + foundInstance = io.instance(); } break; } } - if (foundInstance.empty()) + // times() usually already includes the constant() so would + // have been checked above. However, re-test under these conditions: + // - times() is empty. Sometimes this can happen (e.g. decomposePar + // with collated) + // - times()[0] is not constant + // - Times is empty. + // Sometimes this can happen (eg, decomposePar with collated) + // - Times[0] is not constant + // - The startValue is negative (eg, kivaTest). + // This plays havoc with the reverse search, causing it to miss + // 'constant' + + if + ( + !failed && foundInstance.empty() + && (ts.empty() || ts[0].name() != time.constant() || startValue < 0) + ) { - // times() usually already includes the constant() so would - // have been checked above. Re-test if - // - times() is empty. Sometimes this can happen (e.g. decomposePar - // with collated) - // - times()[0] is not constant - if (!ts.size() || ts[0].name() != time.constant()) - { - // Note. This needs to be a hard-coded constant, rather than the - // constant function of the time, because the latter points to - // the case constant directory in parallel cases + // Note. This needs to be a hard-coded "constant" (not constant + // function of Time), because the latter points to + // the case constant directory in parallel cases. + // However, parRun is disabled so they are actually the same. + + io.instance() = time.constant(); - io.instance() = time.constant(); - if (exists(pDirs, io)) + if (exists(pDirs, io)) + { + if (debug) { - if (debug) - { - Pout<< "masterUncollatedFileOperation::findInstance :" - << " name:" << io.name() - << " local:" << io.local() - << " found at:" << io.instance() << endl; - } - foundInstance = io.instance(); + Pout<< "masterUncollatedFileOperation::findInstance :" + << " name:" << io.name() + << " local:" << io.local() + << " at:" << io.instance() << endl; } + foundInstance = io.instance(); } } - if (foundInstance.empty()) + if (!failed && foundInstance.empty()) { - if - ( - startIO.readOpt() == IOobject::MUST_READ - || startIO.readOpt() == IOobject::MUST_READ_IF_MODIFIED - ) + if (exitIfMissing) { - FatalErrorInFunction - << "Cannot find file \"" << io.name() << "\" in directory " - << io.local() << " in times " << startIO.instance() - << " down to " << time.constant() - << exit(FatalError); + failed = failureCodes::FAILED_CONSTINST; } else { foundInstance = time.constant(); } } - Pstream::parRun(oldParRun); + + UPstream::parRun(oldParRun); // Restore parallel state } // Pstream::broadcast(foundInstance, comm_); Pstream::broadcast(foundInstance, UPstream::worldComm); io.instance() = foundInstance; + + + // Handle failures + // ~~~~~~~~~~~~~~~ + if (failed) + { + FatalErrorInFunction << "Cannot find"; + + if (!io.name().empty()) + { + FatalError + << " file \"" << io.name() << "\" in"; + } + + FatalError + << " directory " + << io.local() << " in times " + << startIO.instance() << " down to "; + + if (failed == failureCodes::FAILED_STOPINST) + { + FatalError << stopInstance; + } + else + { + FatalError << "constant"; + } + FatalError << exit(FatalError); + } + if (debug) { Pout<< "masterUncollatedFileOperation::findInstance :" diff --git a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H index e9c03114608dc1eb7d2c62e52ba8831d9d0de273..f1385f55b1428039ab5fe044529ec606e6ecfd0c 100644 --- a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H +++ b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H @@ -738,9 +738,10 @@ public: //- Get sorted list of times virtual instantList findTimes(const fileName&, const word&) const; - //- Find instance where IOobject is. Fails if cannot be found - // and readOpt() is MUST_READ/MUST_READ_IF_MODIFIED. Otherwise - // returns stopInstance. + //- Find instance where IOobject is. + // FatalError if it cannot be found and readOpt is + // (MUST_READ or MUST_READ_IF_MODIFIED). + // Otherwise it returns the stopInstance. virtual IOobject findInstance ( const IOobject& io, diff --git a/src/conversion/ccm/writer/ccmWriterMesh.C b/src/conversion/ccm/writer/ccmWriterMesh.C index 79f9df0139608866585609280a4daba78effb87e..f66b822712d7078a05cf4267cb2e033f5e6e4460 100644 --- a/src/conversion/ccm/writer/ccmWriterMesh.C +++ b/src/conversion/ccm/writer/ccmWriterMesh.C @@ -663,7 +663,7 @@ void Foam::ccm::writer::writeInterfaces ( "interfaces", "constant", - "polyMesh", + polyMesh::meshSubDir, mesh_, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, diff --git a/src/dynamicMesh/polyTopoChange/polyTopoChanger/polyTopoChanger.C b/src/dynamicMesh/polyTopoChange/polyTopoChanger/polyTopoChanger.C index a7d7acce1cb1187e11ec518941eefba14d48e500..5434f8041a000ccd2c15557f5ab938eb7bb94ec6 100644 --- a/src/dynamicMesh/polyTopoChange/polyTopoChanger/polyTopoChanger.C +++ b/src/dynamicMesh/polyTopoChange/polyTopoChanger/polyTopoChanger.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2021 OpenCFD Ltd. + Copyright (C) 2017-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -116,9 +116,14 @@ Foam::polyTopoChanger::polyTopoChanger ( mesh.meshDir(), "meshModifiers", - rOpt + ( + // Safety? promote NO_READ to READ_IF_PRESENT + rOpt == IOobject::NO_READ + ? IOobject::READ_IF_PRESENT + : rOpt + ) ), - mesh.meshSubDir, + polyMesh::meshSubDir, mesh, rOpt, IOobject::NO_WRITE