/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org \\ / A nd | Copyright (C) 2011-2023 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 "fvFieldDecomposer.H" #include "processorFvPatchField.H" #include "processorFvsPatchField.H" #include "processorCyclicFvPatchField.H" #include "processorCyclicFvsPatchField.H" #include "emptyFvPatchFields.H" #include "stringOps.H" // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template Foam::tmp> Foam::fvFieldDecomposer::mapCellToFace ( const labelUList& owner, const labelUList& neighbour, const Field& field, const labelUList& addressing ) { tmp> tfld(new Field(addressing.size())); Field& fld = tfld.ref(); forAll(addressing, i) { fld[i] = field [ addressing[i] > 0 ? neighbour[addressing[i] - 1] : owner[- addressing[i] - 1] ]; } return tfld; } template Foam::tmp> Foam::fvFieldDecomposer::mapFaceToFace ( const Field& field, const labelUList& addressing, const bool isFlux ) { tmp> tfld(new Field(addressing.size())); Field& fld = tfld.ref(); forAll(addressing, i) { fld[i] = (isFlux && addressing[i] < 0 ? -1 : +1) *field[mag(addressing[i]) - 1]; } return tfld; } template Foam::tmp> Foam::fvFieldDecomposer::decomposeField ( const VolField& field ) const { // Create dummy patch fields PtrList> patchFields(procMesh_.boundary().size()); forAll(procMesh_.boundary(), procPatchi) { patchFields.set ( procPatchi, fvPatchField::New ( calculatedFvPatchField::typeName, procMesh_.boundary()[procPatchi], DimensionedField::null() ) ); } // Create the processor field with the dummy patch fields tmp> tresF ( new VolField ( IOobject ( field.name(), procMesh_.time().name(), procMesh_, IOobject::NO_READ, IOobject::NO_WRITE, false ), procMesh_, field.dimensions(), Field(field.primitiveField(), cellAddressing_), patchFields ) ); VolField& resF = tresF.ref(); // Change the patch fields to the correct type using a mapper constructor // (with reference to the now correct internal field) typename VolField:: Boundary& bf = resF.boundaryFieldRef(); forAll(bf, procPatchi) { const fvPatch& procPatch = procMesh_.boundary()[procPatchi]; const label completePatchi = completePatchID(procPatchi); if (completePatchi == procPatchi) { bf.set ( procPatchi, fvPatchField::New ( field.boundaryField()[completePatchi], procPatch, resF(), patchFieldDecomposers_[procPatchi] ) ); } else if (isA(procPatch)) { if (field.boundaryField()[completePatchi].overridesConstraint()) { OStringStream str; str << "\nThe field \"" << field.name() << "\" on cyclic patch \"" << field.boundaryField()[completePatchi].patch().name() << "\" cannot be decomposed as it is not a cyclic " << "patch field. A \"patchType cyclic;\" setting has " << "been used to override the cyclic patch type.\n\n" << "Cyclic patches like this with non-cyclic boundary " << "conditions should be confined to a single " << "processor using decomposition constraints."; FatalErrorInFunction << stringOps::breakIntoIndentedLines(str.str()).c_str() << exit(FatalError); } const label nbrCompletePatchi = refCast(procPatch) .referPatch().nbrPatchID(); bf.set ( procPatchi, new processorCyclicFvPatchField ( procPatch, resF(), mapCellToFace ( labelUList(), completeMesh_.lduAddr().patchAddr(nbrCompletePatchi), field.primitiveField(), faceAddressingBf_[procPatchi] ) ) ); } else if (isA(procPatch)) { bf.set ( procPatchi, new processorFvPatchField ( procPatch, resF(), mapCellToFace ( completeMesh_.owner(), completeMesh_.neighbour(), field.primitiveField(), faceAddressingBf_[procPatchi] ) ) ); } else { FatalErrorInFunction << "Unknown type." << abort(FatalError); } } return tresF; } template Foam::tmp> Foam::fvFieldDecomposer::decomposeField ( const SurfaceField& field ) const { const SubList