Foam::tmp<Foam::volScalarField> Foam::XiEqModels::basicSubGrid::XiEq() const { const fvMesh& mesh = Su_.mesh(); const volVectorField& U = mesh.lookupObject<volVectorField>("U"); const volScalarField& Nv = mesh.lookupObject<volScalarField>("Nv"); const volSymmTensorField& nsv = mesh.lookupObject<volSymmTensorField>("nsv"); volScalarField magU(mag(U)); volVectorField Uhat ( U/(mag(U) + dimensionedScalar("Usmall", U.dimensions(), 1e-4)) ); const scalarField Cw = pow(mesh.V(), 2.0/3.0); tmp<volScalarField> tN ( new volScalarField ( IOobject ( "tN", mesh.time().constant(), mesh, IOobject::NO_READ, IOobject::NO_WRITE ), mesh, dimensionedScalar("zero", Nv.dimensions(), 0.0), zeroGradientFvPatchVectorField::typeName ) ); volScalarField& N = tN(); N.internalField() = Nv.internalField()*Cw; tmp<volSymmTensorField> tns ( new volSymmTensorField ( IOobject ( "tns", U.mesh().time().timeName(), U.mesh(), IOobject::NO_READ, IOobject::NO_WRITE ), U.mesh(), dimensionedSymmTensor ( "zero", nsv.dimensions(), pTraits<symmTensor>::zero ), zeroGradientFvPatchSymmTensorField::typeName ) ); volSymmTensorField& ns = tns(); ns.internalField() = nsv.internalField()*Cw; volScalarField n(max(N - (Uhat & ns & Uhat), scalar(1e-4))); volScalarField b((Uhat & B_ & Uhat)/sqrt(n)); volScalarField up(sqrt((2.0/3.0)*turbulence_.k())); volScalarField XiSubEq ( scalar(1) + max(2.2*sqrt(b), min(0.34*magU/up*sqrt(b), scalar(1.6))) * min(n, scalar(1)) ); return (XiSubEq*XiEqModel_->XiEq()); }
// solve vegetation model void modifiedVegetationModel::solve(volVectorField& U, volScalarField& T, volScalarField& w) { // solve radiation within vegetation radiation(); const double p_ = 101325; // Magnitude of velocity volScalarField magU("magU", mag(U)); // Bounding velocity bound(magU, UMin_); // solve aerodynamic, stomatal resistance volScalarField new_Tl("new_Tl", Tl_); // info Info << " max leaf temp tl=" << max(T.internalField()) << "k, iteration i=0" << endl; scalar maxError, maxRelError; int i; // solve leaf temperature, iteratively. int maxIter = 500; for (i=1; i<=maxIter; i++) { // Solve aerodynamc, stomatal resistance resistance(magU, T, w, new_Tl); forAll(LAD_, cellI) { if (LAD_[cellI] > 10*SMALL) { // Initial leaf temperature if (i==1) Tl_[cellI];// = T[cellI];//*0. + 300.;//T[cellI]; // Calculate saturated density, specific humidity rhosat_[cellI] = calc_rhosat(Tl_[cellI]); evsat_[cellI] = calc_evsat(Tl_[cellI]); wsat_[cellI] = 0.621945*(evsat_[cellI]/(p_-evsat_[cellI])); // ASHRAE 1, eq.23 // Calculate transpiration rate]); E_[cellI] = nEvapSides_.value()*LAD_[cellI]*rhoa_.value()*(wsat_[cellI]-w[cellI])/(ra_[cellI]+rs_[cellI]); //E_[cellI] = 0.0; // No evapotranspiration // Calculate latent heat flux Ql_[cellI] = lambda_.value()*E_[cellI]; // Calculate new leaf temperature new_Tl[cellI] = T[cellI] + (Rn_[cellI] - Ql_[cellI])*(ra_[cellI]/(2.0*rhoa_.value()*cpa_.value()*LAD_[cellI])); } } // info Info << " max leaf temp tl=" << gMax(new_Tl.internalField()) << " K, iteration i=" << i << endl; // Check rel. L-infinity error maxError = gMax(mag(new_Tl.internalField()-Tl_.internalField())); maxRelError = maxError/gMax(mag(new_Tl.internalField())); // update leaf temp. forAll(Tl_, cellI) Tl_[cellI] = 0.5*Tl_[cellI]+0.5*new_Tl[cellI]; // convergence check if (maxRelError < 1e-8) break; } Tl_.correctBoundaryConditions(); // Iteration info Info << "Vegetation model: Solving for Tl, Final residual = " << maxError << ", Final relative residual = " << maxRelError << ", No Iterations " << i << endl; Info << "temperature parameters: max Tl = " << gMax(Tl_) << ", min T = " << gMin(T) << ", max T = " << gMax(T) << endl; Info << "resistances: max rs = " << gMax(rs_) << ", max ra = " << gMax(ra_) << endl; // Final: Solve aerodynamc, stomatal resistance resistance(magU, T, w, Tl_); // Final: Update sensible and latent heat flux forAll(LAD_, cellI) { if (LAD_[cellI] > 10*SMALL) { // Calculate saturated density, specific humidity rhosat_[cellI] = calc_rhosat(Tl_[cellI]); evsat_[cellI] = calc_evsat(Tl_[cellI]); wsat_[cellI] = 0.621945*(evsat_[cellI]/(p_-evsat_[cellI])); // ASHRAE 1, eq.23 // Calculate transpiration rate E_[cellI] = nEvapSides_.value()*LAD_[cellI]*rhoa_.value()*(wsat_[cellI]-w[cellI])/(ra_[cellI]+rs_[cellI]); // todo: implement switch for double or single side // Calculate latent heat flux Ql_[cellI] = lambda_.value()*E_[cellI]; // Calculate sensible heat flux Qs_[cellI] = 2.0*rhoa_.value()*cpa_.value()*LAD_[cellI]*(Tl_[cellI]-T[cellI])/ra_[cellI]; } } rhosat_.correctBoundaryConditions(); wsat_.correctBoundaryConditions(); E_.correctBoundaryConditions(); Ql_.correctBoundaryConditions(); Qs_.correctBoundaryConditions(); }