/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2020-2021 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 "mappedMixedFvPatchField.H" #include "volFields.H" #include "interpolationCell.H" #include "mappedFixedValueFvPatchField.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template Foam::mappedMixedFvPatchField::mappedMixedFvPatchField ( const fvPatch& p, const DimensionedField& iF ) : mixedFvPatchField(p, iF), mappedPatchFieldBase ( mappedFixedValueFvPatchField::mapper(p, iF), *this ), weightFieldName_() { this->refValue() = Zero; this->refGrad() = Zero; this->valueFraction() = 0.0; } template Foam::mappedMixedFvPatchField::mappedMixedFvPatchField ( const fvPatch& p, const DimensionedField& iF, const dictionary& dict ) : // Bypass dictionary constructor (all reading handled later) // but cannot use NO_READ since will still trigger an evaluate() mixedFvPatchField(p, iF), mappedPatchFieldBase ( mappedFixedValueFvPatchField::mapper(p, iF), *this, dict ), weightFieldName_(dict.getOrDefault("weightField", word::null)) { fvPatchFieldBase::readDict(dict); // Consistent with a dict constructor this->readValueEntry(dict, IOobjectOption::MUST_READ); if (this->readMixedEntries(dict)) { // Full restart } else { // Start from user entered data. Assume fixedValue. this->refValue() = *this; this->refGrad() = Zero; this->valueFraction() = 1.0; } // This blocks (crashes) with more than two worlds! // /// // Store patch value as initial guess when running in database mode /// mappedPatchFieldBase::initRetrieveField /// ( /// this->internalField().name(), /// *this /// ); /// mappedPatchFieldBase::initRetrieveField /// ( /// this->internalField().name() + "_weights", /// this->patch().deltaCoeffs() /// ); } template Foam::mappedMixedFvPatchField::mappedMixedFvPatchField ( const mappedMixedFvPatchField& ptf, const fvPatch& p, const DimensionedField& iF, const fvPatchFieldMapper& mapper ) : mixedFvPatchField(ptf, p, iF, mapper), mappedPatchFieldBase ( mappedFixedValueFvPatchField::mapper(p, iF), *this, ptf ), weightFieldName_(ptf.weightFieldName_) {} template Foam::mappedMixedFvPatchField::mappedMixedFvPatchField ( const mappedMixedFvPatchField& ptf ) : mixedFvPatchField(ptf), mappedPatchFieldBase(ptf), weightFieldName_(ptf.weightFieldName_) {} template Foam::mappedMixedFvPatchField::mappedMixedFvPatchField ( const mappedMixedFvPatchField& ptf, const DimensionedField& iF ) : mixedFvPatchField(ptf, iF), mappedPatchFieldBase ( mappedFixedValueFvPatchField::mapper(ptf.patch(), iF), *this, ptf ), weightFieldName_(ptf.weightFieldName_) {} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template void Foam::mappedMixedFvPatchField::autoMap(const fvPatchFieldMapper& m) { mixedFvPatchField::autoMap(m); } template void Foam::mappedMixedFvPatchField::rmap ( const fvPatchField& ptf, const labelList& addr ) { mixedFvPatchField::rmap(ptf, addr); } template void Foam::mappedMixedFvPatchField::updateCoeffs() { if (this->updated()) { return; } const tmp> nbrIntFld(this->mappedInternalField()); //- Unweighted //const tmp nbrKDelta(this->mappedWeightField()); //- Weighted tmp myKDelta; tmp nbrKDelta; this->mappedWeightField(weightFieldName_, myKDelta, nbrKDelta); // Both sides agree on // - temperature : (myKDelta*fld + nbrKDelta*nbrFld)/(myKDelta+nbrKDelta) // - gradient : (temperature-fld)*delta // We've got a degree of freedom in how to implement this in a mixed bc. // (what gradient, what fixedValue and mixing coefficient) // Two reasonable choices: // 1. specify above temperature on one side (preferentially the high side) // and above gradient on the other. So this will switch between pure // fixedvalue and pure fixedgradient // 2. specify gradient and temperature such that the equations are the // same on both sides. This leads to the choice of // - refGradient = zero gradient // - refValue = neighbour value // - mixFraction = nbrKDelta / (nbrKDelta + myKDelta()) this->refValue() = nbrIntFld; this->refGrad() = Zero; this->valueFraction() = nbrKDelta()/(nbrKDelta() + myKDelta()); mixedFvPatchField::updateCoeffs(); if (debug) { auto limits = gMinMax(*this); auto avg = gAverage(*this); Info<< this->patch().boundaryMesh().mesh().name() << ':' << this->patch().name() << ':' << this->internalField().name() << " <- " << this->mapper_.sampleRegion() << ':' << this->mapper_.samplePatch() << ':' << this->fieldName_ << " :" << " value " << " min:" << limits.min() << " max:" << limits.max() << " avg:" << avg << endl; } } template void Foam::mappedMixedFvPatchField::write(Ostream& os) const { mappedPatchFieldBase::write(os); os.writeEntryIfDifferent("weightField", word::null, weightFieldName_); mixedFvPatchField::write(os); } // ************************************************************************* //