Files
openfoam/src/dynamicMesh/fvMeshDistribute/fvMeshDistributeTemplates.C
mattijs 916dcb8685 ENH: parallel: overhaul of parallel mapping
- redistributePar to have almost (complete) functionality of decomposePar+reconstructPar
- low-level distributed Field mapping
- support for mapping surfaceFields (including flipping faces)
- support for decomposing/reconstructing refinement data
2015-11-17 15:05:05 +00:00

383 lines
9.7 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "mapPolyMesh.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class GeoField>
void Foam::fvMeshDistribute::printFieldInfo(const fvMesh& mesh)
{
HashTable<const GeoField*> flds
(
mesh.objectRegistry::lookupClass<GeoField>()
);
forAllConstIter(typename HashTable<const GeoField*>, flds, iter)
{
const GeoField& fld = *iter();
Pout<< "Field:" << iter.key() << " internalsize:" << fld.size()
//<< " value:" << fld
<< endl;
forAll(fld.boundaryField(), patchI)
{
Pout<< " " << patchI
<< ' ' << fld.boundaryField()[patchI].patch().name()
<< ' ' << fld.boundaryField()[patchI].type()
<< ' ' << fld.boundaryField()[patchI].size()
<< endl;
}
}
}
// Save whole boundary field
template<class T, class Mesh>
void Foam::fvMeshDistribute::saveBoundaryFields
(
PtrList<FieldField<fvsPatchField, T> >& bflds
) const
{
typedef GeometricField<T, fvsPatchField, Mesh> fldType;
HashTable<const fldType*> flds
(
static_cast<const fvMesh&>(mesh_).objectRegistry::lookupClass<fldType>()
);
bflds.setSize(flds.size());
label i = 0;
forAllConstIter(typename HashTable<const fldType*>, flds, iter)
{
const fldType& fld = *iter();
bflds.set(i, fld.boundaryField().clone().ptr());
i++;
}
}
// Map boundary field
template<class T, class Mesh>
void Foam::fvMeshDistribute::mapBoundaryFields
(
const mapPolyMesh& map,
const PtrList<FieldField<fvsPatchField, T> >& oldBflds
)
{
const labelList& oldPatchStarts = map.oldPatchStarts();
const labelList& faceMap = map.faceMap();
typedef GeometricField<T, fvsPatchField, Mesh> fldType;
HashTable<fldType*> flds
(
mesh_.objectRegistry::lookupClass<fldType>()
);
if (flds.size() != oldBflds.size())
{
FatalErrorIn("fvMeshDistribute::mapBoundaryFields(..)") << "problem"
<< abort(FatalError);
}
label fieldI = 0;
forAllIter(typename HashTable<fldType*>, flds, iter)
{
fldType& fld = *iter();
typename fldType::GeometricBoundaryField& bfld = fld.boundaryField();
const FieldField<fvsPatchField, T>& oldBfld = oldBflds[fieldI++];
// Pull from old boundary field into bfld.
forAll(bfld, patchI)
{
fvsPatchField<T>& 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<class T>
void Foam::fvMeshDistribute::saveInternalFields
(
PtrList<Field<T> >& iflds
) const
{
typedef GeometricField<T, fvsPatchField, surfaceMesh> fldType;
HashTable<const fldType*> flds
(
static_cast<const fvMesh&>(mesh_).objectRegistry::lookupClass<fldType>()
);
iflds.setSize(flds.size());
label i = 0;
forAllConstIter(typename HashTable<const fldType*>, flds, iter)
{
const fldType& fld = *iter();
iflds.set(i, fld.internalField().clone());
i++;
}
}
// Set boundary values of exposed internal faces
template<class T>
void Foam::fvMeshDistribute::mapExposedFaces
(
const mapPolyMesh& map,
const PtrList<Field<T> >& oldFlds
)
{
const labelList& faceMap = map.faceMap();
typedef GeometricField<T, fvsPatchField, surfaceMesh> fldType;
HashTable<fldType*> flds
(
mesh_.objectRegistry::lookupClass<fldType>()
);
if (flds.size() != oldFlds.size())
{
FatalErrorIn("fvMeshDistribute::mapExposedFaces(..)") << "problem"
<< abort(FatalError);
}
label fieldI = 0;
forAllIter(typename HashTable<fldType*>, flds, iter)
{
fldType& fld = *iter();
typename fldType::GeometricBoundaryField& bfld = fld.boundaryField();
const Field<T>& oldInternal = oldFlds[fieldI++];
// Pull from old internal field into bfld.
forAll(bfld, patchI)
{
fvsPatchField<T>& patchFld = bfld[patchI];
forAll(patchFld, i)
{
const label faceI = patchFld.patch().start()+i;
label oldFaceI = faceMap[faceI];
if (oldFaceI < oldInternal.size())
{
patchFld[i] = oldInternal[oldFaceI];
if (map.flipFaceFlux().found(faceI))
{
patchFld[i] = flipOp()(patchFld[i]);
}
}
}
}
}
}
// Init patch fields of certain type
template<class GeoField, class PatchFieldType>
void Foam::fvMeshDistribute::initPatchFields
(
const typename GeoField::value_type& initVal
)
{
HashTable<GeoField*> flds
(
mesh_.objectRegistry::lookupClass<GeoField>()
);
forAllIter(typename HashTable<GeoField*>, flds, iter)
{
GeoField& fld = *iter();
typename GeoField::GeometricBoundaryField& bfld =
fld.boundaryField();
forAll(bfld, patchI)
{
if (isA<PatchFieldType>(bfld[patchI]))
{
bfld[patchI] == initVal;
}
}
}
}
// correctBoundaryConditions patch fields of certain type
template<class GeoField>
void Foam::fvMeshDistribute::correctBoundaryConditions()
{
HashTable<GeoField*> flds
(
mesh_.objectRegistry::lookupClass<GeoField>()
);
forAllIter(typename HashTable<GeoField*>, flds, iter)
{
const GeoField& fld = *iter();
fld.correctBoundaryConditions();
}
}
// 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 ..;}}
//
template<class GeoField>
void Foam::fvMeshDistribute::sendFields
(
const label domain,
const wordList& fieldNames,
const fvMeshSubset& subsetter,
Ostream& toNbr
)
{
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<GeoField>(fieldNames[i]);
tmp<GeoField> 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;
}
// Opposite of sendFields
template<class GeoField>
void Foam::fvMeshDistribute::receiveFields
(
const label domain,
const wordList& fieldNames,
fvMesh& mesh,
PtrList<GeoField>& 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.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
fieldDicts.subDict(fieldNames[i])
)
);
}
}
// ************************************************************************* //