/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "polyTopoChangeMap.H" #include "processorFvPatchField.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template void Foam::fvMeshDistribute::printFieldInfo(const fvMesh& mesh) { HashTable flds ( mesh.objectRegistry::lookupClass() ); forAllConstIter(typename HashTable, flds, iter) { const GeoField& fld = *iter(); Pout<< "Field:" << iter.key() << " internal size:" << fld.size() << endl; forAll(fld.boundaryField(), patchi) { Pout<< " " << patchi << ' ' << fld.boundaryField()[patchi].patch().name() << ' ' << fld.boundaryField()[patchi].type() << ' ' << fld.boundaryField()[patchi].size() << endl; } } } template void Foam::fvMeshDistribute::saveBoundaryFields ( PtrList>& bflds ) const { // Save whole boundary field HashTable*> flds ( static_cast(mesh_) .objectRegistry::lookupClass>() ); bflds.setSize(flds.size()); label i = 0; forAllConstIter(typename HashTable*>, flds, iter) { const SurfaceField& fld = *iter(); bflds.set(i, fld.boundaryField().clone().ptr()); i++; } } template void Foam::fvMeshDistribute::mapBoundaryFields ( const polyTopoChangeMap& map, const PtrList>& oldBflds ) { // Map boundary field const labelList& oldPatchStarts = map.oldPatchStarts(); const labelList& faceMap = map.faceMap(); HashTable*> flds ( mesh_.objectRegistry::lookupClass>() ); if (flds.size() != oldBflds.size()) { FatalErrorInFunction << abort(FatalError); } label fieldi = 0; forAllIter(typename HashTable*>, flds, iter) { SurfaceField& fld = *iter(); typename SurfaceField::Boundary& bfld = fld.boundaryFieldRef(); const FieldField& oldBfld = oldBflds[fieldi++]; // Pull from old boundary field into bfld. forAll(bfld, patchi) { fvsPatchField& patchFld = bfld[patchi]; label facei = patchFld.patch().start(); forAll(patchFld, i) { label oldFacei = faceMap[facei++]; // Find patch and local patch face oldFacei was in. forAll(oldPatchStarts, oldPatchi) { label oldLocalI = oldFacei - oldPatchStarts[oldPatchi]; if (oldLocalI >= 0 && oldLocalI < oldBfld[oldPatchi].size()) { patchFld[i] = oldBfld[oldPatchi][oldLocalI]; } } } } } } template void Foam::fvMeshDistribute::initMapExposedFaces ( PtrList>& iflds ) const { HashTable*> flds ( static_cast(mesh_).lookupClass>() ); iflds.setSize(flds.size()); label fieldi = 0; forAllConstIter(typename HashTable*>, flds, iter) { iflds.set(fieldi, Field(mesh_.nFaces())); const SurfaceField& fld = *iter(); SubList(iflds[fieldi], fld.primitiveField().size()) = fld.primitiveField(); forAll(fld.boundaryField(), patchi) { const fvsPatchField& pfld = fld.boundaryField()[patchi]; SubList(iflds[fieldi], pfld.size(), pfld.patch().start()) = pfld; } fieldi++; } } template void Foam::fvMeshDistribute::mapExposedFaces ( const polyTopoChangeMap& map, const PtrList>& oldFlds ) { HashTable*> flds ( mesh_.objectRegistry::lookupClass>() ); label fieldi = 0; forAllIter(typename HashTable*>, flds, iter) { SurfaceField& fld = *iter(); const Field& oldFld = oldFlds[fieldi]; const bool negateIfFlipped = isFlux(fld); forAll(fld.boundaryField(), patchi) { fvsPatchField& patchFld = fld.boundaryFieldRef()[patchi]; forAll(patchFld, i) { const label facei = patchFld.patch().start()+i; const label oldFacei = map.faceMap()[facei]; if (oldFacei < map.nOldInternalFaces()) { if (negateIfFlipped && map.flipFaceFlux().found(facei)) { patchFld[i] = flipOp()(oldFld[oldFacei]); } else { patchFld[i] = oldFld[oldFacei]; } } else { patchFld[i] = oldFld[oldFacei]; } } } fieldi++; } } template void Foam::fvMeshDistribute::correctCoupledPatchFields() { HashTable flds ( mesh_.objectRegistry::lookupClass() ); forAllIter(typename HashTable, flds, iter) { GeoField& fld = *iter(); typename GeoField::Boundary& bfld = fld.boundaryFieldRef(); if ( Pstream::defaultCommsType == Pstream::commsTypes::blocking || Pstream::defaultCommsType == Pstream::commsTypes::nonBlocking ) { label nReq = Pstream::nRequests(); forAll(bfld, patchi) { if (bfld[patchi].coupled()) { bfld[patchi].initEvaluate(Pstream::defaultCommsType); } } // Block for any outstanding requests if ( Pstream::parRun() && Pstream::defaultCommsType == Pstream::commsTypes::nonBlocking ) { Pstream::waitRequests(nReq); } forAll(bfld, patchi) { if (bfld[patchi].coupled()) { bfld[patchi].evaluate(Pstream::defaultCommsType); } } } else if (Pstream::defaultCommsType == Pstream::commsTypes::scheduled) { const lduSchedule& patchSchedule = mesh_.globalData().patchSchedule(); forAll(patchSchedule, patchEvali) { if (bfld[patchEvali].coupled()) { if (patchSchedule[patchEvali].init) { bfld[patchSchedule[patchEvali].patch] .initEvaluate(Pstream::commsTypes::scheduled); } else { bfld[patchSchedule[patchEvali].patch] .evaluate(Pstream::commsTypes::scheduled); } } } } } } template void Foam::fvMeshDistribute::sendFields ( const label domain, const wordList& fieldNames, const fvMeshSubset& subsetter, Ostream& toNbr ) { // Send fields. Note order supplied so we can receive in exactly the same // order. // Note that field gets written as entry in dictionary so we // can construct from subdictionary. // (since otherwise the reading as-a-dictionary mixes up entries from // consecutive fields) // The dictionary constructed is: // volScalarField // { // p {internalField ..; boundaryField ..;} // k {internalField ..; boundaryField ..;} // } // volVectorField // { // U {internalField ... } // } // volVectorField {U {internalField ..; boundaryField ..;}} toNbr << GeoField::typeName << token::NL << token::BEGIN_BLOCK << token::NL; forAll(fieldNames, i) { if (debug) { Pout<< "Subsetting field " << fieldNames[i] << " for domain:" << domain << endl; } // Send all fieldNames. This has to be exactly the same set as is // being received! const GeoField& fld = subsetter.baseMesh().lookupObject(fieldNames[i]); tmp tsubfld = subsetter.interpolate(fld); toNbr << fieldNames[i] << token::NL << token::BEGIN_BLOCK << tsubfld << token::NL << token::END_BLOCK << token::NL; } toNbr << token::END_BLOCK << token::NL; } template void Foam::fvMeshDistribute::receiveFields ( const label domain, const wordList& fieldNames, typename GeoField::Mesh& mesh, PtrList& fields, const dictionary& fieldDicts ) { if (debug) { Pout<< "Receiving fields " << fieldNames << " from domain:" << domain << endl; } fields.setSize(fieldNames.size()); forAll(fieldNames, i) { if (debug) { Pout<< "Constructing field " << fieldNames[i] << " from domain:" << domain << endl; } fields.set ( i, new GeoField ( IOobject ( fieldNames[i], mesh.thisDb().time().name(), mesh.thisDb(), IOobject::NO_READ, IOobject::AUTO_WRITE ), mesh, fieldDicts.subDict(fieldNames[i]) ) ); } } // ************************************************************************* //