ENH: autoLayerDriver: better layering information message
[OpenFOAM-2.0.x.git] / src / OpenFOAM / meshes / polyMesh / zones / ZoneMesh / ZoneMesh.C
blob2497592ee88ecf3f587330312f30f56ae41b1a04
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by
13     the Free Software Foundation, either version 3 of the License, or
14     (at your option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "ZoneMesh.H"
27 #include "entry.H"
28 #include "demandDrivenData.H"
29 #include "stringListOps.H"
30 #include "Pstream.H"
32 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
34 template<class ZoneType, class MeshType>
35 void Foam::ZoneMesh<ZoneType, MeshType>::calcZoneMap() const
37     // It is an error to attempt to recalculate cellEdges
38     // if the pointer is already set
39     if (zoneMapPtr_)
40     {
41         FatalErrorIn("void ZoneMesh<ZoneType>::calcZoneMap() const")
42             << "zone map already calculated"
43             << abort(FatalError);
44     }
45     else
46     {
47         // Count number of objects in all zones
48         label nObjects = 0;
50         forAll(*this, zoneI)
51         {
52             nObjects += this->operator[](zoneI).size();
53         }
55         zoneMapPtr_ = new Map<label>(2*nObjects);
56         Map<label>& zm = *zoneMapPtr_;
58         // Fill in objects of all zones into the map.  The key is the global
59         // object index and the result is the zone index
60         forAll(*this, zoneI)
61         {
62             const labelList& zoneObjects = this->operator[](zoneI);
64             forAll(zoneObjects, objI)
65             {
66                 zm.insert(zoneObjects[objI], zoneI);
67             }
68         }
69     }
73 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
75 // Read constructor given IOobject and a MeshType reference
76 template<class ZoneType, class MeshType>
77 Foam::ZoneMesh<ZoneType, MeshType>::ZoneMesh
79     const IOobject& io,
80     const MeshType& mesh
83     PtrList<ZoneType>(),
84     regIOobject(io),
85     mesh_(mesh),
86     zoneMapPtr_(NULL)
88     if
89     (
90         readOpt() == IOobject::MUST_READ
91      || readOpt() == IOobject::MUST_READ_IF_MODIFIED
92      || (readOpt() == IOobject::READ_IF_PRESENT && headerOk())
93     )
94     {
95         if (readOpt() == IOobject::MUST_READ_IF_MODIFIED)
96         {
97             WarningIn
98             (
99                 "ZoneMesh::ZoneMesh\n"
100                 "(\n"
101                 "    const IOobject&,\n"
102                 "    const MeshType&\n"
103                 ")"
104             )   << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
105                 << " does not support automatic rereading."
106                 << endl;
107         }
109         PtrList<ZoneType>& zones = *this;
111         // Read zones
112         Istream& is = readStream(typeName);
114         PtrList<entry> patchEntries(is);
115         zones.setSize(patchEntries.size());
117         forAll(zones, zoneI)
118         {
119             zones.set
120             (
121                 zoneI,
122                 ZoneType::New
123                 (
124                     patchEntries[zoneI].keyword(),
125                     patchEntries[zoneI].dict(),
126                     zoneI,
127                     *this
128                 )
129             );
130         }
132         // Check state of IOstream
133         is.check
134         (
135             "ZoneMesh::ZoneMesh"
136             "(const IOobject&, const MeshType&)"
137         );
139         close();
140     }
141     else
142     {
143         // No files found.  Force a write of zero-sized zones
144         // write();
145     }
149 // Construct given size. Zones will be set later
150 template<class ZoneType, class MeshType>
151 Foam::ZoneMesh<ZoneType, MeshType>::ZoneMesh
153     const IOobject& io,
154     const MeshType& mesh,
155     const label size
158     PtrList<ZoneType>(size),
159     regIOobject(io),
160     mesh_(mesh),
161     zoneMapPtr_(NULL)
165 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
167 template<class ZoneType, class MeshType>
168 Foam::ZoneMesh<ZoneType, MeshType>::~ZoneMesh()
170     clearAddressing();
174 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
176 // Map of zones for quick zone lookup
177 template<class ZoneType, class MeshType>
178 const Foam::Map<Foam::label>&
179 Foam::ZoneMesh<ZoneType, MeshType>::zoneMap() const
181     if (!zoneMapPtr_)
182     {
183         calcZoneMap();
184     }
186     return *zoneMapPtr_;
190 // Given a global object index, return the zone it is in.
191 // If object does not belong to any zones, return -1
192 template<class ZoneType, class MeshType>
193 Foam::label Foam::ZoneMesh<ZoneType, MeshType>::whichZone
195     const label objectIndex
196 ) const
198     const Map<label>& zm = zoneMap();
199     Map<label>::const_iterator zmIter = zm.find(objectIndex);
201     if (zmIter == zm.end())
202     {
203         return -1;
204     }
205     else
206     {
207         return zmIter();
208     }
212 // Return a list of zone names
213 template<class ZoneType, class MeshType>
214 Foam::wordList Foam::ZoneMesh<ZoneType, MeshType>::types() const
216     const PtrList<ZoneType>& zones = *this;
218     wordList lst(zones.size());
220     forAll(zones, zoneI)
221     {
222         lst[zoneI] = zones[zoneI].type();
223     }
225     return lst;
229 // Return a list of zone names
230 template<class ZoneType, class MeshType>
231 Foam::wordList Foam::ZoneMesh<ZoneType, MeshType>::names() const
233     const PtrList<ZoneType>& zones = *this;
235     wordList lst(zones.size());
237     forAll(zones, zoneI)
238     {
239         lst[zoneI] = zones[zoneI].name();
240     }
242     return lst;
246 template<class ZoneType, class MeshType>
247 Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::findIndices
249     const keyType& key
250 ) const
252     labelList indices;
254     if (!key.empty())
255     {
256         if (key.isPattern())
257         {
258             indices = findStrings(key, this->names());
259         }
260         else
261         {
262             indices.setSize(this->size());
263             label nFound = 0;
264             forAll(*this, i)
265             {
266                 if (key == operator[](i).name())
267                 {
268                     indices[nFound++] = i;
269                 }
270             }
271             indices.setSize(nFound);
272         }
273     }
275     return indices;
279 template<class ZoneType, class MeshType>
280 Foam::label Foam::ZoneMesh<ZoneType, MeshType>::findIndex
282     const keyType& key
283 ) const
285     if (!key.empty())
286     {
287         if (key.isPattern())
288         {
289             labelList indices = this->findIndices(key);
291             // return first element
292             if (!indices.empty())
293             {
294                 return indices[0];
295             }
296         }
297         else
298         {
299             forAll(*this, i)
300             {
301                 if (key == operator[](i).name())
302                 {
303                     return i;
304                 }
305             }
306         }
307     }
309     // not found
310     return -1;
314 template<class ZoneType, class MeshType>
315 Foam::label Foam::ZoneMesh<ZoneType, MeshType>::findZoneID
317     const word& zoneName
318 ) const
320     const PtrList<ZoneType>& zones = *this;
322     forAll(zones, zoneI)
323     {
324         if (zones[zoneI].name() == zoneName)
325         {
326             return zoneI;
327         }
328     }
330     // Zone not found
331     if (debug)
332     {
333         Info<< "label ZoneMesh<ZoneType>::findZoneID(const word&) const : "
334             << "Zone named " << zoneName << " not found.  "
335             << "List of available zone names: " << names() << endl;
336     }
338     // not found
339     return -1;
343 template<class ZoneType, class MeshType>
344 Foam::PackedBoolList Foam::ZoneMesh<ZoneType, MeshType>::findMatching
346     const keyType& key
347 ) const
349     PackedBoolList lst;
351     const labelList indices = this->findIndices(key);
352     forAll(indices, i)
353     {
354         lst |= static_cast<const labelList&>(this->operator[](indices[i]));
355     }
357     return lst;
361 template<class ZoneType, class MeshType>
362 void Foam::ZoneMesh<ZoneType, MeshType>::clearAddressing()
364     deleteDemandDrivenData(zoneMapPtr_);
366     PtrList<ZoneType>& zones = *this;
368     forAll(zones, zoneI)
369     {
370         zones[zoneI].clearAddressing();
371     }
375 template<class ZoneType, class MeshType>
376 void Foam::ZoneMesh<ZoneType, MeshType>::clear()
378     clearAddressing();
379     PtrList<ZoneType>::clear();
383 // Check zone definition
384 template<class ZoneType, class MeshType>
385 bool Foam::ZoneMesh<ZoneType, MeshType>::checkDefinition
387     const bool report
388 ) const
390     bool inError = false;
392     const PtrList<ZoneType>& zones = *this;
394     forAll(zones, zoneI)
395     {
396         inError |= zones[zoneI].checkDefinition(report);
397     }
398     return inError;
402 template<class ZoneType, class MeshType>
403 bool Foam::ZoneMesh<ZoneType, MeshType>::checkParallelSync
405     const bool report
406 ) const
408     if (!Pstream::parRun())
409     {
410         return false;
411     }
414     const PtrList<ZoneType>& zones = *this;
416     bool hasError = false;
418     // Collect all names
419     List<wordList> allNames(Pstream::nProcs());
420     allNames[Pstream::myProcNo()] = this->names();
421     Pstream::gatherList(allNames);
422     Pstream::scatterList(allNames);
424     List<wordList> allTypes(Pstream::nProcs());
425     allTypes[Pstream::myProcNo()] = this->types();
426     Pstream::gatherList(allTypes);
427     Pstream::scatterList(allTypes);
429     // Have every processor check but only master print error.
431     for (label procI = 1; procI < allNames.size(); procI++)
432     {
433         if
434         (
435             (allNames[procI] != allNames[0])
436          || (allTypes[procI] != allTypes[0])
437         )
438         {
439             hasError = true;
441             if (debug || (report && Pstream::master()))
442             {
443                 Info<< " ***Inconsistent zones across processors, "
444                        "processor 0 has zone names:" << allNames[0]
445                     << " zone types:" << allTypes[0]
446                     << " processor " << procI << " has zone names:"
447                     << allNames[procI]
448                     << " zone types:" << allTypes[procI]
449                     << endl;
450             }
451         }
452     }
454     // Check contents
455     if (!hasError)
456     {
457         forAll(zones, zoneI)
458         {
459             if (zones[zoneI].checkParallelSync(false))
460             {
461                 hasError = true;
463                 if (debug || (report && Pstream::master()))
464                 {
465                     Info<< " ***Zone " << zones[zoneI].name()
466                         << " of type " << zones[zoneI].type()
467                         << " is not correctly synchronised"
468                         << " across coupled boundaries."
469                         << " (coupled faces are either not both "
470                         << " present in set or have same flipmap)" << endl;
471                 }
472             }
473         }
474     }
476     return hasError;
480 // Correct zone mesh after moving points
481 template<class ZoneType, class MeshType>
482 void Foam::ZoneMesh<ZoneType, MeshType>::movePoints(const pointField& p)
484     PtrList<ZoneType>& zones = *this;
486     forAll(zones, zoneI)
487     {
488         zones[zoneI].movePoints(p);
489     }
493 // writeData member function required by regIOobject
494 template<class ZoneType, class MeshType>
495 bool Foam::ZoneMesh<ZoneType, MeshType>::writeData(Ostream& os) const
497     os  << *this;
498     return os.good();
501 // * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * * //
503 template<class ZoneType, class MeshType>
504 const ZoneType& Foam::ZoneMesh<ZoneType, MeshType>::operator[]
506     const word& zoneName
507 ) const
509     const label zoneI = findZoneID(zoneName);
511     if (zoneI < 0)
512     {
513         FatalErrorIn
514         (
515             "ZoneMesh<ZoneType>::operator[](const word&) const"
516         )   << "Zone named " << zoneName << " not found." << nl
517             << "Available zone names: " << names() << endl
518             << abort(FatalError);
519     }
521     return operator[](zoneI);
525 template<class ZoneType, class MeshType>
526 ZoneType& Foam::ZoneMesh<ZoneType, MeshType>::operator[]
528     const word& zoneName
531     const label zoneI = findZoneID(zoneName);
533     if (zoneI < 0)
534     {
535         FatalErrorIn
536         (
537             "ZoneMesh<ZoneType>::operator[](const word&)"
538         )   << "Zone named " << zoneName << " not found." << nl
539             << "Available zone names: " << names() << endl
540             << abort(FatalError);
541     }
543     return operator[](zoneI);
547 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
549 template<class ZoneType, class MeshType>
550 Foam::Ostream& Foam::operator<<
552     Ostream& os,
553     const ZoneMesh<ZoneType, MeshType>& zones
556     os  << zones.size() << nl << token::BEGIN_LIST;
558     forAll(zones, zoneI)
559     {
560         zones[zoneI].writeDict(os);
561     }
563     os  << token::END_LIST;
565     return os;
569 // ************************************************************************* //