Commit 94b9f525 authored by Mark Olesen's avatar Mark Olesen

WIP: not really working with suppressed field

- restart with collated is the problem.
  Everything simply blocks!!!
parent 04fc041c
......@@ -419,6 +419,18 @@ public:
const bool verbose = true
);
//- Read header (uses localFilePath to find file) and check its info.
// Optionally checks headerClassName against the type-name.
// When search is false, simply use the current instance,
// otherwise search previous instances.
template<class Type>
bool localTypeHeaderOk
(
const bool checkType = true,
const bool search = true,
const bool verbose = true
);
//- Helper: warn that type does not support re-reading
template<class Type>
void warnNoRereading() const;
......
......@@ -31,6 +31,37 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
bool Foam::IOobject::localTypeHeaderOk
(
const bool checkType,
const bool search,
const bool verbose
)
{
const fileOperation& fp = Foam::fileHandler();
// Determine local status only
fileName fName(this->localFilePath(Type::typeName, search));
bool ok = fp.readHeader(*this, fName, Type::typeName);
if (ok && checkType && headerClassName_ != Type::typeName)
{
if (verbose)
{
WarningInFunction
<< "unexpected class name " << headerClassName_
<< " expected " << Type::typeName
<< " when reading " << fName << endl;
}
ok = false;
}
return ok;
}
template<class Type>
bool Foam::IOobject::typeHeaderOk
(
......
......@@ -41,12 +41,55 @@ Foam::localIOdictionary::localIOdictionary(const IOobject& io)
Foam::localIOdictionary::localIOdictionary
(
const IOobject& io,
const word& wantedType
const word& wantedType,
const bool valid
)
:
baseIOdictionary(io)
{
// const bool valid = true;
Pout<<"<" << wantedType <<"> localIOdictionary "
<< io.objectPath() << " valid=" << valid
<<" readOpt: " << io.readOpt()
<< endl;
#if 0
readHeaderOk(IOstream::ASCII, wantedType);
#else
const bool isHeaderOk =
(
io.readOpt() == IOobject::READ_IF_PRESENT
|| io.readOpt() == IOobject::MUST_READ
|| io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
) && headerOk();
Pout<<"header: " << isHeaderOk << endl;
if
(
(isHeaderOk && io.readOpt() == IOobject::READ_IF_PRESENT)
||
(
(valid || isHeaderOk)
&&
(
io.readOpt() == IOobject::MUST_READ
|| io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
)
)
)
{
Pout<< "call readStream(" << wantedType << ", " << (valid || isHeaderOk) << ")" << endl;
Istream& is = readStream(wantedType, valid || isHeaderOk);
is >> *this;
close();
}
#endif
Pout<<"dict: " << flatOutput(this->sortedToc()) << endl;
// For if MUST_READ_IF_MODIFIED
addWatch();
......
......@@ -65,8 +65,14 @@ public:
//- Construct given an IOobject and Istream
localIOdictionary(const IOobject& io, Istream& is);
//- Construct given an IOobject, supply wanted typeName
localIOdictionary(const IOobject& io, const word& wantedType);
//- Construct given an IOobject, supply wanted typeName,
// does local processor require reading?
localIOdictionary
(
const IOobject& io,
const word& wantedType,
const bool valid = true
);
//- Destructor
......
......@@ -112,6 +112,15 @@ Foam::Istream& Foam::regIOobject::readStream(const bool valid)
{
// File is being watched. Read exact file that is being watched.
objPath = fileHandler().getFile(watchIndices_.last());
if (IFstream::debug)
{
Pout<< "regIOobject::readStream() : "
<< "watched object " << name()
<< " (global " << global() << ")"
<< " in file " << objPath
<< endl;
}
}
else
{
......@@ -147,6 +156,7 @@ Foam::Istream& Foam::regIOobject::readStream
<< "reading object " << name()
<< " of type " << type()
<< " from file " << filePath()
<< " existing IFstream:" << (isPtr_.valid())
<< endl;
}
......
......@@ -74,126 +74,167 @@ void Foam::GeometricField<Type, PatchField, GeoMesh>::readFields()
{
// Normally MUST_READ, but allow special handling for empty meshes
if (Pstream::parRun())
{
labelList shouldRead(Pstream::nProcs());
shouldRead[Pstream::myProcNo()] = GeoMesh::size(this->mesh()) ? 1 : 0;
IOobject io
(
this->name(),
this->instance(),
this->local(),
this->db(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
);
// Distribute to all processors
Pstream::gatherList(shouldRead);
Pstream::scatterList(shouldRead);
Pout<<"call localIOdictionary with " << io.objectPath()
<< " and option:" << io.readOpt() << endl;
Pout<<"typename: " << typeName << endl;
// If some processors are missing meshes, use the first processor that
// has a mesh (and thus a field) to redistribute.
// Use local sum, since the values are already gathered
const label firstMesh =
if (!Pstream::parRun())
{
const localIOdictionary dict
(
sum(shouldRead) < Pstream::nProcs()
? shouldRead.find(1)
: -1
io, // MUST_READ
typeName,
true // <- enforce MUST_READ
);
Info<<"firstMesh: " << firstMesh
<< " and " << flatOutput(shouldRead) << endl;
Info<<"Read in dict = " << flatOutput(dict.sortedToc()) << endl;
autoPtr<localIOdictionary> dictPtr;
this->close();
// Mesh actually exists on this processor,
// or force read anyhow and let it crash.
if (shouldRead[Pstream::myProcNo()] || firstMesh == -1)
{
dictPtr.set
(
new localIOdictionary
(
IOobject
(
this->name(),
this->instance(),
this->local(),
this->db(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
),
typeName
)
);
this->close();
readFields(dictPtr());
}
readFields(dict);
if (firstMesh == Pstream::myProcNo())
{
// Send out to others
const dictionary& boundaryDict =
dictPtr().subDict("boundaryField");
return;
}
for (label proci = 0; proci < Pstream::nProcs(); ++proci)
{
if (!shouldRead[proci])
{
OPstream send
(
UPstream::commsTypes::scheduled,
proci,
IOstream::ASCII
);
send<< Internal::dimensions().values()
<< label(Internal::oriented().oriented())
<< boundaryDict;
}
}
}
else if (firstMesh != -1 && !shouldRead[Pstream::myProcNo()])
{
// Receive from first-mesh
Internal::clear();
#if 1
// In parallel, some files may not be present on all processors
label orient;
dictionary boundaryDict;
Pout<<"call check " << io.objectPath() << endl;
IPstream recv
(
Pstream::commsTypes::scheduled,
firstMesh,
IOstream::ASCII
);
const word theTypeName =
GeometricField<Type, PatchField, GeoMesh>::typeName;
recv>> Internal::dimensions().values()
>> orient
>> boundaryDict;
const fileOperation& fp = Foam::fileHandler();
Internal::oriented() = orientedType::orientedOption(orient);
const bool search = false;
const bool checkType = true;
boundaryField_.readField(*this, boundaryDict);
}
// Determine local status only
fileName fName(io.localFilePath(theTypeName, search));
Pout<<"checking " << fName << endl;
// const fileOperation& fp = Foam::fileHandler();
// bool ok = fp.readHeader(*this, fName, theTypeName);
boolList result(Pstream::nProcs(), false);
bool ok = fName.size() && fp.readHeader(io, fName, theTypeName, result);
if (ok && checkType && io.headerClassName() != theTypeName)
{
ok = false;
}
Pout<<"checked " << io.name() << " " << ok << " : " << fName << endl;
labelList shouldRead(Pstream::nProcs(), 0);
if (GeoMesh::size(this->mesh()))
{
shouldRead[Pstream::myProcNo()] = 1;
}
else
{
const localIOdictionary dict
shouldRead[Pstream::myProcNo()] = (ok ? 1 : 0);
}
// Distribute to all processors
Pstream::gatherList(shouldRead);
Pstream::scatterList(shouldRead);
Pout<<"done check " << io.objectPath() << " " << shouldRead << endl;
Pout<<"scattered " << flatOutput(shouldRead) << endl;
// If some processors are missing meshes, use the first available
// mesh/field to redistribute.
const label firstMesh =
(
// Local sum, since the values are already gathered
sum(shouldRead) < Pstream::nProcs()
? shouldRead.find(1)
: -1
);
Pout<<"firstMesh: " << firstMesh
<< " and " << flatOutput(shouldRead)
<< " reading " << this->name() << " / "
<< this->instance() << " / " << this->local() << endl;
const localIOdictionary dict
(
io, // MUST_READ
typeName,
(firstMesh == -1)
);
this->close();
Pout<<"Got dict " << io.name() << " = " << flatOutput(dict.sortedToc()) << endl;
if (!dict.empty())
{
readFields(dict);
}
if (firstMesh == Pstream::myProcNo())
{
// Send out to others
const dictionary& boundaryDict = dict.subDict("boundaryField");
for (label proci = 0; proci < Pstream::nProcs(); ++proci)
{
if (!shouldRead[proci])
{
OPstream send
(
UPstream::commsTypes::scheduled,
proci,
IOstream::ASCII
);
send<< Internal::dimensions().values()
<< label(Internal::oriented().oriented())
<< boundaryDict;
}
}
}
else if (firstMesh != -1 && !shouldRead[Pstream::myProcNo()])
{
// Receive from first-mesh
Internal::clear();
label orient;
dictionary boundaryDict;
IPstream recv
(
IOobject
(
this->name(),
this->instance(),
this->local(),
this->db(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
),
typeName
Pstream::commsTypes::scheduled,
firstMesh,
IOstream::ASCII
);
this->close();
recv>> Internal::dimensions().values()
>> orient
>> boundaryDict;
readFields(dict);
Internal::oriented() = orientedType::orientedOption(orient);
// Since the patches are zero-sized, the constructor will
// ignore any 'values' entry
boundaryField_.readField(*this, boundaryDict);
}
Pout<<"done read of " << io.name() << endl;
#endif
}
......@@ -220,6 +261,8 @@ bool Foam::GeometricField<Type, PatchField, GeoMesh>::readIfPresent()
)
)
{
Pout<< "called: readIfPresent for " << this->name() << endl;
readFields();
// Check compatibility between field and mesh
......@@ -255,6 +298,8 @@ bool Foam::GeometricField<Type, PatchField, GeoMesh>::readOldTimeIfPresent()
this->registerObject()
);
Pout<<"readOldTimeIfPresent: " << this->name() + "_0" << endl;
if
(
field0.template typeHeaderOk<GeometricField<Type, PatchField, GeoMesh>>
......
......@@ -44,6 +44,7 @@ Description
#include "fileNameList.H"
#include "instantList.H"
#include "fileMonitor.H"
#include "boolList.H"
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......@@ -96,13 +97,13 @@ public:
//- Enumeration for the location of an IOobject
enum pathType
{
NOTFOUND, // not found
ABSOLUTE, // instance is absolute directory
OBJECT, // objectPath exists
PROCESSORSOBJECT, // objectPath exists in processors/
PARENTOBJECT, // parent of object path
FINDINSTANCE, // file found in time directory
PROCESSORSFINDINSTANCE // as above but in processors/
NOTFOUND, //!< not found
ABSOLUTE, //!< instance is absolute directory
OBJECT, //!< objectPath exists
PROCESSORSOBJECT, //!< objectPath exists in processors/
PARENTOBJECT, //!< parent of object path
FINDINSTANCE, //!< file found in time directory
PROCESSORSFINDINSTANCE //!< as above but in processors/
};
......@@ -322,6 +323,16 @@ public:
const word& typeName
) const = 0;
//- Read object header from supplied file and store the per-process
// result.
virtual bool readHeader
(
IOobject&,
const fileName&,
const word& typeName,
boolList& result
) const = 0;
//- Reads header for regIOobject and returns an ISstream
// to read the contents.
virtual autoPtr<ISstream> readStream
......
......@@ -102,6 +102,14 @@ Foam::fileName Foam::fileOperations::masterUncollatedFileOperation::filePathInfo
{
newInstancePath = word::null;
if (true)
{
Pout<< "masterUncollatedFileOperation::filePathInfo :"
<< " lookup" << io.objectPath()
<< " procase" << io.time().processorCase() << endl;
}
// Special treatment for absolute paths
if (io.instance().isAbsolute())
{
fileName objectPath = io.instance()/io.name();
......@@ -166,14 +174,8 @@ Foam::fileName Foam::fileOperations::masterUncollatedFileOperation::filePathInfo
// Check for approximately same time. E.g. if time = 1e-2 and
// directory is 0.01 (due to different time formats)
HashPtrTable<instantList>::const_iterator pathFnd
(
times_.find
(
io.time().path()
)
);
if (search && (pathFnd != times_.end()))
const auto pathFnd = times_.cfind(io.time().path());
if (search && pathFnd.found())
{
newInstancePath = findInstancePath
(
......@@ -247,10 +249,8 @@ Foam::fileOperations::masterUncollatedFileOperation::processorsPath
)
{
// Check if directory is processorXXX
word caseName(dir.name());
std::string::size_type pos = caseName.find("processor");
if (pos == 0)
if (dir.name().startsWith("processor"))
{
return dir.path()/processorsDir;
}
......@@ -271,7 +271,7 @@ Foam::fileOperations::masterUncollatedFileOperation::splitProcessorPath
{
// Search for processor at start of line or /processor
std::string::size_type pos = objectPath.find("processor");
if (pos == string::npos)
if (pos == std::string::npos)
{
return -1;
}
......@@ -294,7 +294,7 @@ Foam::fileOperations::masterUncollatedFileOperation::splitProcessorPath
label proci;
pos = local.find('/');
if (pos == string::npos)
if (pos == std::string::npos)
{
// processorXXX without local
if (Foam::read(local, proci))
......@@ -702,8 +702,19 @@ Foam::fileName Foam::fileOperations::masterUncollatedFileOperation::filePath
pathType searchType = NOTFOUND;
word newInstancePath;
if (debug > 1)
{
Pout<< "masterUncollatedFileOperation::filePath :"
<< " [filePathInfo]"
<< " objectPath:" << io.objectPath() << endl;
}
if (Pstream::master())
{
Pout<< "masterUncollatedFileOperation::filePath :"
<< " call filePathInfo"
<< " objectPath:" << io.objectPath() << endl;
objPath =
filePathInfo
(
......@@ -714,6 +725,9 @@ Foam::fileName Foam::fileOperations::masterUncollatedFileOperation::filePath
searchType,
newInstancePath
);
Pout<< "masterUncollatedFileOperation::filePath :"
<< " [master] " << objPath << endl;
}
{
......@@ -724,6 +738,11 @@ Foam::fileName Foam::fileOperations::masterUncollatedFileOperation::filePath
Pstream::scatter(newInstancePath);
if (debug > 1)
{
Pout<< "masterUncollatedFileOperation::filePath :" << label(searchType)
<< " [scattered] " << newInstancePath << endl;
}
// Use the master type to determine if additional information is
// needed to construct the local equivalent
......@@ -930,6 +949,19 @@ bool Foam::fileOperations::masterUncollatedFileOperation::readHeader
const fileName& fName,
const word& typeName
) const
{
boolList result;