/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 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 "meshToMesh0.H" #include "volFields.H" #include "interpolationCellPoint.H" #include "SubField.H" #include "mixedFvPatchField.H" // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template void Foam::meshToMesh0::mapField ( Field& toF, const Field& fromVf, const labelList& adr, const CombineOp& cop ) const { // Direct mapping of nearest-cell values forAll(toF, celli) { if (adr[celli] != -1) { cop(toF[celli], fromVf[adr[celli]]); } } //toF.map(fromVf, adr); } template void Foam::meshToMesh0::interpolateField ( Field& toF, const GeometricField& fromVf, const labelListList& adr, const scalarListList& weights, const CombineOp& cop ) const { // Inverse volume weighted interpolation forAll(toF, celli) { const labelList& overlapCells = adr[celli]; const scalarList& w = weights[celli]; Type f = Zero; forAll(overlapCells, i) { label fromCelli = overlapCells[i]; f += fromVf[fromCelli]*w[i]; cop(toF[celli], f); } } } template void Foam::meshToMesh0::interpolateField ( Field& toF, const GeometricField& fromVf, const labelList& adr, const scalarListList& weights, const CombineOp& cop ) const { // Inverse distance weighted interpolation // get reference to cellCells const labelListList& cc = fromMesh_.cellCells(); forAll(toF, celli) { if (adr[celli] != -1) { const labelList& neighbours = cc[adr[celli]]; const scalarList& w = weights[celli]; Type f = fromVf[adr[celli]]*w[0]; for (label ni = 1; ni < w.size(); ni++) { f += fromVf[neighbours[ni - 1]]*w[ni]; } cop(toF[celli], f); } } } template void Foam::meshToMesh0::interpolateField ( Field& toF, const GeometricField& fromVf, const labelList& adr, const vectorField& centres, const CombineOp& cop ) const { // Cell-Point interpolation interpolationCellPoint interpolator(fromVf); forAll(toF, celli) { if (adr[celli] != -1) { cop ( toF[celli], interpolator.interpolate ( centres[celli], adr[celli] ) ); } } } template void Foam::meshToMesh0::interpolateInternalField ( Field& toF, const GeometricField& fromVf, meshToMesh0::order ord, const CombineOp& cop ) const { if (fromVf.mesh() != fromMesh_) { FatalErrorInFunction << "the argument field does not correspond to the right mesh. " << "Field size: " << fromVf.size() << " mesh size: " << fromMesh_.nCells() << exit(FatalError); } if (toF.size() != toMesh_.nCells()) { FatalErrorInFunction << "the argument field does not correspond to the right mesh. " << "Field size: " << toF.size() << " mesh size: " << toMesh_.nCells() << exit(FatalError); } switch(ord) { case MAP: mapField(toF, fromVf, cellAddressing_, cop); break; case INTERPOLATE: { interpolateField ( toF, fromVf, cellAddressing_, inverseDistanceWeights(), cop ); break; } case CELL_POINT_INTERPOLATE: { interpolateField ( toF, fromVf, cellAddressing_, toMesh_.cellCentres(), cop ); break; } case CELL_VOLUME_WEIGHT: { const labelListList& cellToCell = cellToCellAddressing(); const scalarListList& invVolWeights = inverseVolumeWeights(); interpolateField ( toF, fromVf, cellToCell, invVolWeights, cop ); break; } default: FatalErrorInFunction << "unknown interpolation scheme " << ord << exit(FatalError); } } template void Foam::meshToMesh0::interpolateInternalField ( Field& toF, const tmp>& tfromVf, meshToMesh0::order ord, const CombineOp& cop ) const { interpolateInternalField(toF, tfromVf(), ord, cop); tfromVf.clear(); } template void Foam::meshToMesh0::interpolate ( GeometricField& toVf, const GeometricField& fromVf, meshToMesh0::order ord, const CombineOp& cop ) const { interpolateInternalField(toVf, fromVf, ord, cop); forAll(toMesh_.boundaryMesh(), patchi) { const fvPatch& toPatch = toMesh_.boundary()[patchi]; if (cuttingPatches_.found(toPatch.name())) { switch(ord) { case MAP: { mapField ( toVf.boundaryField()[patchi], fromVf, boundaryAddressing_[patchi], cop ); break; } case INTERPOLATE: { interpolateField ( toVf.boundaryField()[patchi], fromVf, boundaryAddressing_[patchi], toPatch.Cf(), cop ); break; } case CELL_POINT_INTERPOLATE: { interpolateField ( toVf.boundaryField()[patchi], fromVf, boundaryAddressing_[patchi], toPatch.Cf(), cop ); break; } case CELL_VOLUME_WEIGHT: { // Do nothing break; } default: FatalErrorInFunction << "unknown interpolation scheme " << ord << exit(FatalError); } if (isA>(toVf.boundaryField()[patchi])) { refCast> ( toVf.boundaryField()[patchi] ).refValue() = toVf.boundaryField()[patchi]; } } else if ( patchMap_.found(toPatch.name()) && fromMeshPatches_.found(patchMap_.find(toPatch.name())()) ) { /* toVf.boundaryField()[patchi].map ( fromVf.boundaryField() [ fromMeshPatches_.find(patchMap_.find(toPatch.name())())() ], boundaryAddressing_[patchi] ); */ mapField ( toVf.boundaryField()[patchi], fromVf.boundaryField() [ fromMeshPatches_.find(patchMap_.find(toPatch.name())())() ], boundaryAddressing_[patchi], cop ); } } } template void Foam::meshToMesh0::interpolate ( GeometricField& toVf, const tmp>& tfromVf, meshToMesh0::order ord, const CombineOp& cop ) const { interpolate(toVf, tfromVf(), ord, cop); tfromVf.clear(); } template Foam::tmp> Foam::meshToMesh0::interpolate ( const GeometricField& fromVf, meshToMesh0::order ord, const CombineOp& cop ) const { // Create and map the internal-field values Field internalField(toMesh_.nCells()); interpolateInternalField(internalField, fromVf, ord, cop); // check whether both meshes have got the same number // of boundary patches if (fromMesh_.boundary().size() != toMesh_.boundary().size()) { FatalErrorInFunction << "Incompatible meshes: different number of boundaries, " "only internal field may be interpolated" << exit(FatalError); } // Create and map the patch field values PtrList> patchFields ( boundaryAddressing_.size() ); forAll(boundaryAddressing_, patchI) { patchFields.set ( patchI, fvPatchField::New ( fromVf.boundaryField()[patchI], toMesh_.boundary()[patchI], DimensionedField::null(), patchFieldInterpolator ( boundaryAddressing_[patchI] ) ) ); } // Create the complete field from the pieces tmp> ttoF ( new GeometricField ( IOobject ( "interpolated(" + fromVf.name() + ')', toMesh_.time().timeName(), toMesh_, IOobject::NO_READ, IOobject::NO_WRITE ), toMesh_, fromVf.dimensions(), internalField, patchFields ) ); return ttoF; } template Foam::tmp> Foam::meshToMesh0::interpolate ( const tmp>& tfromVf, meshToMesh0::order ord, const CombineOp& cop ) const { tmp> tint = interpolate(tfromVf(), ord, cop); tfromVf.clear(); return tint; } // ************************************************************************* //