Exemple #1
0
void calcYPlus
(
    const TurbulenceModel& turbulenceModel,
    const fvMesh& mesh,
    const volVectorField& U,
    volScalarField& yPlus
)
{
    volScalarField::GeometricBoundaryField d = nearWallDist(mesh).y();

    const volScalarField::GeometricBoundaryField nutBf =
        turbulenceModel->nut()().boundaryField();

    const volScalarField::GeometricBoundaryField nuEffBf =
        turbulenceModel->nuEff()().boundaryField();

    const volScalarField::GeometricBoundaryField nuBf =
        turbulenceModel->nu()().boundaryField();

    const fvPatchList& patches = mesh.boundary();

    forAll(patches, patchi)
    {
        const fvPatch& patch = patches[patchi];

        if (isA<nutWallFunctionFvPatchScalarField>(nutBf[patchi]))
        {
            const nutWallFunctionFvPatchScalarField& nutPf =
                dynamic_cast<const nutWallFunctionFvPatchScalarField&>
                (
                    nutBf[patchi]
                );

            yPlus.boundaryField()[patchi] = nutPf.yPlus();
            const scalarField& Yp = yPlus.boundaryField()[patchi];

            Info<< "Patch " << patchi
                << " named " << nutPf.patch().name()
                << ", wall-function " << nutPf.type()
                << ", y+ : min: " << gMin(Yp) << " max: " << gMax(Yp)
                << " average: " << gAverage(Yp) << nl << endl;
        }
        else if (isA<wallFvPatch>(patch))
        {
            yPlus.boundaryField()[patchi] =
                d[patchi]
               *sqrt
                (
                    nuEffBf[patchi]
                   *mag(U.boundaryField()[patchi].snGrad())
                )/nuBf[patchi];
            const scalarField& Yp = yPlus.boundaryField()[patchi];

            Info<< "Patch " << patchi
                << " named " << patch.name()
                << " y+ : min: " << gMin(Yp) << " max: " << gMax(Yp)
                << " average: " << gAverage(Yp) << nl << endl;
        }
    }
}
Exemple #2
0
STATIC void makeNonOverlapHalfStep(register int j, register int nglay,
   double qcsq[], double rough[], double mu[], double zint, double rufint)
{
      gd[nglay] = zint * rough[j];
   gqcsq[nglay] = gAverage(qcsq, j, rufint);
    gmu[nglay] = gAverage(  mu, j, rufint);
}
int main(int argc, char *argv[])
{
    
    #include "postProcess.H"
    #include "setRootCase.H"
    #include "createTime.H"
    #include "createMesh.H"
    #include "createControl.H"

    label inlet  = mesh.boundaryMesh().findPatchID("Inlet"); 
    label outlet = mesh.boundaryMesh().findPatchID("Outlet");

    #include "createFields.H"
    #include "createFvOptions.H"
    #include "initContinuityErrs.H"

    turbulence->validate();

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //


    Info<< "\nStarting Iteration loop\n" << endl;
    
    while (simple.loop())
    {
        Info<< "Iteration Number = " << runTime.timeName() << nl << endl;

        // Pressure-velocity SIMPLE corrector
        {
            #include "UEqn.H"
            #include "EEqn.H"
            #include "pEqn.H"
        }
        
        turbulence->correct();

        runTime.write();

        Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"  << "  ClockTime = " << runTime.elapsedClockTime() << " s"  << endl;

        Info<< "Inflow      : "   << -1.0* gSum( phi.boundaryField()[inlet]  )   <<" [kg/s]" << endl;
        Info<< "Outflow     : "   <<       gSum( phi.boundaryField()[outlet] )  <<" [kg/s]" <<  endl;
        Info<< "EnergyInflow  : " << -1.0* gSum( phi.boundaryField()[inlet]  * ( thermo.he().boundaryField()[inlet]  +  0.5*magSqr(U.boundaryField()[inlet])  ) )   <<" [W]" <<  endl;
        Info<< "EnergyOutflow : " <<       gSum( phi.boundaryField()[outlet] * ( thermo.he().boundaryField()[outlet] +  0.5*magSqr(U.boundaryField()[outlet]) ) )   <<" [W]" <<  endl;   
        Info<< "EnergyBalance : " <<       gSum( phi.boundaryField()[outlet] * ( thermo.he().boundaryField()[outlet] +  0.5*magSqr(U.boundaryField()[outlet]) ) ) 
                                     +1.0* gSum( phi.boundaryField()[inlet]  * ( thermo.he().boundaryField()[inlet]  +  0.5*magSqr(U.boundaryField()[inlet])  ) )   <<" [W]" <<  endl;

        Info<< "rho max/avg/min : " << gMax(thermo.rho())   << " " << gAverage(thermo.rho())    << " " << gMin(thermo.rho())   << endl;
        Info<< "T   max/avg/min : " << gMax(thermo.T())     << " " << gAverage(thermo.T())      << " " << gMin(thermo.T())     << endl;
        Info<< "P   max/avg/min : " << gMax(thermo.p())     << " " << gAverage(thermo.p())      << " " << gMin(thermo.p())     << endl;
        Info<< "Prg max/avg/min : " << gMax(p_rgh)          << " " << gAverage(p_rgh)           << " " << gMin(p_rgh)          << endl;
        Info<< "U   max/avg/min : " << gMax(U).component(2) << " " << gAverage(U).component(2)  << " " << gMin(U).component(2) << endl;
        Info<< "Prg max-min : "  << gMax(p_rgh)  -  gMin(p_rgh) << endl;      
        Info<< " " << endl;
    }

    Info<< "End\n" << endl;

    return 0;
}
Exemple #4
0
void gensub(double qcsq[], double d[], double rough[], double mu[],
            int nlayer, double zint[], double rufint[], int nrough)
{

#include <parameters.h>
#include <glayd.h>
#include <glayi.h>

   int i;

   /* Correct bogus input */
   if (rough[nlayer] < 1.e-10) rough[nlayer] = 1.e-10;

   /* Check for funny number of layers */
   if (nlayer < 1) {
      nglay = 0;
      puts("/** NLAYER must be positive **/");
   } else {
      register int midpoint = nrough / 2 + 1;

      /* Evaluate substrate gradation */
      for (i = 0; i <= nrough - midpoint; i++) {
            gd[nglay] = zint[i + midpoint] * rough[nlayer];
         gqcsq[nglay] = gAverage(qcsq, nlayer, rufint[i + midpoint]);
           gmu[nglay] = gAverage(  mu, nlayer, rufint[i + midpoint]);
         nglay++;
      }
      gqcsq[nglay] = qcsq[nlayer];
        gmu[nglay] =   mu[nlayer];
         gd[nglay] =    d[nlayer];
      nglay++;
   }
}
void Foam::porousBafflePressureFvPatchField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    const surfaceScalarField& phi =
            db().lookupObject<surfaceScalarField>(phiName_);

    const fvsPatchField<scalar>& phip =
        patch().patchField<surfaceScalarField, scalar>(phi);

    scalarField Un(phip/patch().magSf());

    if (phi.dimensions() == dimDensity*dimVelocity*dimArea)
    {
        Un /= patch().lookupPatchField<volScalarField, scalar>(rhoName_);
    }

    scalarField magUn(mag(Un));

    const turbulenceModel& turbModel = db().lookupObject<turbulenceModel>
    (
        IOobject::groupName
        (
            turbulenceModel::propertiesName,
            internalField().group()
        )
    );

    jump_ =
        -sign(Un)
        *(
            D_*turbModel.nu(patch().index())
          + I_*0.5*magUn
         )*magUn*length_;

    if (internalField().dimensions() == dimPressure)
    {
        jump_ *= patch().lookupPatchField<volScalarField, scalar>(rhoName_);
    }

    if (debug)
    {
        scalar avePressureJump = gAverage(jump_);
        scalar aveVelocity = gAverage(mag(Un));

        Info<< patch().boundaryMesh().mesh().name() << ':'
            << patch().name() << ':'
            << " Average pressure drop :" << avePressureJump
            << " Average velocity :" << aveVelocity
            << endl;
    }

    fixedJumpFvPatchField<scalar>::updateCoeffs();
}
void Foam::bound(volScalarField& vsf, const dimensionedScalar& vsf0)
{
    scalar minVsf = min(vsf).value();

    if (minVsf < vsf0.value())
    {
        Info<< "bounding " << vsf.name()
            << ", min: " << gMin(vsf.internalField())
            << " max: " << gMax(vsf.internalField())
            << " average: " << gAverage(vsf.internalField())
            << endl;

        vsf.internalField() = max
        (
            max
            (
                vsf.internalField(),
                fvc::average(max(vsf, vsf0))().internalField()
                // Bug fix: was assuming bound on zero.  HJ, 25/Nov/2008
                *pos(vsf0.value() - vsf.internalField())
            ),
            vsf0.value()
        );

        vsf.correctBoundaryConditions();
        vsf.boundaryField() = max(vsf.boundaryField(), vsf0.value());
    }
}
void Foam::solidWallHeatFluxTemperatureFvPatchScalarField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    gradient() = q_/K();

    fixedGradientFvPatchScalarField::updateCoeffs();

    if (debug)
    {
        scalar Q = gSum(K()*patch().magSf()*snGrad());

        Info<< patch().boundaryMesh().mesh().name() << ':'
            << patch().name() << ':'
            << this->dimensionedInternalField().name() << " :"
            << " heatFlux:" << Q
            << " walltemperature "
            << " min:" << gMin(*this)
            << " max:" << gMax(*this)
            << " avg:" << gAverage(*this)
            << endl;
    }
}
Exemple #8
0
Foam::scalar Foam::lduMatrix::solver::normFactor
(
    const scalarField& x,
    const scalarField& b,
    const scalarField& Ax,
    scalarField& tmpField,
    const direction cmpt
) const
{
    // Calculate A dot reference value of x
//     matrix_.sumA(tmpField, coupleBouCoeffs_, interfaces_);
//     tmpField *= gAverage(x);

    // Calculate normalisation factor using full multiplication
    // with mean value.  HJ, 5/Nov/2007
    scalar xRef = gAverage(x);
    matrix_.Amul
    (
        tmpField,
        scalarField(x.size(), xRef),
        coupleBouCoeffs_,
        interfaces_,
        cmpt
    );

    return gSum(mag(Ax - tmpField) + mag(b - tmpField)) + matrix_.small_;

    // At convergence this simpler method is equivalent to the above
    // return 2*gSumMag(b) + matrix_.small_;
}
void Foam::boundMinMax
(
    volScalarField& vsf,
    const dimensionedScalar& vsf0,
    const dimensionedScalar& vsf1
)
{
    scalar minVsf = min(vsf).value();
    scalar maxVsf = max(vsf).value();

    if (minVsf < vsf0.value() || maxVsf > vsf1.value())
    {
        Info<< "bounding " << vsf.name()
            << ", min: " << gMin(vsf.internalField())
            << " max: " << gMax(vsf.internalField())
            << " average: " << gAverage(vsf.internalField())
            << endl;
    }

    if (minVsf < vsf0.value())
    {
        vsf.internalField() = max
        (
            max
            (
                vsf.internalField(),
                fvc::average(max(vsf, vsf0))().internalField()
                *pos(vsf0.value() - vsf.internalField())
            ),
            vsf0.value()
        );

        vsf.correctBoundaryConditions();
        vsf.boundaryField() = max(vsf.boundaryField(), vsf0.value());
    }

    if (maxVsf > vsf1.value())
    {
        vsf.internalField() = min
        (
            min
            (
                vsf.internalField(),
                fvc::average(min(vsf, vsf1))().internalField()
                *neg(vsf1.value() - vsf.internalField())
                // This is needed when all values are above max
                // HJ, 18/Apr/2009
              + pos(vsf1.value() - vsf.internalField())*vsf1.value()
            ),
            vsf1.value()
        );

        vsf.correctBoundaryConditions();
        vsf.boundaryField() = min(vsf.boundaryField(), vsf1.value());
    }
}
void Foam::yPlusRAS::calcIncompressibleYPlus
(
    const fvMesh& mesh,
    volScalarField& yPlus
)
{
    typedef incompressible::nutWallFunctionFvPatchScalarField
        wallFunctionPatchField;

    const incompressible::RASModel& model =
        mesh.lookupObject<incompressible::RASModel>("RASProperties");

    const volScalarField nut(model.nut());
    const volScalarField::GeometricBoundaryField& nutPatches =
        nut.boundaryField();

    bool foundPatch = false;
    forAll(nutPatches, patchI)
    {
        if (isA<wallFunctionPatchField>(nutPatches[patchI]))
        {
            foundPatch = true;

            const wallFunctionPatchField& nutPw =
                dynamic_cast<const wallFunctionPatchField&>(nutPatches[patchI]);

            yPlus.boundaryField()[patchI] = nutPw.yPlus();
            const scalarField& Yp = yPlus.boundaryField()[patchI];

            scalar minYp = gMin(Yp);
            scalar maxYp = gMax(Yp);
            scalar avgYp = gAverage(Yp);

            if (log_)
            {
                Info<< "    patch " << nutPw.patch().name()
                    << " y+ : min = " << minYp << ", max = " << maxYp
                    << ", average = " << avgYp << nl;
            }

            if (Pstream::master())
            {
                file() << obr_.time().value() << token::TAB
                    << nutPw.patch().name() << token::TAB
                    << minYp << token::TAB << maxYp << token::TAB
                    << avgYp << endl;
            }
        }
    }

    if (log_ && !foundPatch)
    {
        Info<< "    no " << wallFunctionPatchField::typeName << " patches"
            << endl;
    }
}
dimensioned<Type> DimensionedField<Type, GeoMesh>::average() const
{
    dimensioned<Type> Average
    (
        this->name() + ".average()",
        this->dimensions(),
        gAverage(field())
    );

    return Average;
}
Exemple #12
0
void calcIncompressibleYPlus
(
    const fvMesh& mesh,
    const Time& runTime,
    const volVectorField& U,
    volScalarField& yPlus
)
{
    typedef incompressible::RASModels::nutWallFunctionFvPatchScalarField
        wallFunctionPatchField;

    #include "createPhi.H"

    singlePhaseTransportModel laminarTransport(U, phi);

    autoPtr<incompressible::RASModel> RASModel
    (
        incompressible::RASModel::New(U, phi, laminarTransport)
    );

    const volScalarField::GeometricBoundaryField nutPatches =
        RASModel->nut()().boundaryField();

    bool foundNutPatch = false;
    forAll(nutPatches, patchi)
    {
        if (isA<wallFunctionPatchField>(nutPatches[patchi]))
        {
            foundNutPatch = true;

            const wallFunctionPatchField& nutPw =
                dynamic_cast<const wallFunctionPatchField&>
                    (nutPatches[patchi]);

            yPlus.boundaryField()[patchi] = nutPw.yPlus();
            const scalarField& Yp = yPlus.boundaryField()[patchi];

            Info<< "Patch " << patchi
                << " named " << nutPw.patch().name()
                << " y+ : min: " << gMin(Yp) << " max: " << gMax(Yp)
                << " average: " << gAverage(Yp) << nl << endl;
        }
    }

    if (!foundNutPatch)
    {
        Info<< "    no " << wallFunctionPatchField::typeName << " patches"
            << endl;
    }
}
Exemple #13
0
bool Foam::functionObjects::yPlus::write(const bool postProcess)
{
    const volScalarField& yPlus =
        obr_.lookupObject<volScalarField>(type());

    Log << type() << " " << name() << " write:" << nl
        << "    writing field " << yPlus.name() << endl;

    yPlus.write();

    writeFiles::write();

    const volScalarField::Boundary& yPlusBf = yPlus.boundaryField();

    const fvMesh& mesh = refCast<const fvMesh>(obr_);
    const fvPatchList& patches = mesh.boundary();

    forAll(patches, patchi)
    {
        const fvPatch& patch = patches[patchi];

        if (isA<wallFvPatch>(patch))
        {
            const scalarField& yPlusp = yPlusBf[patchi];

            const scalar minYplus = gMin(yPlusp);
            const scalar maxYplus = gMax(yPlusp);
            const scalar avgYplus = gAverage(yPlusp);

            if (Pstream::master())
            {
                Log << "    patch " << patch.name()
                    << " y+ : min = " << minYplus << ", max = " << maxYplus
                    << ", average = " << avgYplus << nl;

                writeTime(file());
                file()
                << token::TAB << patch.name()
                    << token::TAB << minYplus
                    << token::TAB << maxYplus
                    << token::TAB << avgYplus
                    << endl;
            }
        }
    }

    return true;
}
Exemple #14
0
bool Foam::functionObjects::yPlus::write()
{
    Log << type() << " " << name() << " write:" << nl;

    writeLocalObjects::write();

    logFiles::write();

    const volScalarField& yPlus =
        mesh_.lookupObject<volScalarField>(type());

    const volScalarField::Boundary& yPlusBf = yPlus.boundaryField();
    const fvPatchList& patches = mesh_.boundary();

    forAll(patches, patchi)
    {
        const fvPatch& patch = patches[patchi];

        if (isA<wallFvPatch>(patch))
        {
            const scalarField& yPlusp = yPlusBf[patchi];

            const scalar minYplus = gMin(yPlusp);
            const scalar maxYplus = gMax(yPlusp);
            const scalar avgYplus = gAverage(yPlusp);

            if (Pstream::master())
            {
                Log << "    patch " << patch.name()
                    << " y+ : min = " << minYplus << ", max = " << maxYplus
                    << ", average = " << avgYplus << nl;

                writeTime(file());
                file()
                    << token::TAB << patch.name()
                    << token::TAB << minYplus
                    << token::TAB << maxYplus
                    << token::TAB << avgYplus
                    << endl;
            }
        }
    }

    Log << endl;

    return true;
}
Foam::scalar Foam::lduMatrix::solver::normFactor
(
    const scalarField& psi,
    const scalarField& source,
    const scalarField& Apsi,
    scalarField& tmpField
) const
{
    // --- Calculate A dot reference value of psi
    matrix_.sumA(tmpField, interfaceBouCoeffs_, interfaces_);
    tmpField *= gAverage(psi);

    return gSum(mag(Apsi - tmpField) + mag(source - tmpField)) + matrix_.small_;

    // At convergence this simpler method is equivalent to the above
    // return 2*gSumMag(source) + matrix_.small_;
}
Exemple #16
0
void writeData(
    CommonValueExpressionDriver &driver,
    const wordList &accumulations
)
{
    bool isPoint=driver.result().isPoint();

    Field<T> result(driver.getResult<T>(isPoint));

    forAll(accumulations,i) {
        const word &aName=accumulations[i];
        const NumericAccumulationNamedEnum::value accu=
            NumericAccumulationNamedEnum::names[aName];

        T val=pTraits<T>::zero;

        switch(accu) {
            case NumericAccumulationNamedEnum::numMin:
                val=gMin(result);
                break;
            case NumericAccumulationNamedEnum::numMax:
                val=gMax(result);
                break;
            case NumericAccumulationNamedEnum::numSum:
                val=gSum(result);
                break;
            case NumericAccumulationNamedEnum::numAverage:
                val=gAverage(result);
                break;
            // case NumericAccumulationNamedEnum::numSumMag:
            //     val=gSumMag(result);
            //     break;
            case NumericAccumulationNamedEnum::numWeightedAverage:
                val=driver.calcWeightedAverage(result);
                break;
            default:
                WarningIn("funkyDoCalc")
                    << "Unimplemented accumultation type "
                        << NumericAccumulationNamedEnum::names[accu]
                        << ". Currently only 'min', 'max', 'sum', 'weightedAverage' and 'average' are supported"
                        << endl;
        }

        Info << " " << aName << "=" << val;
    }
}
void swakExpressionFunctionObject::writeData(CommonValueExpressionDriver &driver)
{
    Field<T> result=driver.getResult<T>();

    Field<T> results(accumulations_.size());

    forAll(accumulations_,i) {
        const word &aName=accumulations_[i];
        T val=pTraits<T>::zero;

        if(aName=="min") {
            val=gMin(result);
        } else if(aName=="max") {
            val=gMax(result);
        } else if(aName=="sum") {
            val=gSum(result);
        } else if(aName=="average") {
            val=gAverage(result);
        } else {
            WarningIn("swakExpressionFunctionObject::writeData")
                << "Unknown accumultation type " << aName
                    << ". Currently only 'min', 'max', 'sum' and 'average' are supported"
                    << endl;
        }
        results[i]=val;
        if(verbose()) {
            Info << " " << aName << "=" << val;
        }
    }

    if (Pstream::master()) {
        unsigned int w = IOstream::defaultPrecision() + 7;
        
        OFstream& o=*filePtrs_[name()];
        
        o << setw(w) << time().value();
        forAll(results,i) {
            o << setw(w) << results[i];
        }
        o << nl;
    }
void Foam::radiation::greyDiffusiveViewFactorFixedValueFvPatchScalarField::
updateCoeffs()
{
    //Do nothing

    if (debug)
    {
        scalar Q = gSum((*this)*patch().magSf());

        Info<< patch().boundaryMesh().mesh().name() << ':'
            << patch().name() << ':'
            << this->dimensionedInternalField().name() << " <- "
            << " heat[W]:" << Q
            << " wall radiative heat flux "
            << " min:" << gMin(*this)
            << " max:" << gMax(*this)
            << " avg:" << gAverage(*this)
            << endl;
    }

}
void Foam::mappedFieldFvPatchField<Type>::updateCoeffs()
{
    if (this->updated())
    {
        return;
    }

    this->operator==(this->mappedField());

    if (debug)
    {
        Info<< "operating on field:" << this->dimensionedInternalField().name()
            << " patch:" << this->patch().name()
            << "  avg:" << gAverage(*this)
            << "  min:" << gMin(*this)
            << "  max:" << gMax(*this)
            << endl;
    }

    fixedValueFvPatchField<Type>::updateCoeffs();
}
Foam::scalar Foam::BlockIterativeSolver<Type>::normFactor
(
    Field<Type>& x,
    const Field<Type>& b
) const
{
    const BlockLduMatrix<Type>& matrix = this->matrix_;

    // Calculate the normalisation factor
    const label nRows = x.size();

    Field<Type> pA(nRows);
    Field<Type> wA(nRows);

    // Calculate reference value of x
    Type xRef = gAverage(x);

    // Calculate A.x
    matrix.Amul(wA, x);

    // Calculate A.xRef, temporarily using pA for storage
    matrix.Amul
    (
        pA,
        Field<Type>(nRows, xRef)
    );

    scalar normFactor = gSum(mag(wA - pA) + mag(b - pA)) + this->small_;

    if (BlockLduMatrix<Type>::debug >= 2)
    {
        Info<< "Iterative solver normalisation factor = "
            << normFactor << endl;
    }

    return normFactor;
}
void Foam::solidWallMixedTemperatureCoupledFvPatchScalarField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    // Get the coupling information from the directMappedPatchBase
    const directMappedPatchBase& mpp = refCast<const directMappedPatchBase>
    (
        patch().patch()
    );
    const polyMesh& nbrMesh = mpp.sampleMesh();
    const fvPatch& nbrPatch = refCast<const fvMesh>
    (
        nbrMesh
    ).boundary()[mpp.samplePolyPatch().index()];

    // Force recalculation of mapping and schedule
    const mapDistribute& distMap = mpp.map();

    tmp<scalarField> intFld = patchInternalField();


    const solidWallMixedTemperatureCoupledFvPatchScalarField& nbrField =
    refCast<const solidWallMixedTemperatureCoupledFvPatchScalarField>
    (
        nbrPatch.lookupPatchField<volScalarField, scalar>
        (
            neighbourFieldName_
        )
    );

    // Swap to obtain full local values of neighbour internal field
    scalarField nbrIntFld = nbrField.patchInternalField();
    mapDistribute::distribute
    (
        Pstream::defaultCommsType,
        distMap.schedule(),
        distMap.constructSize(),
        distMap.subMap(),           // what to send
        distMap.constructMap(),     // what to receive
        nbrIntFld
    );

    // Swap to obtain full local values of neighbour K*delta
    scalarField nbrKDelta = nbrField.K()*nbrPatch.deltaCoeffs();
    mapDistribute::distribute
    (
        Pstream::defaultCommsType,
        distMap.schedule(),
        distMap.constructSize(),
        distMap.subMap(),           // what to send
        distMap.constructMap(),     // what to receive
        nbrKDelta
    );

    tmp<scalarField> myKDelta = K()*patch().deltaCoeffs();


    // 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() = 0.0;

    this->valueFraction() = nbrKDelta / (nbrKDelta + myKDelta());

    mixedFvPatchScalarField::updateCoeffs();


    if (debug)
    {
        scalar Q = gSum(K()*patch().magSf()*snGrad());

        Info<< patch().boundaryMesh().mesh().name() << ':'
            << patch().name() << ':'
            << this->dimensionedInternalField().name() << " <- "
            << nbrMesh.name() << ':'
            << nbrPatch.name() << ':'
            << this->dimensionedInternalField().name() << " :"
            << " heat[W]:" << Q
            << " walltemperature "
            << " min:" << gMin(*this)
            << " max:" << gMax(*this)
            << " avg:" << gAverage(*this)
            << endl;
    }
}
void thermalBaffle1DFvPatchScalarField<solidType>::updateCoeffs()
{
    if (updated())
    {
        return;
    }
    // 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 mapDistribute& mapDist = this->mappedPatchBase::map();

    const label patchi = patch().index();

    const label nbrPatchi = samplePolyPatch().index();

    if (baffleActivated_)
    {
        const fvPatch& nbrPatch = patch().boundaryMesh()[nbrPatchi];

        const compressible::turbulenceModel& turbModel =
            db().template lookupObject<compressible::turbulenceModel>
            (
                "turbulenceModel"
            );

        // local properties
        const scalarField kappaw(turbModel.kappaEff(patchi));

        const fvPatchScalarField& Tp =
            patch().template lookupPatchField<volScalarField, scalar>(TName_);


        scalarField Qr(Tp.size(), 0.0);

        if (QrName_ != "none")
        {
            Qr = patch().template lookupPatchField<volScalarField, scalar>
                (QrName_);

            Qr = QrRelaxation_*Qr + (1.0 - QrRelaxation_)*QrPrevious_;
            QrPrevious_ = Qr;
        }

        tmp<scalarField> Ti = patchInternalField();

        scalarField myKDelta(patch().deltaCoeffs()*kappaw);

        // nrb properties
        scalarField nbrTp =
            turbModel.thermo().T().boundaryField()[nbrPatchi];
        mapDist.distribute(nbrTp);

        // solid properties
        scalarField kappas(patch().size(), 0.0);
        forAll(kappas, i)
        {
            kappas[i] = solid().kappa(0.0, (Tp[i] + nbrTp[i])/2.0);
        }

        const scalarField KDeltaSolid(kappas/baffleThickness());

        const scalarField alpha(KDeltaSolid - Qr/Tp);

        valueFraction() = alpha/(alpha + myKDelta);

        refValue() = (KDeltaSolid*nbrTp + Qs()/2.0)/alpha;

        if (debug)
        {
            scalar Q = gAverage(kappaw*snGrad());
            Info<< patch().boundaryMesh().mesh().name() << ':'
                << patch().name() << ':'
                << this->dimensionedInternalField().name() << " <- "
                << nbrPatch.name() << ':'
                << this->dimensionedInternalField().name() << " :"
                << " heat[W]:" << Q
                << " walltemperature "
                << " min:" << gMin(*this)
                << " max:" << gMax(*this)
                << " avg:" << gAverage(*this)
                << endl;
        }
    }
void Foam::timeVaryingMappedFixedValuePointPatchField<Type>::updateCoeffs()
{
    if (this->updated())
    {
        return;
    }

    checkTable();

    // Interpolate between the sampled data

    Type wantedAverage;

    if (endSampleTime_ == -1)
    {
        // only start value
        if (debug)
        {
            Pout<< "updateCoeffs : Sampled, non-interpolated values"
                << " from start time:"
                << sampleTimes_[startSampleTime_].name() << nl;
        }

        this->operator==(startSampledValues_);
        wantedAverage = startAverage_;
    }
    else
    {
        scalar start = sampleTimes_[startSampleTime_].value();
        scalar end = sampleTimes_[endSampleTime_].value();

        scalar s = (this->db().time().value()-start)/(end-start);

        if (debug)
        {
            Pout<< "updateCoeffs : Sampled, interpolated values"
                << " between start time:"
                << sampleTimes_[startSampleTime_].name()
                << " and end time:" << sampleTimes_[endSampleTime_].name()
                << " with weight:" << s << endl;
        }

        this->operator==((1-s)*startSampledValues_ + s*endSampledValues_);
        wantedAverage = (1-s)*startAverage_ + s*endAverage_;
    }

    // Enforce average. Either by scaling (if scaling factor > 0.5) or by
    // offsetting.
    if (setAverage_)
    {
        const Field<Type>& fld = *this;

        Type averagePsi = gAverage(fld);

        if (debug)
        {
            Pout<< "updateCoeffs :"
                << " actual average:" << averagePsi
                << " wanted average:" << wantedAverage
                << endl;
        }

        if (mag(averagePsi) < VSMALL)
        {
            // Field too small to scale. Offset instead.
            const Type offset = wantedAverage - averagePsi;
            if (debug)
            {
                Pout<< "updateCoeffs :"
                    << " offsetting with:" << offset << endl;
            }
            this->operator==(fld+offset);
        }
        else
        {
            const scalar scale = mag(wantedAverage)/mag(averagePsi);

            if (debug)
            {
                Pout<< "updateCoeffs :"
                    << " scaling with:" << scale << endl;
            }
            this->operator==(scale*fld);
        }
    }

    // apply offset to mapped values
    if (offset_.valid())
    {
        const scalar t = this->db().time().timeOutputValue();
        this->operator==(*this + offset_->value(t));
    }

    if (debug)
    {
        Pout<< "updateCoeffs : set fixedValue to min:" << gMin(*this)
            << " max:" << gMax(*this)
            << " avg:" << gAverage(*this) << endl;
    }

    fixedValuePointPatchField<Type>::updateCoeffs();
}
void turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    // 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;

    // Get the coupling information from the mappedPatchBase
    const mappedPatchBase& mpp =
        refCast<const mappedPatchBase>(patch().patch());
    const polyMesh& nbrMesh = mpp.sampleMesh();
    const label samplePatchi = mpp.samplePolyPatch().index();
    const fvPatch& nbrPatch =
        refCast<const fvMesh>(nbrMesh).boundary()[samplePatchi];

    // Calculate the temperature by harmonic averaging
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    const turbulentTemperatureCoupledBaffleMixedFvPatchScalarField& nbrField =
    refCast
    <
        const turbulentTemperatureCoupledBaffleMixedFvPatchScalarField
    >
    (
        nbrPatch.lookupPatchField<volScalarField, scalar>
        (
            TnbrName_
        )
    );

    // Swap to obtain full local values of neighbour internal field
    tmp<scalarField> nbrIntFld(new scalarField(nbrField.size(), 0.0));
    tmp<scalarField> nbrKDelta(new scalarField(nbrField.size(), 0.0));

    if (contactRes_ == 0.0)
    {
        nbrIntFld.ref() = nbrField.patchInternalField();
        nbrKDelta.ref() = nbrField.kappa(nbrField)*nbrPatch.deltaCoeffs();
    }
    else
    {
        nbrIntFld.ref() = nbrField;
        nbrKDelta.ref() = contactRes_;
    }

    mpp.distribute(nbrIntFld.ref());
    mpp.distribute(nbrKDelta.ref());

    tmp<scalarField> myKDelta = kappa(*this)*patch().deltaCoeffs();


    // 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() = 0.0;
    this->valueFraction() = nbrKDelta()/(nbrKDelta() + myKDelta());

    mixedFvPatchScalarField::updateCoeffs();

    if (debug)
    {
        scalar Q = gSum(kappa(*this)*patch().magSf()*snGrad());

        Info<< patch().boundaryMesh().mesh().name() << ':'
            << patch().name() << ':'
            << this->internalField().name() << " <- "
            << nbrMesh.name() << ':'
            << nbrPatch.name() << ':'
            << this->internalField().name() << " :"
            << " heat transfer rate:" << Q
            << " walltemperature "
            << " min:" << gMin(*this)
            << " max:" << gMax(*this)
            << " avg:" << gAverage(*this)
            << endl;
    }

    // Restore tag
    UPstream::msgType() = oldTag;
}
void Foam::porousBafflePressureFvPatchField<Foam::scalar>::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    const label patchI = patch().index();

    const surfaceScalarField& phi =
            db().lookupObject<surfaceScalarField>("phi");

    const fvsPatchField<scalar>& phip =
        patch().patchField<surfaceScalarField, scalar>(phi);

    scalarField Un(phip/patch().magSf());

    scalarField magUn(mag(Un));

    if (phi.dimensions() == dimensionSet(0, 3, -1, 0, 0))
    {
        const incompressible::turbulenceModel& turbModel =
            db().lookupObject<incompressible::turbulenceModel>
            (
                "turbulenceModel"
            );

        const scalarField nuEffw = turbModel.nuEff()().boundaryField()[patchI];

        jump_ = -sign(Un)*(I_*nuEffw + D_*0.5*magUn*length_)*magUn;
    }
    else
    {
        const compressible::turbulenceModel& turbModel =
            db().lookupObject<compressible::turbulenceModel>
            (
                "turbulenceModel"
            );

        const scalarField muEffw = turbModel.muEff()().boundaryField()[patchI];

        const scalarField rhow =
            patch().lookupPatchField<volScalarField, scalar>("rho");

        Un /= rhow;

        jump_ = -sign(Un)*(I_*muEffw + D_*0.5*rhow*magUn*length_)*magUn;
    }

    if (debug)
    {
        scalar avePressureJump = gAverage(jump_);
        scalar aveVelocity = gAverage(mag(Un));

        Info<< patch().boundaryMesh().mesh().name() << ':'
            << patch().name() << ':'
            << " Average pressure drop :" << avePressureJump
            << " Average velocity :" << aveVelocity
            << endl;
    }

    fixedJumpFvPatchField<scalar>::updateCoeffs();
}
int main(int argc, char *argv[])
{
    argList::validOptions.insert("ybl", "scalar");
    argList::validOptions.insert("Cbl", "scalar");
    argList::validOptions.insert("writenut", "");

#   include "setRootCase.H"

#   include "createTime.H"
#   include "createMesh.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

    Info<< "Reading field U\n" << endl;
    volVectorField U
    (
        IOobject
        (
            "U",
            runTime.timeName(),
            mesh,
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        ),
        mesh
    );

#   include "createPhi.H"

    Info<< "Calculating wall distance field" << endl;
    volScalarField y = wallDist(mesh).y();

    // Set the mean boundary-layer thickness
    dimensionedScalar ybl("ybl", dimLength, 0);

    if (args.options().found("ybl"))
    {
        // If the boundary-layer thickness is provided use it
        ybl.value() = readScalar(IStringStream(args.options()["ybl"])());
    }
    else if (args.options().found("Cbl"))
    {
        // Calculate boundary layer thickness as Cbl * mean distance to wall
        ybl.value() =
            gAverage(y)*readScalar(IStringStream(args.options()["Cbl"])());
    }
    else
    {
        FatalErrorIn(args.executable())
            << "Neither option 'ybl' or 'Cbl' have been provided to calculate"
               " the boundary-layer thickness"
            << exit(FatalError);
    }

    Info<< "\nCreating boundary-layer for U of thickness "
        << ybl.value() << " m" << nl << endl;

    // Modify velocity by applying a 1/7th power law boundary-layer
    // u/U0 = (y/ybl)^(1/7)
    // assumes U0 is the same as the current cell velocity

    scalar yblv = ybl.value();
    forAll(U, celli)
    {
        if (y[celli] <= yblv)
        {
            U[celli] *= ::pow(y[celli]/yblv, (1.0/7.0));
        }
    }

    Info<< "Writing U" << endl;
    U.write();

    // Update/re-write phi
    phi = fvc::interpolate(U) & mesh.Sf();
    phi.write();

    // Set turbulence constants
    dimensionedScalar kappa("kappa", dimless, 0.4187);
    dimensionedScalar Cmu("Cmu", dimless, 0.09);

    // Read and modify turbulence fields if present

    IOobject epsilonHeader
    (
        "epsilon",
        runTime.timeName(),
        mesh,
        IOobject::MUST_READ
    );

    IOobject kHeader
    (
        "k",
        runTime.timeName(),
        mesh,
        IOobject::MUST_READ
    );

    IOobject nuTildaHeader
    (
        "nuTilda",
        runTime.timeName(),
        mesh,
        IOobject::MUST_READ
    );

    // First calculate nut
    volScalarField nut
    (
        "nut",
        sqr(kappa*min(y, ybl))*::sqrt(2)*mag(dev(symm(fvc::grad(U))))
    );

    if (args.options().found("writenut"))
    {
        Info<< "Writing nut" << endl;
        nut.write();
    }


    // Read and modify turbulence fields if present

    if (nuTildaHeader.headerOk())
    {
        Info<< "Reading field nuTilda\n" << endl;
        volScalarField nuTilda(nuTildaHeader, mesh);
        nuTilda = nut;
        nuTilda.correctBoundaryConditions();

        Info<< "Writing nuTilda\n" << endl;
        nuTilda.write();
    }

    if (kHeader.headerOk() && epsilonHeader.headerOk())
    {
        Info<< "Reading field k\n" << endl;
        volScalarField k(kHeader, mesh);

        Info<< "Reading field epsilon\n" << endl;
        volScalarField epsilon(epsilonHeader, mesh);

        scalar ck0 = ::pow(Cmu.value(), 0.25)*kappa.value();
        k = sqr(nut/(ck0*min(y, ybl)));
        k.correctBoundaryConditions();

        scalar ce0 = ::pow(Cmu.value(), 0.75)/kappa.value();
        epsilon = ce0*k*sqrt(k)/min(y, ybl);
        epsilon.correctBoundaryConditions();

        Info<< "Writing k\n" << endl;
        k.write();

        Info<< "Writing epsilon\n" << endl;
        epsilon.write();
    }

    Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
        << "  ClockTime = " << runTime.elapsedClockTime() << " s"
        << nl << endl;

    Info<< "End\n" << endl;

    return(0);
}
void thermalBaffle1DFvPatchScalarField<solidType>::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    // 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 mappedPatchBase& mpp =
        refCast<const mappedPatchBase>(patch().patch());

    const label patchi = patch().index();

    const label nbrPatchi = mpp.samplePolyPatch().index();

    if (baffleActivated_)
    {
        const fvPatch& nbrPatch = patch().boundaryMesh()[nbrPatchi];

        const compressible::turbulenceModel& turbModel =
            db().template lookupObject<compressible::turbulenceModel>
            (
                "turbulenceModel"
            );

        // local properties

        const scalarField kappaw(turbModel.kappaEff(patchi));

        const fvPatchScalarField& Tp =
            patch().template lookupPatchField<volScalarField, scalar>(TName_);

        const scalarField qDot(kappaw*Tp.snGrad());

        tmp<scalarField> Ti = patchInternalField();

        scalarField myh(patch().deltaCoeffs()*kappaw);

        // nbr properties

        const scalarField nbrKappaw(turbModel.kappaEff(nbrPatchi));

        const fvPatchScalarField& nbrTw =
            turbModel.thermo().T().boundaryField()[nbrPatchi];

        scalarField nbrQDot(nbrKappaw*nbrTw.snGrad());
        mpp.map().distribute(nbrQDot);

        const thermalBaffle1DFvPatchScalarField& nbrField =
        refCast<const thermalBaffle1DFvPatchScalarField>
        (
            nbrPatch.template lookupPatchField<volScalarField, scalar>(TName_)
        );

        scalarField nbrTi(nbrField.patchInternalField());
        mpp.map().distribute(nbrTi);

        scalarField nbrTp =
           nbrPatch.template lookupPatchField<volScalarField, scalar>(TName_);
        mpp.map().distribute(nbrTp);

        scalarField nbrh(nbrPatch.deltaCoeffs()*nbrKappaw);
        mpp.map().distribute(nbrh);


        // heat source
        const scalarField Q(Qs_/thickness_);

        tmp<scalarField> tKDeltaw(new scalarField(patch().size()));
        scalarField KDeltaw = tKDeltaw();

        // Create fields for solid properties (p paramater not used)
        forAll(KDeltaw, i)
        {
            KDeltaw[i] =
                solidPtr_().kappa(0.0, (Tp[i] + nbrTw[i])/2.0)/thickness_[i];
        }

        const scalarField q
        (
            (Ti() - nbrTi)/(1.0/KDeltaw + 1.0/nbrh + 1.0/myh)
        );

        forAll(qDot, i)
        {
            if (Qs_[i] == 0)
            {
                this->refValue()[i] = Ti()[i] - q[i]/myh[i];
                this->refGrad()[i] = 0.0;
                this->valueFraction()[i] = 1.0;
            }
            else
            {
                if (q[i] > 0)
                {
                    this->refValue()[i] =
                        nbrTp[i]
                      - Q[i]*thickness_[i]/(2*KDeltaw[i]);

                    this->refGrad()[i] = 0.0;
                    this->valueFraction()[i] =
                        1.0
                        /
                        (
                            1.0
                          + patch().deltaCoeffs()[i]*kappaw[i]/KDeltaw[i]
                        );
                }
                else if (q[i] < 0)
                {
                    this->refValue()[i] = 0.0;
                    this->refGrad()[i] =
                          (-nbrQDot[i] + Q[i]*thickness_[i])/kappaw[i];
                    this->valueFraction()[i] = 0.0;
                }
                else
                {
                    scalar Qt = Q[i]*thickness_[i];
                    this->refValue()[i] = 0.0;
                    this->refGrad()[i] = Qt/2/kappaw[i];
                    this->valueFraction()[i] = 0.0;
                }
            }
        }

        if (debug)
        {
            scalar Q = gSum(patch().magSf()*qDot);
            Info<< patch().boundaryMesh().mesh().name() << ':'
                << patch().name() << ':'
                << this->dimensionedInternalField().name() << " <- "
                << nbrPatch.name() << ':'
                << this->dimensionedInternalField().name() << " :"
                << " heat[W]:" << Q
                << " walltemperature "
                << " min:" << gMin(*this)
                << " max:" << gMax(*this)
                << " avg:" << gAverage(*this)
                << endl;
        }
    }
void filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    // Get the coupling information from the mappedPatchBase
    const mappedPatchBase& mpp =
        refCast<const mappedPatchBase>(patch().patch());

    const label patchI = patch().index();
    const label nbrPatchI = mpp.samplePolyPatch().index();
    const polyMesh& mesh = patch().boundaryMesh().mesh();
    const polyMesh& nbrMesh = mpp.sampleMesh();
    const fvPatch& nbrPatch =
        refCast<const fvMesh>(nbrMesh).boundary()[nbrPatchI];

    scalarField intFld(patchInternalField());

    const filmPyrolysisRadiativeCoupledMixedFvPatchScalarField&
        nbrField =
        refCast
        <
            const filmPyrolysisRadiativeCoupledMixedFvPatchScalarField
        >
        (
            nbrPatch.lookupPatchField<volScalarField, scalar>(TnbrName_)
        );

    // Swap to obtain full local values of neighbour internal field
    scalarField nbrIntFld(nbrField.patchInternalField());
    mpp.distribute(nbrIntFld);

    scalarField& Tp = *this;

    const scalarField K(this->kappa(*this));
    const scalarField nbrK(nbrField.kappa(*this));

    // Swap to obtain full local values of neighbour K*delta
    scalarField KDeltaNbr(nbrK*nbrPatch.deltaCoeffs());
    mpp.distribute(KDeltaNbr);

    scalarField myKDelta(K*patch().deltaCoeffs());

    scalarList Tfilm(patch().size(), 0.0);
    scalarList htcwfilm(patch().size(), 0.0);
    scalarList filmDelta(patch().size(), 0.0);

    const pyrolysisModelType& pyrolysis = pyrModel();
    const filmModelType& film = filmModel();

    // Obtain Rad heat (Qr)
    scalarField Qr(patch().size(), 0.0);

    label coupledPatchI = -1;
    if (pyrolysisRegionName_ == mesh.name())
    {
        coupledPatchI = patchI;
        if (QrName_ != "none")
        {
            Qr = nbrPatch.lookupPatchField<volScalarField, scalar>(QrName_);
            mpp.distribute(Qr);
        }
    }
    else if (pyrolysis.primaryMesh().name() == mesh.name())
    {
        coupledPatchI = nbrPatch.index();
        if (QrName_ != "none")
        {
            Qr = patch().lookupPatchField<volScalarField, scalar>(QrName_);
        }
    }
    else
    {
        FatalErrorIn
        (
            "void filmPyrolysisRadiativeCoupledMixedFvPatchScalarField::"
            "updateCoeffs()"
        )
            << type() << " condition is intended to be applied to either the "
            << "primary or pyrolysis regions only"
            << exit(FatalError);
    }

    const label filmPatchI = pyrolysis.nbrCoupledPatchID(film, coupledPatchI);

    const scalarField htcw(film.htcw().h()().boundaryField()[filmPatchI]);

    // Obtain htcw
    htcwfilm =
        pyrolysis.mapRegionPatchField
        (
            film,
            coupledPatchI,
            filmPatchI,
            htcw,
            true
        );


    // Obtain Tfilm at the boundary through Ts.
    // NOTE: Tf is not good as at the boundary it will retrieve Tp
    Tfilm = film.Ts().boundaryField()[filmPatchI];
    film.toPrimary(filmPatchI, Tfilm);

    // Obtain delta
    filmDelta =
        pyrolysis.mapRegionPatchField<scalar>
        (
            film,
            "deltaf",
            coupledPatchI,
            true
        );

     // Estimate wetness of the film (1: wet , 0: dry)
     scalarField ratio
     (
        min
        (
            max
            (
                (filmDelta - filmDeltaDry_)/(filmDeltaWet_ - filmDeltaDry_),
                scalar(0.0)
            ),
            scalar(1.0)
        )
     );

    scalarField qConv(ratio*htcwfilm*(Tfilm - Tp)*convectiveScaling_);

    scalarField qRad((1.0 - ratio)*Qr);

    scalarField alpha(KDeltaNbr - (qRad + qConv)/Tp);

    valueFraction() = alpha/(alpha + (1.0 - ratio)*myKDelta);

    refValue() = ratio*Tfilm + (1.0 - ratio)*(KDeltaNbr*nbrIntFld)/alpha;

    mixedFvPatchScalarField::updateCoeffs();

    if (debug)
    {
        scalar Qc = gSum(qConv*patch().magSf());
        scalar Qr = gSum(qRad*patch().magSf());
        scalar Qt = gSum((qConv + qRad)*patch().magSf());

        Info<< mesh.name() << ':'
            << patch().name() << ':'
            << this->dimensionedInternalField().name() << " <- "
            << nbrMesh.name() << ':'
            << nbrPatch.name() << ':'
            << this->dimensionedInternalField().name() << " :" << nl
            << "     convective heat[W] : " << Qc << nl
            << "     radiative heat [W] : " << Qr << nl
            << "     total heat     [W] : " << Qt << nl
            << "     wall temperature "
            << " min:" << gMin(*this)
            << " max:" << gMax(*this)
            << " avg:" << gAverage(*this)
            << endl;
    }
}
void turbulentTemperatureRadCoupledMixedFvPatchScalarField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    // 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;

    // Get the coupling information from the mappedPatchBase
    const mappedPatchBase& mpp =
        refCast<const mappedPatchBase>(patch().patch());
    const polyMesh& nbrMesh = mpp.sampleMesh();
    const label samplePatchi = mpp.samplePolyPatch().index();
    const fvPatch& nbrPatch =
        refCast<const fvMesh>(nbrMesh).boundary()[samplePatchi];


    scalarField Tc(patchInternalField());
    scalarField& Tp = *this;

    const turbulentTemperatureRadCoupledMixedFvPatchScalarField&
        nbrField = refCast
            <const turbulentTemperatureRadCoupledMixedFvPatchScalarField>
            (
                nbrPatch.lookupPatchField<volScalarField, scalar>(TnbrName_)
            );

    // Swap to obtain full local values of neighbour internal field
    scalarField TcNbr(nbrField.patchInternalField());
    mpp.distribute(TcNbr);


    // Swap to obtain full local values of neighbour K*delta
    scalarField KDeltaNbr;
    if (contactRes_ == 0.0)
    {
        KDeltaNbr = nbrField.kappa(nbrField)*nbrPatch.deltaCoeffs();
    }
    else
    {
        KDeltaNbr.setSize(nbrField.size(), contactRes_);
    }
    mpp.distribute(KDeltaNbr);

    scalarField KDelta(kappa(Tp)*patch().deltaCoeffs());

    scalarField Qr(Tp.size(), 0.0);
    if (QrName_ != "none")
    {
        Qr = patch().lookupPatchField<volScalarField, scalar>(QrName_);
    }

    scalarField QrNbr(Tp.size(), 0.0);
    if (QrNbrName_ != "none")
    {
        QrNbr = nbrPatch.lookupPatchField<volScalarField, scalar>(QrNbrName_);
        mpp.distribute(QrNbr);
    }

    valueFraction() = KDeltaNbr/(KDeltaNbr + KDelta);
    refValue() = TcNbr;
    refGrad() = (Qr + QrNbr)/kappa(Tp);

    mixedFvPatchScalarField::updateCoeffs();

    if (debug)
    {
        scalar Q = gSum(kappa(Tp)*patch().magSf()*snGrad());

        Info<< patch().boundaryMesh().mesh().name() << ':'
            << patch().name() << ':'
            << this->internalField().name() << " <- "
            << nbrMesh.name() << ':'
            << nbrPatch.name() << ':'
            << this->internalField().name() << " :"
            << " heat transfer rate:" << Q
            << " walltemperature "
            << " min:" << gMin(Tp)
            << " max:" << gMax(Tp)
            << " avg:" << gAverage(Tp)
            << endl;
    }

    // Restore tag
    UPstream::msgType() = oldTag;
}
void Foam::yPlus::calcYPlus
(
    const TurbulenceModel& turbulenceModel,
    const fvMesh& mesh,
    volScalarField& yPlus
)
{
    volScalarField::GeometricBoundaryField d = nearWallDist(mesh).y();

    const volScalarField::GeometricBoundaryField nutBf =
        turbulenceModel.nut()().boundaryField();

    const volScalarField::GeometricBoundaryField nuEffBf =
        turbulenceModel.nuEff()().boundaryField();

    const volScalarField::GeometricBoundaryField nuBf =
        turbulenceModel.nu()().boundaryField();

    const fvPatchList& patches = mesh.boundary();

    forAll(patches, patchi)
    {
        const fvPatch& patch = patches[patchi];

        if (isA<nutWallFunctionFvPatchScalarField>(nutBf[patchi]))
        {
            const nutWallFunctionFvPatchScalarField& nutPf =
                dynamic_cast<const nutWallFunctionFvPatchScalarField&>
                (
                    nutBf[patchi]
                );

            yPlus.boundaryField()[patchi] = nutPf.yPlus();
            const scalarField& yPlusp = yPlus.boundaryField()[patchi];

            const scalar minYplus = gMin(yPlusp);
            const scalar maxYplus = gMax(yPlusp);
            const scalar avgYplus = gAverage(yPlusp);

            if (Pstream::master())
            {
                if (log_) Info
                    << "    patch " << patch.name()
                    << " y+ : min = " << minYplus << ", max = " << maxYplus
                    << ", average = " << avgYplus << nl;

                file() << obr_.time().value()
                    << token::TAB << patch.name()
                    << token::TAB << minYplus
                    << token::TAB << maxYplus
                    << token::TAB << avgYplus
                    << endl;
            }
        }
        else if (isA<wallFvPatch>(patch))
        {
            yPlus.boundaryField()[patchi] =
                d[patchi]
               *sqrt
                (
                    nuEffBf[patchi]
                   *mag(turbulenceModel.U().boundaryField()[patchi].snGrad())
                )/nuBf[patchi];
            const scalarField& yPlusp = yPlus.boundaryField()[patchi];

            const scalar minYplus = gMin(yPlusp);
            const scalar maxYplus = gMax(yPlusp);
            const scalar avgYplus = gAverage(yPlusp);

            if (Pstream::master())
            {
                if (log_) Info
                    << "    patch " << patch.name()
                    << " y+ : min = " << minYplus << ", max = " << maxYplus
                    << ", average = " << avgYplus << nl;

                file() << obr_.time().value()
                    << token::TAB << patch.name()
                    << token::TAB << minYplus
                    << token::TAB << maxYplus
                    << token::TAB << avgYplus
                    << endl;
            }
        }
    }
}