ENH: GeometricField: support patch groups

This commit is contained in:
mattijs
2011-12-06 17:10:01 +00:00
parent 142142b172
commit 7ad19bfba7
14 changed files with 455 additions and 155 deletions

View File

@ -87,8 +87,6 @@ void Foam::vtkPV3Foam::reduceMemory()
}
int Foam::vtkPV3Foam::setTime(int nRequest, const double requestTimes[])
{
Time& runTime = dbPtr_();
@ -214,6 +212,7 @@ void Foam::vtkPV3Foam::updateMeshPartsStatus()
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::vtkPV3Foam::vtkPV3Foam
@ -378,7 +377,7 @@ void Foam::vtkPV3Foam::updateInfo()
// Update mesh parts list - add Lagrangian at the bottom
updateInfoInternalMesh(partSelection);
updateInfoPatches(partSelection);
updateInfoPatches(partSelection, enabledEntries);
updateInfoSets(partSelection);
updateInfoZones(partSelection);
updateInfoLagrangian(partSelection);

View File

@ -347,7 +347,7 @@ class vtkPV3Foam
void updateInfoLagrangian(vtkDataArraySelection*);
//- Patch info
void updateInfoPatches(vtkDataArraySelection*);
void updateInfoPatches(vtkDataArraySelection*, stringList&);
//- Set info
void updateInfoSets(vtkDataArraySelection*);
@ -554,18 +554,6 @@ class vtkPV3Foam
const labelList& faceLabels
);
//- face set/zone field
template<class Type>
void convertFaceField
(
const GeometricField<Type, fvPatchField, volMesh>&,
vtkMultiBlockDataSet* output,
const arrayRange&,
const label datasetNo,
const fvMesh&,
const faceSet&
);
//- Lagrangian fields - all types
template<class Type>
void convertLagrangianFields

View File

