Beispiel #1
0
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
limitedSnGrad<Type>::correction
(
    const GeometricField<Type, fvPatchField, volMesh>& vf
) const
{
    const GeometricField<Type, fvsPatchField, surfaceMesh> corr
    (
        correctedScheme_().correction(vf)
    );

    const surfaceScalarField limiter
    (
        min
        (
            limitCoeff_
           *mag(snGradScheme<Type>::snGrad(vf, deltaCoeffs(vf), "SndGrad"))
           /(
                (1 - limitCoeff_)*mag(corr)
              + dimensionedScalar("small", corr.dimensions(), SMALL)
            ),
            dimensionedScalar("one", dimless, 1.0)
        )
    );

    if (fv::debug)
    {
        InfoInFunction
            << "limiter min: " << min(limiter.primitiveField())
            << " max: "<< max(limiter.primitiveField())
            << " avg: " << average(limiter.primitiveField()) << endl;
    }

    return limiter*corr;
}
Beispiel #2
0
tmp<surfaceInterpolationScheme<Type> > scheme
(
    const surfaceScalarField& faceFlux,
    const word& name
)
{
    return surfaceInterpolationScheme<Type>::New
    (
        faceFlux.mesh(),
        faceFlux,
        faceFlux.mesh().interpolationScheme(name)
    );
}
Beispiel #3
0
Foam::combustionModel::combustionModel
(
    const dictionary& combustionProperties,
    const hsCombustionThermo& thermo,
    const compressible::turbulenceModel& turbulence,
    const surfaceScalarField& phi,
    const volScalarField& rho
)
:
    combustionModelCoeffs_
    (
        combustionProperties.subDict
        (
            word(combustionProperties.lookup("combustionModel")) + "Coeffs"
        )
    ),
    thermo_(thermo),
    turbulence_(turbulence),
    mesh_(phi.mesh()),
    phi_(phi),
    rho_(rho),
    stoicRatio_(thermo.lookup("stoichiometricAirFuelMassRatio")),
    s_(thermo.lookup("stoichiometricOxygenFuelMassRatio")),
    qFuel_(thermo_.lookup("qFuel")),
    composition_(thermo.composition())
{}
void Foam::MRFZone::makeRelativeRhoFlux
(
    const RhoFieldType& rho,
    surfaceScalarField& phi
) const
{
    if (!active_)
    {
        return;
    }

    const surfaceVectorField& Cf = mesh_.Cf();
    const surfaceVectorField& Sf = mesh_.Sf();

    const vector Omega = omega_->value(mesh_.time().timeOutputValue())*axis_;

    const vectorField& Cfi = Cf;
    const vectorField& Sfi = Sf;
    scalarField& phii = phi.primitiveFieldRef();

    // Internal faces
    forAll(internalFaces_, i)
    {
        label facei = internalFaces_[i];
        phii[facei] -= rho[facei]*(Omega ^ (Cfi[facei] - origin_)) & Sfi[facei];
    }
Beispiel #5
0
tmp<fvMatrix<Type> >
div
(
    const surfaceScalarField& flux,
    const GeometricField<Type, fvPatchField, volMesh>& vf
)
{
    return fvm::div(flux, vf, "div("+flux.name()+','+vf.name()+')');
}
Beispiel #6
0
tmp<GeometricField<Type, fvPatchField, volMesh> >
DDt
(
    const surfaceScalarField& phi,
    const GeometricField<Type, fvPatchField, volMesh>& psi
)
{
    tmp<GeometricField<Type, fvPatchField, volMesh> > ddtDivPhiPsi
        = fvc::ddt(psi) + fvc::div(phi, psi);

    if (phi.mesh().moving())
    {
        return ddtDivPhiPsi - fvc::div(phi + phi.mesh().phi())*psi;
    }
    else
    {
        return ddtDivPhiPsi - fvc::div(phi)*psi;
    }
}
Beispiel #7
0
void Foam::fvc::makeAbsolute
(
    surfaceScalarField& phi,
    const volVectorField& U
)
{
    if (phi.mesh().moving())
    {
        phi += fvc::meshPhi(U);
    }
}
Beispiel #8
0
void Foam::fvc::makeRelative
(
    surfaceScalarField& phi,
    const volVectorField& U
)
{
    if (phi.mesh().moving())
    {
        phi -= fvc::meshPhi(U);
    }
}
Beispiel #9
0
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
flux
(
    const surfaceScalarField& phi,
    const GeometricField<Type, fvPatchField, volMesh>& vf
)
{
    return fvc::flux
    (
        phi, vf, "flux("+phi.name()+','+vf.name()+')'
    );
}
Beispiel #10
0
void Foam::fvc::makeRelative
(
    surfaceScalarField& phi,
    const dimensionedScalar& rho,
    const volVectorField& U
)
{
    if (phi.mesh().moving())
    {
        phi -= rho*fvc::meshPhi(rho, U);
    }
}
Beispiel #11
0
//JK interpolate(rho) is declared but not defined
void Foam::fvc::makeAbsolute
(
    surfaceScalarField& phi,
    const volScalarField& rho,
    const volVectorField& U
)
{
    if (phi.mesh().moving())
    {
        phi += fvc::interpolate(rho)*fvc::meshPhi(rho, U);
    }
}
Beispiel #12
0
tmp<surfaceInterpolationScheme<Type> > scheme
(
    const surfaceScalarField& faceFlux,
    Istream& streamData
)
{
    return surfaceInterpolationScheme<Type>::New
    (
        faceFlux.mesh(),
        faceFlux,
        streamData
    );
}
Beispiel #13
0
void Foam::phaseModel::correctInflowOutflow(surfaceScalarField& alphaPhi) const
{
    surfaceScalarField::Boundary& alphaPhiBf = alphaPhi.boundaryFieldRef();
    const volScalarField::Boundary& alphaBf = boundaryField();
    const surfaceScalarField::Boundary& phiBf = phi()().boundaryField();

    forAll(alphaPhiBf, patchi)
    {
        fvsPatchScalarField& alphaPhip = alphaPhiBf[patchi];

        if (!alphaPhip.coupled())
        {
            alphaPhip = phiBf[patchi]*alphaBf[patchi];
        }
    }
Foam::combustionModel::combustionModel
(
    const dictionary& combustionProps,
    hsCombustionThermo& thermo,
    const compressible::turbulenceModel& turbulence,
    const surfaceScalarField& phi,
    const volScalarField& rho
)
:
    coeffs_(dictionary::null),
    thermo_(thermo),
    turbulence_(turbulence),
    mesh_(phi.mesh()),
    phi_(phi),
    rho_(rho)
{}
generalizedNewtonian<BasicTurbulenceModel>::generalizedNewtonian
(
    const alphaField& alpha,
    const rhoField& rho,
    const volVectorField& U,
    const surfaceScalarField& alphaRhoPhi,
    const surfaceScalarField& phi,
    const transportModel& transport,
    const word& propertiesName
)
:
    linearViscousStress<laminarModel<BasicTurbulenceModel>>
    (
        typeName,
        alpha,
        rho,
        U,
        alphaRhoPhi,
        phi,
        transport,
        propertiesName
    ),

    viscosityModel_
    (
        generalizedNewtonianViscosityModel::New
        (
            this->coeffDict_
        )
    ),

    nu_
    (
        IOobject
        (
            IOobject::groupName("generalizedNewtonian:nu", alphaRhoPhi.group()),
            this->runTime_.timeName(),
            this->mesh_,
            IOobject::NO_READ,
            IOobject::AUTO_WRITE
        ),
        viscosityModel_->nu(this->nu(), strainRate())
    )
{}
Beispiel #16
0
tmp<GeometricField<Type, fvPatchField, volMesh> >
noConvectionScheme<Type>::fvcDiv
(
    const surfaceScalarField& faceFlux,
    const GeometricField<Type, fvPatchField, volMesh>& vf
) const
{
    tmp<GeometricField<Type, fvPatchField, volMesh> > tConvection
    (
        fvc::surfaceIntegrate(flux(faceFlux, vf))
    );

    tConvection().rename
    (
        "convection(" + faceFlux.name() + ',' + vf.name() + ')'
    );

    return tConvection;
}
Beispiel #17
0
tmp<fvMatrix<Type> >
noConvectionScheme<Type>::fvmDiv
(
    const surfaceScalarField& faceFlux,
    GeometricField<Type, fvPatchField, volMesh>& vf
) const
{
    tmp<fvMatrix<Type> > tfvm
    (
        new fvMatrix<Type>
        (
            vf,
            faceFlux.dimensions()*vf.dimensions()
        )
    );

    // Touch diagonal for consistency
    tfvm().diag() = 0;

    return tfvm;
}
Beispiel #18
0
scalar fieldOperations::
getScalingFlowRate(const surfaceScalarField& phi)
{
  return mag( gSum(phi.boundaryField()[scalingPatchID_]) );
}
Beispiel #19
0
void Foam::MULES::implicitSolve
(
    const RhoType& rho,
    volScalarField& psi,
    const surfaceScalarField& phi,
    surfaceScalarField& phiPsi,
    const SpType& Sp,
    const SuType& Su,
    const scalar psiMax,
    const scalar psiMin
)
{
    const fvMesh& mesh = psi.mesh();

    const dictionary& MULEScontrols = mesh.solverDict(psi.name());

    label maxIter
    (
        readLabel(MULEScontrols.lookup("maxIter"))
    );

    label nLimiterIter
    (
        readLabel(MULEScontrols.lookup("nLimiterIter"))
    );

    scalar maxUnboundedness
    (
        readScalar(MULEScontrols.lookup("maxUnboundedness"))
    );

    scalar CoCoeff
    (
        readScalar(MULEScontrols.lookup("CoCoeff"))
    );

    scalarField allCoLambda(mesh.nFaces());

    {
        slicedSurfaceScalarField CoLambda
        (
            IOobject
            (
                "CoLambda",
                mesh.time().timeName(),
                mesh,
                IOobject::NO_READ,
                IOobject::NO_WRITE,
                false
            ),
            mesh,
            dimless,
            allCoLambda,
            false   // Use slices for the couples
        );

        if (phi.dimensions() == dimDensity*dimVelocity*dimArea)
        {
            tmp<surfaceScalarField> Cof =
                mesh.time().deltaT()*mesh.surfaceInterpolation::deltaCoeffs()
               *mag(phi/interpolate(rho))/mesh.magSf();

            CoLambda == 1.0/max(CoCoeff*Cof, scalar(1));
        }
        else
        {
            tmp<surfaceScalarField> Cof =
                mesh.time().deltaT()*mesh.surfaceInterpolation::deltaCoeffs()
               *mag(phi)/mesh.magSf();

            CoLambda == 1.0/max(CoCoeff*Cof, scalar(1));
        }
    }

    scalarField allLambda(allCoLambda);
    //scalarField allLambda(mesh.nFaces(), 1.0);

    slicedSurfaceScalarField lambda
    (
        IOobject
        (
            "lambda",
            mesh.time().timeName(),
            mesh,
            IOobject::NO_READ,
            IOobject::NO_WRITE,
            false
        ),
        mesh,
        dimless,
        allLambda,
        false   // Use slices for the couples
    );

    linear<scalar> CDs(mesh);
    upwind<scalar> UDs(mesh, phi);
    //fv::uncorrectedSnGrad<scalar> snGrads(mesh);

    fvScalarMatrix psiConvectionDiffusion
    (
        fvm::ddt(rho, psi)
      + fv::gaussConvectionScheme<scalar>(mesh, phi, UDs).fvmDiv(phi, psi)
        //- fv::gaussLaplacianScheme<scalar, scalar>(mesh, CDs, snGrads)
        //.fvmLaplacian(Dpsif, psi)
      - fvm::Sp(Sp, psi)
      - Su
    );

    surfaceScalarField phiBD(psiConvectionDiffusion.flux());

    surfaceScalarField& phiCorr = phiPsi;
    phiCorr -= phiBD;

    for (label i=0; i<maxIter; i++)
    {
        if (i != 0 && i < 4)
        {
            allLambda = allCoLambda;
        }

        limiter
        (
            allLambda,
            rho,
            psi,
            phiBD,
            phiCorr,
            Sp,
            Su,
            psiMax,
            psiMin,
            nLimiterIter
        );

        solve
        (
            psiConvectionDiffusion + fvc::div(lambda*phiCorr),
            MULEScontrols
        );

        scalar maxPsiM1 = gMax(psi.internalField()) - 1.0;
        scalar minPsi = gMin(psi.internalField());

        scalar unboundedness = max(max(maxPsiM1, 0.0), -min(minPsi, 0.0));

        if (unboundedness < maxUnboundedness)
        {
            break;
        }
        else
        {
            Info<< "MULES: max(" << psi.name() << " - 1) = " << maxPsiM1
                << " min(" << psi.name() << ") = " << minPsi << endl;

            phiBD = psiConvectionDiffusion.flux();

            /*
            word gammaScheme("div(phi,gamma)");
            word gammarScheme("div(phirb,gamma)");

            const surfaceScalarField& phir =
                mesh.lookupObject<surfaceScalarField>("phir");

            phiCorr =
                fvc::flux
                (
                    phi,
                    psi,
                    gammaScheme
                )
              + fvc::flux
                (
                    -fvc::flux(-phir, scalar(1) - psi, gammarScheme),
                    psi,
                    gammarScheme
                )
                - phiBD;
            */
        }
    }

    phiPsi = psiConvectionDiffusion.flux() + lambda*phiCorr;
}
void Foam::MULES::limiter
(
    scalarField& allLambda,
    const RdeltaTType& rDeltaT,
    const RhoType& rho,
    const volScalarField& psi,
    const surfaceScalarField& phiBD,
    const surfaceScalarField& phiCorr,
    const SpType& Sp,
    const SuType& Su,
    const scalar psiMax,
    const scalar psiMin
)
{
    const scalarField& psiIf = psi;
    const volScalarField::GeometricBoundaryField& psiBf = psi.boundaryField();

    const fvMesh& mesh = psi.mesh();

    const dictionary& MULEScontrols = mesh.solverDict(psi.name());

    label nLimiterIter
    (
        MULEScontrols.lookupOrDefault<label>("nLimiterIter", 3)
    );

    scalar smoothLimiter
    (
        MULEScontrols.lookupOrDefault<scalar>("smoothLimiter", 0)
    );

    const scalarField& psi0 = psi.oldTime();

    const labelUList& owner = mesh.owner();
    const labelUList& neighb = mesh.neighbour();
    tmp<volScalarField::DimensionedInternalField> tVsc = mesh.Vsc();
    const scalarField& V = tVsc();

    const scalarField& phiBDIf = phiBD;
    const surfaceScalarField::GeometricBoundaryField& phiBDBf =
        phiBD.boundaryField();

    const scalarField& phiCorrIf = phiCorr;
    const surfaceScalarField::GeometricBoundaryField& phiCorrBf =
        phiCorr.boundaryField();

    slicedSurfaceScalarField lambda
    (
        IOobject
        (
            "lambda",
            mesh.time().timeName(),
            mesh,
            IOobject::NO_READ,
            IOobject::NO_WRITE,
            false
        ),
        mesh,
        dimless,
        allLambda,
        false   // Use slices for the couples
    );

    scalarField& lambdaIf = lambda;
    surfaceScalarField::GeometricBoundaryField& lambdaBf =
        lambda.boundaryField();

    scalarField psiMaxn(psiIf.size(), psiMin);
    scalarField psiMinn(psiIf.size(), psiMax);

    scalarField sumPhiBD(psiIf.size(), 0.0);

    scalarField sumPhip(psiIf.size(), VSMALL);
    scalarField mSumPhim(psiIf.size(), VSMALL);

    forAll(phiCorrIf, facei)
    {
        label own = owner[facei];
        label nei = neighb[facei];

        psiMaxn[own] = max(psiMaxn[own], psiIf[nei]);
        psiMinn[own] = min(psiMinn[own], psiIf[nei]);

        psiMaxn[nei] = max(psiMaxn[nei], psiIf[own]);
        psiMinn[nei] = min(psiMinn[nei], psiIf[own]);

        sumPhiBD[own] += phiBDIf[facei];
        sumPhiBD[nei] -= phiBDIf[facei];

        scalar phiCorrf = phiCorrIf[facei];

        if (phiCorrf > 0.0)
        {
            sumPhip[own] += phiCorrf;
            mSumPhim[nei] += phiCorrf;
        }
        else
        {
            mSumPhim[own] -= phiCorrf;
            sumPhip[nei] -= phiCorrf;
        }
    }
tmp<errorEstimate<Type> >
div
(
    const surfaceScalarField& flux,
    const GeometricField<Type, fvPatchField, volMesh>& vf
)
{
    const fvMesh& mesh = vf.mesh();

    const scalarField& vols = mesh.V();
    const surfaceVectorField& faceCentres = mesh.Cf();
    const volVectorField& cellCentres = mesh.C();
    const fvPatchList& patches = mesh.boundary();
    const unallocLabelList& owner = mesh.owner();
    const unallocLabelList& neighbour = mesh.neighbour();

    Field<Type> res(vols.size(), pTraits<Type>::zero);
    scalarField aNorm(vols.size(), 0.0);

    // Get sign of flux
    const surfaceScalarField signF = pos(flux);

    // Calculate gradient of the solution
    GeometricField
    <
        typename outerProduct<vector, Type>::type, fvPatchField, volMesh
    > gradVf = fvc::grad(vf);

    // Internal faces
    forAll (owner, faceI)
    {
        // Calculate the centre of the face
        const vector& curFaceCentre = faceCentres[faceI];

        // Owner
        vector ownD = curFaceCentre - cellCentres[owner[faceI]];

        // Subtract convection
        res[owner[faceI]] -=
        (
            vf[owner[faceI]]
          + (ownD & gradVf[owner[faceI]])
        )*flux[faceI];

        aNorm[owner[faceI]] += signF[faceI]*flux[faceI];

        // Neighbour
        vector neiD = curFaceCentre - cellCentres[neighbour[faceI]];

        // Subtract convection
        res[neighbour[faceI]] +=
        (
            vf[neighbour[faceI]]
          + (neiD & gradVf[neighbour[faceI]])
        )*flux[faceI];

        aNorm[neighbour[faceI]] -= (1.0 - signF[faceI])*flux[faceI];
    }

    forAll (patches, patchI)
    {
        const vectorField& patchFaceCentres =
            faceCentres.boundaryField()[patchI];

        const scalarField& patchFlux = flux.boundaryField()[patchI];
        const scalarField& patchSignFlux = signF.boundaryField()[patchI];

        const labelList& fCells = patches[patchI].faceCells();

        forAll (fCells, faceI)
        {
            vector d =
                patchFaceCentres[faceI] - cellCentres[fCells[faceI]];

            // Subtract convection
            res[fCells[faceI]] -=
            (
                vf[fCells[faceI]]
              + (d & gradVf[fCells[faceI]])
            )*patchFlux[faceI];

            aNorm[fCells[faceI]] += patchSignFlux[faceI]*patchFlux[faceI];
        }
    }
Beispiel #22
0
void Foam::MULES::limiter
(
    scalargpuField& allLambda,
    const RdeltaTType& rDeltaT,
    const RhoType& rho,
    const volScalarField& psi,
    const surfaceScalarField& phiBD,
    const surfaceScalarField& phiCorr,
    const SpType& Sp,
    const SuType& Su,
    const scalar psiMax,
    const scalar psiMin,
    const label nLimiterIter
)
{
    const scalargpuField& psiIf = psi.getField();
    const volScalarField::GeometricBoundaryField& psiBf = psi.boundaryField();

    const scalargpuField& psi0 = psi.oldTime();

    const fvMesh& mesh = psi.mesh();

    const labelgpuList& owner = mesh.owner();
    const labelgpuList& neighb = mesh.neighbour();
    const labelgpuList& losort = mesh.lduAddr().losortAddr();

    const labelgpuList& ownStart = mesh.lduAddr().ownerStartAddr();
    const labelgpuList& losortStart = mesh.lduAddr().losortStartAddr();

    tmp<volScalarField::DimensionedInternalField> tVsc = mesh.Vsc();
    const scalargpuField& V = tVsc().getField();

    const scalargpuField& phiBDIf = phiBD;
    const surfaceScalarField::GeometricBoundaryField& phiBDBf =
        phiBD.boundaryField();

    const scalargpuField& phiCorrIf = phiCorr;
    const surfaceScalarField::GeometricBoundaryField& phiCorrBf =
        phiCorr.boundaryField();

    slicedSurfaceScalarField lambda
    (
        IOobject
        (
            "lambda",
            mesh.time().timeName(),
            mesh,
            IOobject::NO_READ,
            IOobject::NO_WRITE,
            false
        ),
        mesh,
        dimless,
        allLambda,
        false   // Use slices for the couples
    );

    scalargpuField& lambdaIf = lambda;
    surfaceScalarField::GeometricBoundaryField& lambdaBf =
        lambda.boundaryField();

    scalargpuField psiMaxn(psiIf.size(), psiMin);
    scalargpuField psiMinn(psiIf.size(), psiMax);

    scalargpuField sumPhiBD(psiIf.size(), 0.0);

    scalargpuField sumPhip(psiIf.size(), VSMALL);
    scalargpuField mSumPhim(psiIf.size(), VSMALL);

    thrust::for_each
    (
        thrust::make_counting_iterator(0),
        thrust::make_counting_iterator(0)+psiIf.size(),
        limiterMULESFunctor
        (
            owner.data(),
            neighb.data(),
            ownStart.data(),
            losortStart.data(),
            losort.data(),
            psiIf.data(),
            phiBDIf.data(),
            phiCorrIf.data(),
            psiMaxn.data(),
            psiMinn.data(),
            sumPhiBD.data(),
            sumPhip.data(),
            mSumPhim.data()
        )
    );


    forAll(phiCorrBf, patchi)
    {
        const fvPatchScalarField& psiPf = psiBf[patchi];
        const scalargpuField& phiBDPf = phiBDBf[patchi];
        const scalargpuField& phiCorrPf = phiCorrBf[patchi];

        const labelgpuList& pcells = mesh.lduAddr().patchSortCells(patchi);

        const labelgpuList& losort = mesh.lduAddr().patchSortAddr(patchi);
        const labelgpuList& losortStart = mesh.lduAddr().patchSortStartAddr(patchi);

        thrust::for_each
        (
            thrust::make_counting_iterator(0),
            thrust::make_counting_iterator(0)+pcells.size(),
            patchMinMaxMULESFunctor
            (
                losortStart.data(),
                losort.data(),
                pcells.data(),
                psiPf.coupled()?psiPf.patchNeighbourField()().data():psiPf.data(),
                phiBDPf.data(),
                phiCorrPf.data(),
                psiMaxn.data(),
                psiMinn.data(),
                sumPhiBD.data(),
                sumPhip.data(),
                mSumPhim.data()
            )
        );

    }

    psiMaxn = min(psiMaxn, psiMax);
    psiMinn = max(psiMinn, psiMin);

    //scalar smooth = 0.5;
    //psiMaxn = min((1.0 - smooth)*psiIf + smooth*psiMaxn, psiMax);
    //psiMinn = max((1.0 - smooth)*psiIf + smooth*psiMinn, psiMin);

    if (mesh.moving())
    {
        tmp<volScalarField::DimensionedInternalField> V0 = mesh.Vsc0();

        psiMaxn =
            V
           *(
               (rho.getField()*rDeltaT - Sp.getField())*psiMaxn
             - Su.getField()
            )
          - (V0().getField()*rDeltaT)*rho.oldTime().getField()*psi0
          + sumPhiBD;

        psiMinn =
            V
           *(
               Su.getField()
             - (rho.getField()*rDeltaT - Sp.getField())*psiMinn
            )
          + (V0().getField()*rDeltaT)*rho.oldTime().getField()*psi0
          - sumPhiBD;
    }
    else
    {
        psiMaxn =
            V
           *(
               (rho.getField()*rDeltaT - Sp.getField())*psiMaxn
             - Su.getField()
             - (rho.oldTime().getField()*rDeltaT)*psi0
            )
          + sumPhiBD;

        psiMinn =
            V
           *(
               Su.getField()
             - (rho.getField()*rDeltaT - Sp.getField())*psiMinn
             + (rho.oldTime().getField()*rDeltaT)*psi0
            )
          - sumPhiBD;
    }

    scalargpuField sumlPhip(psiIf.size());
    scalargpuField mSumlPhim(psiIf.size());

    for (int j=0; j<nLimiterIter; j++)
    {
        sumlPhip = 0.0;
        mSumlPhim = 0.0;

        thrust::for_each
        (
            thrust::make_counting_iterator(0),
            thrust::make_counting_iterator(0)+sumlPhip.size(),
            sumlPhiMULESFunctor
            (
                owner.data(),
                neighb.data(),
                ownStart.data(),
                losortStart.data(),
                losort.data(),
                lambdaIf.data(),
                phiCorrIf.data(),
                sumlPhip.data(),
                mSumlPhim.data()
            )
        );


        forAll(lambdaBf, patchi)
        {
            scalargpuField& lambdaPf = lambdaBf[patchi];
            const scalargpuField& phiCorrfPf = phiCorrBf[patchi];

            const labelgpuList& pcells = mesh.lduAddr().patchSortCells(patchi);

            const labelgpuList& losort = mesh.lduAddr().patchSortAddr(patchi);
            const labelgpuList& losortStart = mesh.lduAddr().patchSortStartAddr(patchi);

            thrust::for_each
            (
                thrust::make_counting_iterator(0),
                thrust::make_counting_iterator(0)+pcells.size(),
                patchSumlPhiMULESFunctor
                (
                    losortStart.data(),
                    losort.data(),
                    pcells.data(),
                    lambdaPf.data(),
                    phiCorrfPf.data(),
                    sumlPhip.data(),
                    mSumlPhim.data()
                )
            );
        }

        thrust::transform
        (
            sumlPhip.begin(),
            sumlPhip.end(),
            thrust::make_zip_iterator(thrust::make_tuple
            (
                psiMaxn.begin(),
                mSumPhim.begin()
            )),
            sumlPhip.begin(),
            sumlPhipFinalMULESFunctor<false>()
        );

        thrust::transform
        (
            mSumlPhim.begin(),
            mSumlPhim.end(),
            thrust::make_zip_iterator(thrust::make_tuple
            (
                psiMinn.begin(),
                sumPhip.begin()
            )),
            mSumlPhim.begin(),
            sumlPhipFinalMULESFunctor<true>()
        );

        const scalargpuField& lambdam = sumlPhip;
        const scalargpuField& lambdap = mSumlPhim;

        thrust::transform
        (
            phiCorrIf.begin(),
            phiCorrIf.end(),
            thrust::make_zip_iterator(thrust::make_tuple
            (
                lambdaIf.begin(),
                thrust::make_permutation_iterator
                (
                    lambdap.begin(),
                    owner.begin()
                ),
                thrust::make_permutation_iterator
                (
                    lambdam.begin(),
                    neighb.begin()
                ),
                thrust::make_permutation_iterator
                (
                    lambdam.begin(),
                    owner.begin()
                ),
                thrust::make_permutation_iterator
                (
                    lambdap.begin(),
                    neighb.begin()
                )
            )),
            lambdaIf.begin(),
            lambdaIfMULESFunctor()
        );

        forAll(lambdaBf, patchi)
        {
            fvsPatchScalarField& lambdaPf = lambdaBf[patchi];
            const scalargpuField& phiCorrfPf = phiCorrBf[patchi];
            const fvPatchScalarField& psiPf = psiBf[patchi];

            if (isA<wedgeFvPatch>(mesh.boundary()[patchi]))
            {
                lambdaPf = 0;
            }
            else if (psiPf.coupled())
            {
                const labelgpuList& pFaceCells =
                    mesh.boundary()[patchi].faceCells();

                thrust::transform
                (
                    phiCorrfPf.begin(),
                    phiCorrfPf.end(),
                    thrust::make_zip_iterator(thrust::make_tuple
                    (
                        lambdaPf.begin(),
                        thrust::make_permutation_iterator
                        (
                            lambdap.begin(),
                            pFaceCells.begin()
                        ),
                        thrust::make_permutation_iterator
                        (
                            lambdam.begin(),
                            pFaceCells.begin()
                        )
                    )),
                    lambdaPf.begin(),
                    coupledPatchLambdaPfMULESFunctor()
                );

            }
            else
            {
                const labelgpuList& pFaceCells =
                    mesh.boundary()[patchi].faceCells();
                const scalargpuField& phiBDPf = phiBDBf[patchi];
                const scalargpuField& phiCorrPf = phiCorrBf[patchi];

                thrust::transform
                (
                    phiCorrfPf.begin(),
                    phiCorrfPf.end(),
                    thrust::make_zip_iterator(thrust::make_tuple
                    (
                        lambdaPf.begin(),
                        phiBDPf.begin(),
                        phiCorrPf.begin(),
                        thrust::make_permutation_iterator
                        (
                            lambdap.begin(),
                            pFaceCells.begin()
                        ),
                        thrust::make_permutation_iterator
                        (
                            lambdam.begin(),
                            pFaceCells.begin()
                        )
                    )),
                    lambdaPf.begin(),
                    patchLambdaPfMULESFunctor()
                );
            }
        }