diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index efcd5f0047..43a832506c 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -224,6 +224,9 @@ $(derivedFvPatchFields)/plenumPressure/plenumPressureFvPatchScalarField.C $(derivedFvPatchFields)/interfaceCompression/interfaceCompressionFvPatchScalarField.C $(derivedFvPatchFields)/swirlFanVelocity/swirlFanVelocityFvPatchField.C +$(derivedFvPatchFields)/mappedField/Sampled/makeSampledPatchFunction1s.C + + fvsPatchFields = fields/fvsPatchFields $(fvsPatchFields)/fvsPatchField/fvsPatchFields.C diff --git a/src/finiteVolume/fields/fvPatchFields/derived/mappedField/Sampled/Sampled.C b/src/finiteVolume/fields/fvPatchFields/derived/mappedField/Sampled/Sampled.C new file mode 100644 index 0000000000..130337d0c8 --- /dev/null +++ b/src/finiteVolume/fields/fvPatchFields/derived/mappedField/Sampled/Sampled.C @@ -0,0 +1,353 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ 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 "fvMesh.H" +#include "volFields.H" +#include "interpolationCell.H" + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +template +Type Foam::PatchFunction1Types::Sampled::getAverage +( + const dictionary& dict, + const bool mandatory +) +{ + if (mandatory) + { + return dict.get("average"); + } + + return Zero; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template +Foam::PatchFunction1Types::Sampled::Sampled +( + const polyPatch& pp, + const word& type, + const word& entryName, + const dictionary& dict, + const bool faceValues +) +: + PatchFunction1(pp, entryName, dict, faceValues), + mappedPatchBase(pp, dict), + fieldName_(dict.get("field")), + setAverage_(dict.lookupOrDefault("setAverage", false)), + average_(getAverage(dict, setAverage_)), + interpolationScheme_(interpolationCell::typeName) +{ + if (this->mode() == mappedPatchBase::NEARESTCELL) + { + dict.readEntry("interpolationScheme", interpolationScheme_); + } +} + + +template +Foam::PatchFunction1Types::Sampled::Sampled +( + const Sampled& ut +) +: + PatchFunction1(ut), + mappedPatchBase(ut), + fieldName_(ut.fieldName_), + setAverage_(ut.setAverage_), + average_(ut.average_), + interpolationScheme_(ut.interpolationScheme_) +{} + + +template +Foam::PatchFunction1Types::Sampled::Sampled +( + const Sampled& ut, + const polyPatch& pp +) +: + PatchFunction1(ut, pp), + mappedPatchBase(pp, ut), + fieldName_(ut.fieldName_), + setAverage_(ut.setAverage_), + average_(ut.average_), + interpolationScheme_(ut.interpolationScheme_) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template +const Foam::GeometricField& +Foam::PatchFunction1Types::Sampled::sampleField() const +{ + typedef GeometricField fieldType; + + if (this->sameRegion()) + { + const polyMesh& thisMesh = + this->mappedPatchBase::patch_.boundaryMesh().mesh(); + return thisMesh.template lookupObject(fieldName_); + } + else + { + const fvMesh& nbrMesh = refCast(this->sampleMesh()); + return nbrMesh.template lookupObject(fieldName_); + } +} + + +template +bool Foam::PatchFunction1Types::Sampled::haveSampleField() const +{ + typedef GeometricField fieldType; + + if (this->sameRegion()) + { + const polyMesh& thisMesh = + this->mappedPatchBase::patch_.boundaryMesh().mesh(); + return thisMesh.template foundObject(fieldName_); + } + else + { + const fvMesh& nbrMesh = refCast(this->sampleMesh()); + return nbrMesh.template foundObject(fieldName_); + } +} + + +template +Foam::tmp> +Foam::PatchFunction1Types::Sampled::value +( + const scalar x +) const +{ + typedef GeometricField fieldType; + + // Since we're inside initEvaluate/evaluate there might be processor + // comms underway. Change the tag we use. + int oldTag = UPstream::msgType(); + UPstream::msgType() = oldTag + 1; + + const fvMesh& thisMesh = refCast + ( + this->mappedPatchBase::patch_.boundaryMesh().mesh() + ); + const fvMesh& nbrMesh = refCast(this->sampleMesh()); + + + // Result of obtaining remote values + auto tnewValues = tmp>::New(); + auto& newValues = tnewValues.ref(); + + if (!haveSampleField()) + { + // Restore tag + UPstream::msgType() = oldTag; + newValues.setSize(this->mappedPatchBase::patch_.size()); + newValues = Zero; + return this->transform(tnewValues); + } + + switch (this->mode()) + { + case mappedPatchBase::NEARESTCELL: + { + const mapDistribute& distMap = this->map(); + + if (interpolationScheme_ != interpolationCell::typeName) + { + // Send back sample points to the processor that holds the cell + vectorField samples(this->samplePoints()); + distMap.reverseDistribute + ( + ( + this->sameRegion() + ? thisMesh.nCells() + : nbrMesh.nCells() + ), + point::max, + samples + ); + + auto interpolator = + interpolation::New + ( + interpolationScheme_, + sampleField() + ); + + const auto& interp = *interpolator; + + newValues.setSize(samples.size(), pTraits::max); + forAll(samples, celli) + { + if (samples[celli] != point::max) + { + newValues[celli] = interp.interpolate + ( + samples[celli], + celli + ); + } + } + } + else + { + newValues = sampleField(); + } + distMap.distribute(newValues); + + break; + } + case mappedPatchBase::NEARESTPATCHFACE: + case mappedPatchBase::NEARESTPATCHFACEAMI: + { + const label nbrPatchID = + nbrMesh.boundaryMesh().findPatchID(this->samplePatch()); + + if (nbrPatchID < 0) + { + FatalErrorInFunction + << "Unable to find sample patch " << this->samplePatch() + << " in region " << this->sampleRegion() + << " for patch " << this->mappedPatchBase::patch_.name() << nl + << abort(FatalError); + } + + const fieldType& nbrField = sampleField(); + + newValues = nbrField.boundaryField()[nbrPatchID]; + this->distribute(newValues); + + break; + } + case mappedPatchBase::NEARESTFACE: + { + Field allValues(nbrMesh.nFaces(), Zero); + + const fieldType& nbrField = sampleField(); + + for (const fvPatchField& pf : nbrField.boundaryField()) + { + label faceStart = pf.patch().start(); + + forAll(pf, facei) + { + allValues[faceStart++] = pf[facei]; + } + } + + this->distribute(allValues); + newValues.transfer(allValues); + + break; + } + default: + { + FatalErrorInFunction + << "Unknown sampling mode: " << this->mode() << nl + << abort(FatalError); + } + } + + // Enforce average. Either by scaling (if scaling factor > 0.5) or by + // offsetting. + if (setAverage_ && returnReduce(newValues.size(), sumOp