@ -110,79 +110,6 @@ void Foam::vtkPV3Foam::convertFaceField
}
template<class Type>
void Foam::vtkPV3Foam::convertFaceField
(
const GeometricField<Type, fvPatchField, volMesh>& tf,
vtkMultiBlockDataSet* output,
const arrayRange& range,
const label datasetNo,
const fvMesh& mesh,
const faceSet& fSet
)
{
const label nComp = pTraits<Type>::nComponents;
const label nInternalFaces = mesh.nInternalFaces();
const labelList& faceOwner = mesh.faceOwner();
const labelList& faceNeigh = mesh.faceNeighbour();
vtkFloatArray* cellData = vtkFloatArray::New();
cellData->SetNumberOfTuples(fSet.size());
cellData->SetNumberOfComponents(nComp);
cellData->Allocate(nComp*fSet.size());
cellData->SetName(tf.name().c_str());
if (debug)
{
Info<< "convert convertFaceField: "
<< tf.name()
<< " size = " << tf.size()
<< " nComp=" << nComp
<< " nTuples = " << fSet.size() << endl;
}
float vec[nComp];
// for interior faces: average owner/neighbour
// for boundary faces: owner
label faceI = 0;
forAllConstIter(faceSet, fSet, iter)
{
const label faceNo = iter.key();
if (faceNo < nInternalFaces)
{
Type t = 0.5*(tf[faceOwner[faceNo]] + tf[faceNeigh[faceNo]]);
for (direction d=0; d<nComp; ++d)
{
vec[d] = component(t, d);
}
}
else
{
const Type& t = tf[faceOwner[faceNo]];
for (direction d=0; d<nComp; ++d)
{
vec[d] = component(t, d);
}
}
vtkOpenFOAMTupleRemap<Type>(vec);
cellData->InsertTuple(faceI, vec);
++faceI;
}
vtkPolyData::SafeDownCast
(
GetDataSetFromBlock(output, range, datasetNo)
) ->GetCellData()
->AddArray(cellData);
cellData->Delete();
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif

View File

@ -221,7 +221,8 @@ void Foam::vtkPV3Foam::updateInfoLagrangian
void Foam::vtkPV3Foam::updateInfoPatches
(
vtkDataArraySelection* arraySelection
vtkDataArraySelection* arraySelection,
stringList& enabledEntries
)
{
if (debug)
@ -230,12 +231,63 @@ void Foam::vtkPV3Foam::updateInfoPatches
<< " [meshPtr=" << (meshPtr_ ? "set" : "NULL") << "]" << endl;
}
HashSet<string> enabledEntriesSet(enabledEntries);
arrayRangePatches_.reset(arraySelection->GetNumberOfArrays());
int nPatches = 0;
if (meshPtr_)
{
const polyBoundaryMesh& patches = meshPtr_->boundaryMesh();
const HashTable<labelList, word>& groups = patches.groupPatchIDs();
const wordList allPatchNames = patches.names();
// Add patch groups
// ~~~~~~~~~~~~~~~~
for
(
HashTable<labelList, word>::const_iterator iter = groups.begin();
iter != groups.end();
++iter
)
{
const word& groupName = iter.key();
const labelList& patchIDs = iter();
label nFaces = 0;
forAll(patchIDs, i)
{
nFaces += patches[patchIDs[i]].size();
}
// Valid patch if nFace > 0 - add patch to GUI list
if (nFaces)
{
string vtkGrpName = groupName + " - group";
arraySelection->AddArray(vtkGrpName.c_str());
++nPatches;
if (enabledEntriesSet.found(vtkGrpName))
{
forAll(patchIDs, i)
{
const polyPatch& pp = patches[patchIDs[i]];
string vtkPatchName = pp.name() + " - patch";
enabledEntriesSet.insert(vtkPatchName);
}
enabledEntriesSet.erase(vtkGrpName);
}
}
}
// Add patches
// ~~~~~~~~~~~
forAll(patches, patchI)
{
const polyPatch& pp = patches[patchI];
@ -277,20 +329,101 @@ void Foam::vtkPV3Foam::updateInfoPatches
{
polyBoundaryMeshEntries patchEntries(ioObj);
// Add (non-zero) patches to the list of mesh parts
forAll(patchEntries, entryI)
// Read patches and determine sizes
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wordList names(patchEntries.size());
labelList sizes(patchEntries.size());
forAll(patchEntries, patchI)
{
label nFaces
(
readLabel(patchEntries[entryI].dict().lookup("nFaces"))
);
const dictionary& patchDict = patchEntries[patchI].dict();
sizes[patchI] = readLabel(patchDict.lookup("nFaces"));
names[patchI] = patchEntries[patchI].keyword();
}
// Add (non-zero) patch groups to the list of mesh parts
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HashTable<labelList, word> groups(patchEntries.size());
forAll(patchEntries, patchI)
{
const dictionary& patchDict = patchEntries[patchI].dict();
wordList groupNames;
patchDict.readIfPresent("inGroups", groupNames);
forAll(groupNames, groupI)
{
HashTable<labelList, word>::iterator iter = groups.find
(
groupNames[groupI]
);
if (iter != groups.end())
{
iter().append(patchI);
}
else
{
groups.insert(groupNames[groupI], labelList(1, patchI));
}
}
}
for
(
HashTable<labelList, word>::const_iterator iter =
groups.begin();
iter != groups.end();
++iter
)
{
const word& groupName = iter.key();
const labelList& patchIDs = iter();
label nFaces = 0;
forAll(patchIDs, i)
{
nFaces += sizes[patchIDs[i]];
}
// Valid patch if nFace > 0 - add patch to GUI list
if (nFaces)
{
string vtkGrpName = groupName + " - group";
arraySelection->AddArray(vtkGrpName.c_str());
++nPatches;
if (enabledEntriesSet.found(vtkGrpName))
{
forAll(patchIDs, i)
{
string vtkPatchName =
names[patchIDs[i]] + " - patch";
enabledEntriesSet.insert(vtkPatchName);
}
enabledEntriesSet.erase(vtkGrpName);
}
}
}
// Add (non-zero) patches to the list of mesh parts
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
forAll(names, patchI)
{
// Valid patch if nFace > 0 - add patch to GUI list
if (sizes[patchI])
{
arraySelection->AddArray
(
(patchEntries[entryI].keyword() + " - patch").c_str()
(names[patchI] + " - patch").c_str()
);
++nPatches;
@ -300,6 +433,9 @@ void Foam::vtkPV3Foam::updateInfoPatches
}
arrayRangePatches_ += nPatches;
// Update enabled entries in case of group selection
enabledEntries = enabledEntriesSet.toc();
if (debug)
{
// just for debug info

View File

@ -271,7 +271,7 @@ void Foam::vtkPV3Foam::convertVolFields
arrayRangeFaceSets_,
datasetNo,
mesh,
fSet
fSet.toc()
);
// TODO: points

View File

@ -248,15 +248,81 @@ GeometricBoundaryField
<< endl;
}
// Check for groups first. (using non-wild card entries of dictionaries)
forAllConstIter(dictionary, dict, iter)
{
if (iter().isDict())
{
const labelList patchIDs = bmesh_.findIndices
(
iter().keyword(),
true
);
forAll(patchIDs, i)
{
label patchi = patchIDs[i];
this->set
(
patchi,
PatchField<Type>::New
(
bmesh_[patchi],
field,
iter().dict()
)
);
}
}
}
// Check for explicit patch overrides
forAll(bmesh_, patchi)
{
if (bmesh_[patchi].type() != emptyPolyPatch::typeName)
if (bmesh_[patchi].type() == emptyPolyPatch::typeName)
{
if
(
bmesh_[patchi].type() == cyclicPolyPatch::typeName
&& !dict.found(bmesh_[patchi].name())
)
if (!this->set(patchi))
{
this->set
(
patchi,
PatchField<Type>::New
(
emptyPolyPatch::typeName,
bmesh_[patchi],
field
)
);
}
}
else
{
bool found = dict.found(bmesh_[patchi].name());
if (found)
{
this->set
(
patchi,
PatchField<Type>::New
(
bmesh_[patchi],
field,
dict.subDict(bmesh_[patchi].name())
)
);
}
}
}
// Check for any unset patches
forAll(bmesh_, patchi)
{
if (!this->set(patchi))
{
if (bmesh_[patchi].type() == cyclicPolyPatch::typeName)
{
FatalIOErrorIn
(
@ -274,30 +340,21 @@ GeometricBoundaryField
<< "Run foamUpgradeCyclics to convert mesh and fields"
<< " to split cyclics." << exit(FatalIOError);
}
this->set
(
patchi,
PatchField<Type>::New
else
{
FatalIOErrorIn
(
bmesh_[patchi],
field,
dict.subDict(bmesh_[patchi].name())
)
);
}
else
{
this->set
(
patchi,
PatchField<Type>::New
(
emptyPolyPatch::typeName,
bmesh_[patchi],
field
)
);
"GeometricField<Type, PatchField, GeoMesh>::\n"
"GeometricBoundaryField::GeometricBoundaryField\n"
"(\n"
" const BoundaryMesh&,\n"
" const DimensionedField<Type, GeoMesh>&,\n"
" const dictionary&\n"
")",
dict
) << "Cannot find patchField entry for "
<< bmesh_[patchi].name() << exit(FatalIOError);
}
}
}
}

View File

@ -32,12 +32,14 @@ Foam::patchIdentifier::patchIdentifier
(
const word& name,
const label index,
const word& physicalType
const word& physicalType,
const wordList& inGroups
)
:
name_(name),
index_(index),
physicalType_(physicalType)
physicalType_(physicalType),
inGroups_(inGroups)
{}
@ -52,6 +54,7 @@ Foam::patchIdentifier::patchIdentifier
index_(index)
{
dict.readIfPresent("physicalType", physicalType_);
dict.readIfPresent("inGroups", inGroups_);
}
@ -63,7 +66,8 @@ Foam::patchIdentifier::patchIdentifier
:
name_(p.name_),
index_(index),
physicalType_(p.physicalType_)
physicalType_(p.physicalType_),
inGroups_(p.inGroups_)
{}
@ -82,6 +86,11 @@ void Foam::patchIdentifier::write(Ostream& os) const
os.writeKeyword("physicalType") << physicalType_
<< token::END_STATEMENT << nl;
}
if (inGroups_.size())
{
os.writeKeyword("inGroups") << inGroups_
<< token::END_STATEMENT << nl;
}
}

View File

@ -35,7 +35,7 @@ SourceFiles
#ifndef patchIdentifier_H
#define patchIdentifier_H
#include "word.H"
#include "wordList.H"
#include "label.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -68,6 +68,8 @@ class patchIdentifier
//- Optional physical type
mutable word physicalType_;
//- Optional groups patch belongs to
wordList inGroups_;
public:
@ -78,7 +80,8 @@ public:
(
const word& name,
const label index,
const word& physicalType = word::null
const word& physicalType = word::null,
const wordList& inGroups = wordList()
);
//- Construct from dictionary
@ -139,6 +142,19 @@ public:
return index_;
}
//- Return the optional groups patch belongs to
const wordList& inGroups() const
{
return inGroups_;
}
//- Return the optional groups patch belongs to for modification
wordList& inGroups()
{
return inGroups_;
}
//- Write patchIdentifier as a dictionary
void write(Ostream&) const;

