1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
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
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 "mapPolyMesh.H"
27 #include "PstreamCombineReduceOps.H"
29 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 //- combineReduce operator for lists. Used for counting.
38 void operator()(T& x, const T& y) const
51 template <class Container, class T>
52 void Foam::fvMeshDistribute::exchange
54 const List<Container >& sendBufs,
55 List<Container >& recvBufs,
59 if (Pstream::parRun())
65 "Pstream::exchange(..)"
66 ) << "Continuous data only." << Foam::abort(FatalError);
69 if (sendBufs.size() != Pstream::nProcs())
73 "Pstream::exchange(..)"
74 ) << "Size of list:" << sendBufs.size()
75 << " does not equal the number of processors:"
77 << Foam::abort(FatalError);
80 sizes.setSize(Pstream::nProcs());
81 labelList& nsTransPs = sizes[Pstream::myProcNo()];
82 nsTransPs.setSize(Pstream::nProcs());
84 forAll(sendBufs, procI)
86 nsTransPs[procI] = sendBufs[procI].size();
89 Foam::combineReduce(sizes, listEq());
95 recvBufs.setSize(sendBufs.size());
98 label nRecv = sizes[procI][Pstream::myProcNo()];
100 if (procI != Pstream::myProcNo() && nRecv > 0)
102 recvBufs[procI].setSize(nRecv);
105 Pstream::nonBlocking,
107 reinterpret_cast<char*>(recvBufs[procI].begin()),
117 forAll(sendBufs, procI)
119 if (procI != Pstream::myProcNo() && sendBufs[procI].size() > 0)
125 Pstream::nonBlocking,
127 reinterpret_cast<const char*>(sendBufs[procI].begin()),
128 sendBufs[procI].size()*sizeof(T)
132 FatalErrorIn("Pstream::exchange(..)")
133 << "Cannot send outgoing message. "
134 << "to:" << procI << " nBytes:"
135 << label(sendBufs[procI].size()*sizeof(T))
136 << Foam::abort(FatalError);
142 // Wait for all to finish
143 // ~~~~~~~~~~~~~~~~~~~~~~
145 IPstream::waitRequests();
146 OPstream::waitRequests();
150 recvBufs[Pstream::myProcNo()] = sendBufs[Pstream::myProcNo()];
154 template<class GeoField>
155 void Foam::fvMeshDistribute::printFieldInfo(const fvMesh& mesh)
157 HashTable<const GeoField*> flds
159 mesh.objectRegistry::lookupClass<GeoField>()
164 typename HashTable<const GeoField*>::const_iterator iter = flds.begin();
169 const GeoField& fld = *iter();
171 Pout<< "Field:" << iter.key() << " internalsize:" << fld.size()
172 //<< " value:" << fld
175 forAll(fld.boundaryField(), patchI)
178 << ' ' << fld.boundaryField()[patchI].patch().name()
179 << ' ' << fld.boundaryField()[patchI].type()
180 << ' ' << fld.boundaryField()[patchI].size()
187 template<class GeoField>
188 void Foam::fvMeshDistribute::addPatchFields(const word& patchFieldType)
190 HashTable<const GeoField*> flds
192 mesh_.objectRegistry::lookupClass<GeoField>()
197 typename HashTable<const GeoField*>::const_iterator iter = flds.begin();
202 const GeoField& fld = *iter();
204 typename GeoField::GeometricBoundaryField& bfld =
205 const_cast<typename GeoField::GeometricBoundaryField&>
210 label sz = bfld.size();
211 bfld.setSize(sz + 1);
215 GeoField::PatchFieldType::New
218 mesh_.boundary()[sz],
219 fld.dimensionedInternalField()
226 // Delete trailing patch fields
227 template<class GeoField>
228 void Foam::fvMeshDistribute::deleteTrailingPatchFields()
230 HashTable<const GeoField*> flds
232 mesh_.objectRegistry::lookupClass<GeoField>()
237 typename HashTable<const GeoField*>::const_iterator iter = flds.begin();
242 const GeoField& fld = *iter();
244 typename GeoField::GeometricBoundaryField& bfld =
245 const_cast<typename GeoField::GeometricBoundaryField&>
250 // Shrink patchFields
251 bfld.setSize(bfld.size() - 1);
256 // Save whole boundary field
257 template <class T, class Mesh>
258 void Foam::fvMeshDistribute::saveBoundaryFields
260 PtrList<FieldField<fvsPatchField, T> >& bflds
263 typedef GeometricField<T, fvsPatchField, Mesh> fldType;
265 HashTable<const fldType*> flds
267 mesh_.objectRegistry::lookupClass<fldType>()
270 bflds.setSize(flds.size());
276 typename HashTable<const fldType*>::const_iterator iter = flds.begin();
281 const fldType& fld = *iter();
283 bflds.set(i, fld.boundaryField().clone().ptr());
290 // Map boundary field
291 template <class T, class Mesh>
292 void Foam::fvMeshDistribute::mapBoundaryFields
294 const mapPolyMesh& map,
295 const PtrList<FieldField<fvsPatchField, T> >& oldBflds
298 const labelList& oldPatchStarts = map.oldPatchStarts();
299 const labelList& faceMap = map.faceMap();
301 typedef GeometricField<T, fvsPatchField, Mesh> fldType;
303 HashTable<const fldType*> flds
305 mesh_.objectRegistry::lookupClass<fldType>()
308 if (flds.size() != oldBflds.size())
310 FatalErrorIn("fvMeshDistribute::mapBoundaryFields(..)") << "problem"
311 << abort(FatalError);
318 typename HashTable<const fldType*>::const_iterator iter = flds.begin();
323 const fldType& fld = *iter();
324 typename fldType::GeometricBoundaryField& bfld =
325 const_cast<typename fldType::GeometricBoundaryField&>
331 const FieldField<fvsPatchField, T>& oldBfld = oldBflds[fieldI++];
333 // Pull from old boundary field into bfld.
337 fvsPatchField<T>& patchFld = bfld[patchI];
338 label faceI = patchFld.patch().patch().start();
342 label oldFaceI = faceMap[faceI++];
344 // Find patch and local patch face oldFaceI was in.
345 forAll(oldPatchStarts, oldPatchI)
347 label oldLocalI = oldFaceI - oldPatchStarts[oldPatchI];
349 if (oldLocalI >= 0 && oldLocalI < oldBfld[oldPatchI].size())
351 patchFld[i] = oldBfld[oldPatchI][oldLocalI];
360 // Init patch fields of certain type
361 template<class GeoField, class PatchFieldType>
362 void Foam::fvMeshDistribute::initPatchFields
364 const typename GeoField::value_type& initVal
367 HashTable<const GeoField*> flds
369 mesh_.objectRegistry::lookupClass<GeoField>()
374 typename HashTable<const GeoField*>::const_iterator iter = flds.begin();
379 const GeoField& fld = *iter();
381 typename GeoField::GeometricBoundaryField& bfld =
382 const_cast<typename GeoField::GeometricBoundaryField&>
389 if (isA<PatchFieldType>(bfld[patchI]))
391 bfld[patchI] == initVal;
398 // Send fields. Note order supplied so we can receive in exactly the same order.
399 // Note that field gets written as entry in dictionary so we
400 // can construct from subdictionary.
401 // (since otherwise the reading as-a-dictionary mixes up entries from
402 // consecutive fields)
403 // The dictionary constructed is:
406 // p {internalField ..; boundaryField ..;}
407 // k {internalField ..; boundaryField ..;}
411 // U {internalField ... }
414 // volVectorField {U {internalField ..; boundaryField ..;}}
416 template<class GeoField>
417 void Foam::fvMeshDistribute::sendFields
420 const wordList& fieldNames,
421 const fvMeshSubset& subsetter,
425 toNbr << GeoField::typeName << token::NL << token::BEGIN_BLOCK << token::NL;
426 forAll(fieldNames, i)
430 Pout<< "Subsetting field " << fieldNames[i]
431 << " for domain:" << domain << endl;
434 // Send all fieldNames. This has to be exactly the same set as is
436 const GeoField& fld =
437 subsetter.baseMesh().lookupObject<GeoField>(fieldNames[i]);
439 tmp<GeoField> tsubfld = subsetter.interpolate(fld);
442 << fieldNames[i] << token::NL << token::BEGIN_BLOCK
444 << token::NL << token::END_BLOCK << token::NL;
446 toNbr << token::END_BLOCK << token::NL;
450 // Opposite of sendFields
451 template<class GeoField>
452 void Foam::fvMeshDistribute::receiveFields
455 const wordList& fieldNames,
457 PtrList<GeoField>& fields,
458 const dictionary& fieldDicts
463 Pout<< "Receiving fields " << fieldNames
464 << " from domain:" << domain << endl;
467 fields.setSize(fieldNames.size());
469 forAll(fieldNames, i)
473 Pout<< "Constructing field " << fieldNames[i]
474 << " from domain:" << domain << endl;
485 mesh.time().timeName(),
491 fieldDicts.subDict(fieldNames[i])
498 // ************************************************************************* //