FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

fvMeshDistributeTemplates.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include <OpenFOAM/mapPolyMesh.H>
00027 #include <OpenFOAM/PstreamCombineReduceOps.H>
00028 
00029 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00030 
00031 //- combineReduce operator for lists. Used for counting.
00032 class listEq
00033 {
00034 
00035 public:
00036 
00037     template<class T>
00038     void operator()(T& x, const T& y) const
00039     {
00040         forAll(y, i)
00041         {
00042             if (y[i].size())
00043             {
00044                 x[i] = y[i];
00045             }
00046         }
00047     }
00048 };
00049 
00050 
00051 template <class Container, class T>
00052 void Foam::fvMeshDistribute::exchange
00053 (
00054     const List<Container >& sendBufs,
00055     List<Container >& recvBufs,
00056     labelListList& sizes
00057 )
00058 {
00059     if (Pstream::parRun())
00060     {
00061         if (!contiguous<T>())
00062         {
00063             FatalErrorIn
00064             (
00065                 "Pstream::exchange(..)"
00066             )   << "Continuous data only." << Foam::abort(FatalError);
00067         }
00068 
00069         if (sendBufs.size() != Pstream::nProcs())
00070         {
00071             FatalErrorIn
00072             (
00073                 "Pstream::exchange(..)"
00074             )   << "Size of list:" << sendBufs.size()
00075                 << " does not equal the number of processors:"
00076                 << Pstream::nProcs()
00077                 << Foam::abort(FatalError);
00078         }
00079 
00080         sizes.setSize(Pstream::nProcs());
00081         labelList& nsTransPs = sizes[Pstream::myProcNo()];
00082         nsTransPs.setSize(Pstream::nProcs());
00083 
00084         forAll(sendBufs, procI)
00085         {
00086             nsTransPs[procI] = sendBufs[procI].size();
00087         }
00088 
00089         Foam::combineReduce(sizes, listEq());
00090 
00091 
00092         // Set up receives
00093         // ~~~~~~~~~~~~~~~
00094 
00095         recvBufs.setSize(sendBufs.size());
00096         forAll(sizes, procI)
00097         {
00098             label nRecv = sizes[procI][Pstream::myProcNo()];
00099 
00100             if (procI != Pstream::myProcNo() && nRecv > 0)
00101             {
00102                 recvBufs[procI].setSize(nRecv);
00103                 IPstream::read
00104                 (
00105                     Pstream::nonBlocking,
00106                     procI,
00107                     reinterpret_cast<char*>(recvBufs[procI].begin()),
00108                     nRecv*sizeof(T)
00109                 );
00110             }
00111         }
00112 
00113 
00114         // Set up sends
00115         // ~~~~~~~~~~~~
00116 
00117         forAll(sendBufs, procI)
00118         {
00119             if (procI != Pstream::myProcNo() && sendBufs[procI].size() > 0)
00120             {
00121                 if
00122                 (
00123                    !OPstream::write
00124                     (
00125                         Pstream::nonBlocking,
00126                         procI,
00127                         reinterpret_cast<const char*>(sendBufs[procI].begin()),
00128                         sendBufs[procI].size()*sizeof(T)
00129                     )
00130                 )
00131                 {
00132                     FatalErrorIn("Pstream::exchange(..)")
00133                         << "Cannot send outgoing message. "
00134                         << "to:" << procI << " nBytes:"
00135                         << label(sendBufs[procI].size()*sizeof(T))
00136                         << Foam::abort(FatalError);
00137                 }
00138             }
00139         }
00140 
00141 
00142         // Wait for all to finish
00143         // ~~~~~~~~~~~~~~~~~~~~~~
00144 
00145         IPstream::waitRequests();
00146         OPstream::waitRequests();
00147     }
00148 
00149     // Do myself
00150     recvBufs[Pstream::myProcNo()] = sendBufs[Pstream::myProcNo()];
00151 }
00152 
00153 
00154 template<class GeoField>
00155 void Foam::fvMeshDistribute::printFieldInfo(const fvMesh& mesh)
00156 {
00157     HashTable<const GeoField*> flds
00158     (
00159         mesh.objectRegistry::lookupClass<GeoField>()
00160     );
00161 
00162     for
00163     (
00164         typename HashTable<const GeoField*>::const_iterator iter = flds.begin();
00165         iter != flds.end();
00166         ++iter
00167     )
00168     {
00169         const GeoField& fld = *iter();
00170 
00171         Pout<< "Field:" << iter.key() << " internalsize:" << fld.size()
00172             //<< " value:" << fld
00173             << endl;
00174 
00175         forAll(fld.boundaryField(), patchI)
00176         {
00177             Pout<< "    " << patchI
00178                 << ' ' << fld.boundaryField()[patchI].patch().name()
00179                 << ' ' << fld.boundaryField()[patchI].type()
00180                 << ' ' << fld.boundaryField()[patchI].size()
00181                 << endl;
00182         }
00183     }
00184 }
00185 
00186 
00187 template<class GeoField>
00188 void Foam::fvMeshDistribute::addPatchFields(const word& patchFieldType)
00189 {
00190     HashTable<const GeoField*> flds
00191     (
00192         mesh_.objectRegistry::lookupClass<GeoField>()
00193     );
00194 
00195     for
00196     (
00197         typename HashTable<const GeoField*>::const_iterator iter = flds.begin();
00198         iter != flds.end();
00199         ++iter
00200     )
00201     {
00202         const GeoField& fld = *iter();
00203 
00204         typename GeoField::GeometricBoundaryField& bfld =
00205             const_cast<typename GeoField::GeometricBoundaryField&>
00206             (
00207                 fld.boundaryField()
00208             );
00209 
00210         label sz = bfld.size();
00211         bfld.setSize(sz + 1);
00212         bfld.set
00213         (
00214             sz,
00215             GeoField::PatchFieldType::New
00216             (
00217                 patchFieldType,
00218                 mesh_.boundary()[sz],
00219                 fld.dimensionedInternalField()
00220             )
00221         );
00222     }
00223 }
00224 
00225 
00226 // Delete trailing patch fields
00227 template<class GeoField>
00228 void Foam::fvMeshDistribute::deleteTrailingPatchFields()
00229 {
00230     HashTable<const GeoField*> flds
00231     (
00232         mesh_.objectRegistry::lookupClass<GeoField>()
00233     );
00234 
00235     for
00236     (
00237         typename HashTable<const GeoField*>::const_iterator iter = flds.begin();
00238         iter != flds.end();
00239         ++iter
00240     )
00241     {
00242         const GeoField& fld = *iter();
00243 
00244         typename GeoField::GeometricBoundaryField& bfld =
00245             const_cast<typename GeoField::GeometricBoundaryField&>
00246             (
00247                 fld.boundaryField()
00248             );
00249 
00250         // Shrink patchFields
00251         bfld.setSize(bfld.size() - 1);
00252     }
00253 }
00254 
00255 
00256 // Save whole boundary field
00257 template <class T, class Mesh>
00258 void Foam::fvMeshDistribute::saveBoundaryFields
00259 (
00260     PtrList<FieldField<fvsPatchField, T> >& bflds
00261 ) const
00262 {
00263     typedef GeometricField<T, fvsPatchField, Mesh> fldType;
00264 
00265     HashTable<const fldType*> flds
00266     (
00267         mesh_.objectRegistry::lookupClass<fldType>()
00268     );
00269 
00270     bflds.setSize(flds.size());
00271 
00272     label i = 0;
00273 
00274     for
00275     (
00276         typename HashTable<const fldType*>::const_iterator iter = flds.begin();
00277         iter != flds.end();
00278         ++iter
00279     )
00280     {
00281         const fldType& fld = *iter();
00282 
00283         bflds.set(i, fld.boundaryField().clone().ptr());
00284 
00285         i++;
00286     }
00287 }
00288 
00289 
00290 // Map boundary field
00291 template <class T, class Mesh>
00292 void Foam::fvMeshDistribute::mapBoundaryFields
00293 (
00294     const mapPolyMesh& map,
00295     const PtrList<FieldField<fvsPatchField, T> >& oldBflds
00296 )
00297 {
00298     const labelList& oldPatchStarts = map.oldPatchStarts();
00299     const labelList& faceMap = map.faceMap();
00300 
00301     typedef GeometricField<T, fvsPatchField, Mesh> fldType;
00302 
00303     HashTable<const fldType*> flds
00304     (
00305         mesh_.objectRegistry::lookupClass<fldType>()
00306     );
00307 
00308     if (flds.size() != oldBflds.size())
00309     {
00310         FatalErrorIn("fvMeshDistribute::mapBoundaryFields(..)") << "problem"
00311             << abort(FatalError);
00312     }
00313 
00314     label fieldI = 0;
00315 
00316     for
00317     (
00318         typename HashTable<const fldType*>::const_iterator iter = flds.begin();
00319         iter != flds.end();
00320         ++iter
00321     )
00322     {
00323         const fldType& fld = *iter();
00324         typename fldType::GeometricBoundaryField& bfld =
00325             const_cast<typename fldType::GeometricBoundaryField&>
00326             (
00327                 fld.boundaryField()
00328             );
00329 
00330 
00331         const FieldField<fvsPatchField, T>& oldBfld = oldBflds[fieldI++];
00332 
00333         // Pull from old boundary field into bfld.
00334 
00335         forAll(bfld, patchI)
00336         {
00337             fvsPatchField<T>& patchFld = bfld[patchI];
00338             label faceI = patchFld.patch().patch().start();
00339 
00340             forAll(patchFld, i)
00341             {
00342                 label oldFaceI = faceMap[faceI++];
00343 
00344                 // Find patch and local patch face oldFaceI was in.
00345                 forAll(oldPatchStarts, oldPatchI)
00346                 {
00347                     label oldLocalI = oldFaceI - oldPatchStarts[oldPatchI];
00348 
00349                     if (oldLocalI >= 0 && oldLocalI < oldBfld[oldPatchI].size())
00350                     {
00351                         patchFld[i] = oldBfld[oldPatchI][oldLocalI];
00352                     }
00353                 }
00354             }
00355         }
00356     }
00357 }
00358 
00359 
00360 // Init patch fields of certain type
00361 template<class GeoField, class PatchFieldType>
00362 void Foam::fvMeshDistribute::initPatchFields
00363 (
00364     const typename GeoField::value_type& initVal
00365 )
00366 {
00367     HashTable<const GeoField*> flds
00368     (
00369         mesh_.objectRegistry::lookupClass<GeoField>()
00370     );
00371 
00372     for
00373     (
00374         typename HashTable<const GeoField*>::const_iterator iter = flds.begin();
00375         iter != flds.end();
00376         ++iter
00377     )
00378     {
00379         const GeoField& fld = *iter();
00380 
00381         typename GeoField::GeometricBoundaryField& bfld =
00382             const_cast<typename GeoField::GeometricBoundaryField&>
00383             (
00384                 fld.boundaryField()
00385             );
00386 
00387         forAll(bfld, patchI)
00388         {
00389             if (isA<PatchFieldType>(bfld[patchI]))
00390             {
00391                 bfld[patchI] == initVal;
00392             }
00393         }
00394     }
00395 }
00396 
00397 
00398 // Send fields. Note order supplied so we can receive in exactly the same order.
00399 // Note that field gets written as entry in dictionary so we
00400 // can construct from subdictionary.
00401 // (since otherwise the reading as-a-dictionary mixes up entries from
00402 // consecutive fields)
00403 // The dictionary constructed is:
00404 //  volScalarField
00405 //  {
00406 //      p {internalField ..; boundaryField ..;}
00407 //      k {internalField ..; boundaryField ..;}
00408 //  }
00409 //  volVectorField
00410 //  {
00411 //      U {internalField ...  }
00412 //  }
00413 
00414 // volVectorField {U {internalField ..; boundaryField ..;}}
00415 // 
00416 template<class GeoField>
00417 void Foam::fvMeshDistribute::sendFields
00418 (
00419     const label domain,
00420     const wordList& fieldNames,
00421     const fvMeshSubset& subsetter,
00422     OSstream& toNbr
00423 )
00424 {
00425     toNbr << GeoField::typeName << token::NL << token::BEGIN_BLOCK << token::NL;
00426     forAll(fieldNames, i)
00427     {
00428         if (debug)
00429         {
00430             Pout<< "Subsetting field " << fieldNames[i]
00431                 << " for domain:" << domain << endl;
00432         }
00433 
00434         // Send all fieldNames. This has to be exactly the same set as is
00435         // being received!
00436         const GeoField& fld =
00437             subsetter.baseMesh().objectRegistry::lookupObject<GeoField>(fieldNames[i]);
00438 
00439         tmp<GeoField> tsubfld = subsetter.interpolate(fld);
00440 
00441         toNbr
00442             << fieldNames[i] << token::NL << token::BEGIN_BLOCK
00443             << tsubfld
00444             << token::NL << token::END_BLOCK << token::NL;
00445     }
00446     toNbr << token::END_BLOCK << token::NL;
00447 }
00448 
00449 
00450 // Opposite of sendFields
00451 template<class GeoField>
00452 void Foam::fvMeshDistribute::receiveFields
00453 (
00454     const label domain,
00455     const wordList& fieldNames,
00456     fvMesh& mesh,
00457     PtrList<GeoField>& fields,
00458     const dictionary& fieldDicts
00459 )
00460 {
00461     if (debug)
00462     {
00463         Pout<< "Receiving fields " << fieldNames
00464             << " from domain:" << domain << endl;
00465     }
00466 
00467     fields.setSize(fieldNames.size());
00468 
00469     forAll(fieldNames, i)
00470     {
00471         if (debug)
00472         {
00473             Pout<< "Constructing field " << fieldNames[i]
00474                 << " from domain:" << domain << endl;
00475         }
00476 
00477         fields.set
00478         (
00479             i,
00480             new GeoField
00481             (
00482                 IOobject
00483                 (
00484                     fieldNames[i],
00485                     mesh.time().timeName(),
00486                     mesh,
00487                     IOobject::NO_READ,
00488                     IOobject::AUTO_WRITE
00489                 ),
00490                 mesh,
00491                 fieldDicts.subDict(fieldNames[i])
00492             )
00493         );
00494     }
00495 }
00496 
00497 
00498 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines