/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2015 OpenFOAM Foundation \\/ M anipulation | Copyright (C) 2016-2017 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 . \*---------------------------------------------------------------------------*/ #include "parFvFieldReconstructor.H" #include "Time.H" #include "PtrList.H" #include "fvPatchFields.H" #include "emptyFvPatch.H" #include "emptyFvPatchField.H" #include "emptyFvsPatchField.H" #include "IOobjectList.H" #include "mapDistributePolyMesh.H" #include "processorFvPatch.H" #include "directFvPatchFieldMapper.H" #include "distributedUnallocatedDirectFieldMapper.H" #include "distributedUnallocatedDirectFvPatchFieldMapper.H" // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template Foam::tmp> Foam::parFvFieldReconstructor::reconstructFvVolumeInternalField ( const DimensionedField& fld ) const { distributedUnallocatedDirectFieldMapper mapper ( labelUList::null(), distMap_.cellMap() ); Field internalField(fld, mapper); // Construct a volField IOobject baseIO ( fld.name(), baseMesh_.time().timeName(), fld.local(), baseMesh_, IOobject::NO_READ, IOobject::NO_WRITE ); tmp> tfield ( new DimensionedField ( baseIO, baseMesh_, fld.dimensions(), internalField ) ); tfield.ref().oriented() = fld.oriented(); return tfield; } template Foam::tmp> Foam::parFvFieldReconstructor::reconstructFvVolumeInternalField ( const IOobject& fieldIoObject ) const { // Read the field DimensionedField fld ( fieldIoObject, procMesh_ ); // Distribute onto baseMesh return reconstructFvVolumeInternalField(fld); } // Reconstruct a field onto the baseMesh template Foam::tmp> Foam::parFvFieldReconstructor::reconstructFvVolumeField ( const GeometricField& fld ) const { // Create the internalField by remote mapping // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ distributedUnallocatedDirectFieldMapper mapper ( labelUList::null(), distMap_.cellMap() ); Field internalField(fld.internalField(), mapper); // Create the patchFields by remote mapping // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Note: patchFields still on mesh, not baseMesh PtrList> patchFields(fld.mesh().boundary().size()); const typename GeometricField::Boundary& bfld = fld.boundaryField(); forAll(bfld, patchI) { if (patchFaceMaps_.set(patchI)) { // Clone local patch field patchFields.set(patchI, bfld[patchI].clone()); distributedUnallocatedDirectFvPatchFieldMapper mapper ( labelUList::null(), patchFaceMaps_[patchI] ); // Map into local copy patchFields[patchI].autoMap(mapper); } } PtrList> basePatchFields ( baseMesh_.boundary().size() ); // Clone the patchFields onto the base patches. This is just to reset // the reference to the patch, size and content stay the same. forAll(patchFields, patchI) { if (patchFields.set(patchI)) { const fvPatch& basePatch = baseMesh_.boundary()[patchI]; const fvPatchField& pfld = patchFields[patchI]; labelList dummyMap(identity(pfld.size())); directFvPatchFieldMapper dummyMapper(dummyMap); basePatchFields.set ( patchI, fvPatchField::New ( pfld, basePatch, DimensionedField::null(), dummyMapper ) ); } } // Add some empty patches on remaining patches (tbd.probably processor // patches) forAll(basePatchFields, patchI) { if (patchI >= patchFields.size() || !patchFields.set(patchI)) { basePatchFields.set ( patchI, fvPatchField::New ( emptyFvPatchField::typeName, baseMesh_.boundary()[patchI], DimensionedField::null() ) ); } } // Construct a volField IOobject baseIO ( fld.name(), baseMesh_.time().timeName(), fld.local(), baseMesh_, IOobject::NO_READ, IOobject::NO_WRITE ); tmp> tfield ( new GeometricField ( baseIO, baseMesh_, fld.dimensions(), internalField, basePatchFields ) ); tfield.ref().oriented()= fld.oriented(); return tfield; } template Foam::tmp> Foam::parFvFieldReconstructor::reconstructFvVolumeField ( const IOobject& fieldIoObject ) const { // Read the field GeometricField fld ( fieldIoObject, procMesh_ ); // Distribute onto baseMesh return reconstructFvVolumeField(fld); } template Foam::tmp> Foam::parFvFieldReconstructor::reconstructFvSurfaceField ( const GeometricField& fld ) const { // Create the internalField by remote mapping // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ distributedUnallocatedDirectFieldMapper mapper ( labelUList::null(), distMap_.faceMap() ); // Create flat field of internalField + all patch fields Field flatFld(fld.mesh().nFaces(), Type(Zero)); SubList(flatFld, fld.internalField().size()) = fld.internalField(); forAll(fld.boundaryField(), patchI) { const fvsPatchField& fvp = fld.boundaryField()[patchI]; SubList(flatFld, fvp.size(), fvp.patch().start()) = fvp; } // Map all faces Field internalField(flatFld, mapper, fld.oriented()()); // Trim to internal faces (note: could also have special mapper) internalField.setSize ( min ( internalField.size(), baseMesh_.nInternalFaces() ) ); // Create the patchFields by remote mapping // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Note: patchFields still on mesh, not baseMesh PtrList> patchFields(fld.mesh().boundary().size()); const typename GeometricField::Boundary& bfld = fld.boundaryField(); forAll(bfld, patchI) { if (patchFaceMaps_.set(patchI)) { // Clone local patch field patchFields.set(patchI, bfld[patchI].clone()); distributedUnallocatedDirectFvPatchFieldMapper mapper ( labelUList::null(), patchFaceMaps_[patchI] ); // Map into local copy patchFields[patchI].autoMap(mapper); } } PtrList> basePatchFields ( baseMesh_.boundary().size() ); // Clone the patchFields onto the base patches. This is just to reset // the reference to the patch, size and content stay the same. forAll(patchFields, patchI) { if (patchFields.set(patchI)) { const fvPatch& basePatch = baseMesh_.boundary()[patchI]; const fvsPatchField& pfld = patchFields[patchI]; labelList dummyMap(identity(pfld.size())); directFvPatchFieldMapper dummyMapper(dummyMap); basePatchFields.set ( patchI, fvsPatchField::New ( pfld, basePatch, DimensionedField::null(), dummyMapper ) ); } } // Add some empty patches on remaining patches (tbd.probably processor // patches) forAll(basePatchFields, patchI) { if (patchI >= patchFields.size() || !patchFields.set(patchI)) { basePatchFields.set ( patchI, fvsPatchField::New ( emptyFvsPatchField::typeName, baseMesh_.boundary()[patchI], DimensionedField::null() ) ); } } // Construct a volField IOobject baseIO ( fld.name(), baseMesh_.time().timeName(), fld.local(), baseMesh_, IOobject::NO_READ, IOobject::NO_WRITE ); tmp> tfield ( new GeometricField ( baseIO, baseMesh_, fld.dimensions(), internalField, basePatchFields ) ); tfield.ref().oriented() = fld.oriented(); return tfield; } template Foam::tmp> Foam::parFvFieldReconstructor::reconstructFvSurfaceField ( const IOobject& fieldIoObject ) const { // Read the field GeometricField fld ( fieldIoObject, procMesh_ ); return reconstructFvSurfaceField(fld); } template void Foam::parFvFieldReconstructor::reconstructFvVolumeInternalFields ( const IOobjectList& objects, const HashSet& selectedFields ) const { const word& fieldClassName = DimensionedField::typeName; IOobjectList fields = objects.lookupClass(fieldClassName); if (fields.size()) { Info<< " Reconstructing " << fieldClassName << "s\n" << endl; forAllConstIter(IOobjectList, fields, fieldIter) { if ( selectedFields.empty() || selectedFields.found(fieldIter()->name()) ) { Info<< " " << fieldIter()->name() << endl; tmp> tfld ( reconstructFvVolumeInternalField(*fieldIter()) ); if (isWriteProc_) { tfld().write(); } } } Info<< endl; } } template void Foam::parFvFieldReconstructor::reconstructFvVolumeFields ( const IOobjectList& objects, const HashSet& selectedFields ) const { const word& fieldClassName = GeometricField::typeName; IOobjectList fields = objects.lookupClass(fieldClassName); if (fields.size()) { Info<< " Reconstructing " << fieldClassName << "s\n" << endl; forAllConstIter(IOobjectList, fields, fieldIter) { const word& name = fieldIter()->name(); if ( (selectedFields.empty() || selectedFields.found(name)) && name != "cellDist" ) { Info<< " " << name << endl; tmp> tfld ( reconstructFvVolumeField(*fieldIter()) ); if (isWriteProc_) { tfld().write(); } } } Info<< endl; } } template void Foam::parFvFieldReconstructor::reconstructFvSurfaceFields ( const IOobjectList& objects, const HashSet& selectedFields ) const { const word& fieldClassName = GeometricField::typeName; IOobjectList fields = objects.lookupClass(fieldClassName); if (fields.size()) { Info<< " Reconstructing " << fieldClassName << "s\n" << endl; forAllConstIter(IOobjectList, fields, fieldIter) { if ( selectedFields.empty() || selectedFields.found(fieldIter()->name()) ) { Info<< " " << fieldIter()->name() << endl; tmp> tfld ( reconstructFvSurfaceField(*fieldIter()) ); if (isWriteProc_) { tfld().write(); } } } Info<< endl; } } // ************************************************************************* //