View File

@ -58,6 +58,16 @@ Foam::pointBoundaryMesh::pointBoundaryMesh
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::labelList Foam::pointBoundaryMesh::findIndices
(
const keyType& key,
const bool usePatchGroups
) const
{
return mesh()().boundaryMesh().findIndices(key, usePatchGroups);
}
void Foam::pointBoundaryMesh::calcGeometry()
{
PstreamBuffers pBufs(Pstream::defaultCommsType);

View File

@ -96,6 +96,9 @@ public:
return mesh_;
}
//- Find patch indices given a name
labelList findIndices(const keyType&, const bool useGroups) const;
//- Correct polyBoundaryMesh after moving points
void movePoints(const pointField&);

View File

@ -151,6 +151,7 @@ void Foam::polyBoundaryMesh::clearAddressing()
{
neighbourEdgesPtr_.clear();
patchIDPtr_.clear();
groupPatchIDsPtr_.clear();
forAll(*this, patchI)
{
@ -369,6 +370,54 @@ const Foam::labelList& Foam::polyBoundaryMesh::patchID() const
}
const Foam::HashTable<Foam::labelList, Foam::word>&
Foam::polyBoundaryMesh::groupPatchIDs() const
{
if (!groupPatchIDsPtr_.valid())
{
groupPatchIDsPtr_.reset(new HashTable<labelList, word>(10));
HashTable<labelList, word>& groupPatchIDs = groupPatchIDsPtr_();
const polyBoundaryMesh& bm = *this;
forAll(bm, patchI)
{
const wordList& groups = bm[patchI].inGroups();
forAll(groups, i)
{
const word& name = groups[i];
if (findPatchID(name) != -1)
{
WarningIn("polyBoundaryMesh::groupPatchIDs() const")
<< "Patch " << bm[patchI].name()
<< " specifies a group " << name
<< " which is also a patch name."
<< " This might give problems later on." << endl;
}
HashTable<labelList, word>::iterator iter = groupPatchIDs.find
(
name
);
if (iter != groupPatchIDs.end())
{
iter().append(patchI);
}
else
{
groupPatchIDs.insert(name, labelList(1, patchI));
}
}
}
}
return groupPatchIDsPtr_();
}
Foam::wordList Foam::polyBoundaryMesh::names() const
{
const polyPatchList& patches = *this;
@ -414,28 +463,74 @@ Foam::wordList Foam::polyBoundaryMesh::physicalTypes() const
}
Foam::labelList Foam::polyBoundaryMesh::findIndices(const keyType& key) const
Foam::labelList Foam::polyBoundaryMesh::findIndices
(
const keyType& key,
const bool usePatchGroups
) const
{
labelList indices;
DynamicList<label> indices;
if (!key.empty())
{
if (key.isPattern())
{
indices = findStrings(key, this->names());
if (usePatchGroups && groupPatchIDs().size())
{
labelHashSet indexSet(indices);
const wordList allGroupNames = groupPatchIDs().toc();
labelList groupIDs = findStrings(key, allGroupNames);
forAll(groupIDs, i)
{
const word& grpName = allGroupNames[groupIDs[i]];
const labelList& patchIDs = groupPatchIDs()[grpName];
forAll(patchIDs, j)
{
if (indexSet.insert(patchIDs[j]))
{
indices.append(patchIDs[j]);
}
}
}
}
}
else
{
indices.setSize(this->size());
label nFound = 0;
// Literal string. Special version of above to avoid
// unnecessary memory allocations
indices.setCapacity(1);
forAll(*this, i)
{
if (key == operator[](i).name())
{
indices[nFound++] = i;
indices.append(i);
break;
}
}
if (usePatchGroups && groupPatchIDs().size())
{
const HashTable<labelList, word>::const_iterator iter =
groupPatchIDs().find(key);
if (iter != groupPatchIDs().end())
{
labelHashSet indexSet(indices);
const labelList& patchIDs = iter();
forAll(patchIDs, j)
{
if (indexSet.insert(patchIDs[j]))
{
indices.append(patchIDs[j]);
}
}
}
}
indices.setSize(nFound);
}
}
@ -552,7 +647,8 @@ Foam::label Foam::polyBoundaryMesh::whichPatch(const label faceIndex) const
Foam::labelHashSet Foam::polyBoundaryMesh::patchSet
(
const UList<wordRe>& patchNames,
const bool warnNotFound
const bool warnNotFound,
const bool usePatchGroups
) const
{
const wordList allPatchNames(this->names());
@ -560,24 +656,58 @@ Foam::labelHashSet Foam::polyBoundaryMesh::patchSet
forAll(patchNames, i)
{
const word& patchName = patchNames[i];
// Treat the given patch names as wild-cards and search the set
// of all patch names for matches
labelList patchIDs = findStrings(patchNames[i], allPatchNames);
if (patchIDs.empty() && warnNotFound)
{
WarningIn
(
"polyBoundaryMesh::patchSet"
"(const wordReList&, const bool) const"
) << "Cannot find any patch names matching " << patchNames[i]
<< endl;
}
labelList patchIDs = findStrings(patchName, allPatchNames);
forAll(patchIDs, j)
{
ids.insert(patchIDs[j]);
}
if (patchIDs.empty())
{
if (usePatchGroups)
{
const wordList allGroupNames = groupPatchIDs().toc();
// Regard as group name
labelList groupIDs = findStrings(patchName, allGroupNames);
forAll(groupIDs, i)
{
const word& name = allGroupNames[groupIDs[i]];
const labelList& extraPatchIDs = groupPatchIDs()[name];
forAll(extraPatchIDs, extraI)
{
ids.insert(extraPatchIDs[extraI]);
}
}
if (groupIDs.empty() && warnNotFound)
{
WarningIn
(
"polyBoundaryMesh::patchSet"
"(const wordReList&, const bool, const bool) const"
) << "Cannot find any patch or group names matching "
<< patchName
<< endl;
}
}
else if (warnNotFound)
{
WarningIn
(
"polyBoundaryMesh::patchSet"
"(const wordReList&, const bool, const bool) const"
) << "Cannot find any patch names matching " << patchName
<< endl;
}
}
}
return ids;
@ -778,6 +908,7 @@ void Foam::polyBoundaryMesh::updateMesh()
{
neighbourEdgesPtr_.clear();
patchIDPtr_.clear();
groupPatchIDsPtr_.clear();
PstreamBuffers pBufs(Pstream::defaultCommsType);

View File

@ -70,6 +70,8 @@ class polyBoundaryMesh
mutable autoPtr<labelList> patchIDPtr_;
mutable autoPtr<HashTable<labelList, word> > groupPatchIDsPtr_;
//- Edges of neighbouring patches
mutable autoPtr<List<labelPairList> > neighbourEdgesPtr_;
@ -153,8 +155,12 @@ public:
//- Return a list of physical types
wordList physicalTypes() const;
//- Return patch indices for all matches
labelList findIndices(const keyType&) const;
//- Return patch indices for all matches. Optionally matches patchGroups
labelList findIndices
(
const keyType&,
const bool usePatchGroups = false
) const;
//- Return patch index for the first match, return -1 if not found
label findIndex(const keyType&) const;
@ -168,12 +174,17 @@ public:
//- Per boundary face label the patch index
const labelList& patchID() const;
//- Per patch group the patch indices
const HashTable<labelList, word>& groupPatchIDs() const;
//- Return the set of patch IDs corresponding to the given names
// By default warns if given names are not found.
// By default warns if given names are not found. Optionally
// matches to patchGroups as well as patchNames
labelHashSet patchSet
(
const UList<wordRe>& patchNames,
const bool warnNotFound = true
const bool warnNotFound = true,
const bool usePatchGroups = false
) const;
//- Check whether all procs have all patches and in same order. Return

View File

@ -23,8 +23,8 @@ License
\*---------------------------------------------------------------------------*/
#include "fvMesh.H"
#include "fvBoundaryMesh.H"
#include "fvMesh.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -87,6 +87,16 @@ Foam::label Foam::fvBoundaryMesh::findPatchID(const word& patchName) const
}
Foam::labelList Foam::fvBoundaryMesh::findIndices
(
const keyType& key,
const bool usePatchGroups
) const
{
return mesh().boundaryMesh().findIndices(key, usePatchGroups);
}
void Foam::fvBoundaryMesh::movePoints()
{
forAll(*this, patchI)

View File

@ -109,6 +109,9 @@ public:
//- Find patch index given a name
label findPatchID(const word& patchName) const;
//- Find patch indices given a name
labelList findIndices(const keyType&, const bool useGroups) const;
//- Correct patches after moving points
void movePoints();