Ejemplo n.º 1
0
void Foam::MixedDiffuseSpecular<CloudType>::correct
(
    typename CloudType::parcelType& p
)
{
    vector& U = p.U();

    scalar& Ei = p.Ei();

    label typeId = p.typeId();

    const label wppIndex = p.patch();

    const polyPatch& wpp = p.mesh().boundaryMesh()[wppIndex];

    label wppLocalFace = wpp.whichFace(p.face());

    const vector nw = p.normal();

    // Normal velocity magnitude
    scalar U_dot_nw = U & nw;

    CloudType& cloud(this->owner());

    Random& rndGen(cloud.rndGen());

    if (diffuseFraction_ > rndGen.scalar01())
    {
        // Diffuse reflection

        // Wall tangential velocity (flow direction)
        vector Ut = U - U_dot_nw*nw;

        while (mag(Ut) < small)
        {
            // If the incident velocity is parallel to the face normal, no
            // tangential direction can be chosen.  Add a perturbation to the
            // incoming velocity and recalculate.

            U = vector
            (
                U.x()*(0.8 + 0.2*rndGen.scalar01()),
                U.y()*(0.8 + 0.2*rndGen.scalar01()),
                U.z()*(0.8 + 0.2*rndGen.scalar01())
            );

            U_dot_nw = U & nw;

            Ut = U - U_dot_nw*nw;
        }

        // Wall tangential unit vector
        vector tw1 = Ut/mag(Ut);

        // Other tangential unit vector
        vector tw2 = nw^tw1;

        scalar T = cloud.boundaryT().boundaryField()[wppIndex][wppLocalFace];

        scalar mass = cloud.constProps(typeId).mass();

        direction iDof = cloud.constProps(typeId).internalDegreesOfFreedom();

        U =
            sqrt(physicoChemical::k.value()*T/mass)
           *(
                rndGen.scalarNormal()*tw1
              + rndGen.scalarNormal()*tw2
              - sqrt(-2.0*log(max(1 - rndGen.scalar01(), vSmall)))*nw
            );

        U += cloud.boundaryU().boundaryField()[wppIndex][wppLocalFace];

        Ei = cloud.equipartitionInternalEnergy(T, iDof);
    }
    else
    {
        // Specular reflection

        if (U_dot_nw > 0.0)
        {
            U -= 2.0*U_dot_nw*nw;
        }
    }

}
Ejemplo n.º 2
0
void Foam::MaxwellianThermal<CloudType>::correct
(
    typename CloudType::parcelType& p,
    const wallPolyPatch& wpp
)
{
    vector& U = p.U();

    scalar& Ei = p.Ei();

    label typeId = p.typeId();

    label wppIndex = wpp.index();

    label wppLocalFace = wpp.whichFace(p.face());

    vector nw = p.normal();
    nw /= mag(nw);

    // Normal velocity magnitude
    scalar U_dot_nw = U & nw;

    // Wall tangential velocity (flow direction)
    vector Ut = U - U_dot_nw*nw;

    CloudType& cloud(this->owner());

    Random& rndGen(cloud.rndGen());

    while (mag(Ut) < SMALL)
    {
        // If the incident velocity is parallel to the face normal, no
        // tangential direction can be chosen.  Add a perturbation to the
        // incoming velocity and recalculate.

        U = vector
        (
            U.x()*(0.8 + 0.2*rndGen.scalar01()),
            U.y()*(0.8 + 0.2*rndGen.scalar01()),
            U.z()*(0.8 + 0.2*rndGen.scalar01())
        );

        U_dot_nw = U & nw;

        Ut = U - U_dot_nw*nw;
    }

    // Wall tangential unit vector
    vector tw1 = Ut/mag(Ut);

    // Other tangential unit vector
    vector tw2 = nw^tw1;

    scalar T = cloud.boundaryT().boundaryField()[wppIndex][wppLocalFace];

    scalar mass = cloud.constProps(typeId).mass();

    scalar iDof = cloud.constProps(typeId).internalDegreesOfFreedom();

    U =
        sqrt(physicoChemical::k.value()*T/mass)
       *(
            rndGen.GaussNormal()*tw1
          + rndGen.GaussNormal()*tw2
          - sqrt(-2.0*log(max(1 - rndGen.scalar01(), VSMALL)))*nw
        );

    U += cloud.boundaryU().boundaryField()[wppIndex][wppLocalFace];

    Ei = cloud.equipartitionInternalEnergy(T, iDof);
}
void Foam::LarsenBorgnakkeVariableHardSphere<CloudType>::collide
(
    typename CloudType::parcelType& pP,
    typename CloudType::parcelType& pQ
)
{
    CloudType& cloud(this->owner());

    label typeIdP = pP.typeId();
    label typeIdQ = pQ.typeId();
    vector& UP = pP.U();
    vector& UQ = pQ.U();
    scalar& EiP = pP.Ei();
    scalar& EiQ = pQ.Ei();

    Random& rndGen(cloud.rndGen());

    scalar inverseCollisionNumber = 1/relaxationCollisionNumber_;

    // Larsen Borgnakke internal energy redistribution part.  Using the serial
    // application of the LB method, as per the INELRS subroutine in Bird's
    // DSMC0R.FOR

    scalar preCollisionEiP = EiP;
    scalar preCollisionEiQ = EiQ;

    direction iDofP = cloud.constProps(typeIdP).internalDegreesOfFreedom();
    direction iDofQ = cloud.constProps(typeIdQ).internalDegreesOfFreedom();

    scalar omegaPQ =
        0.5
       *(
            cloud.constProps(typeIdP).omega()
          + cloud.constProps(typeIdQ).omega()
        );

    scalar mP = cloud.constProps(typeIdP).mass();
    scalar mQ = cloud.constProps(typeIdQ).mass();
    scalar mR = mP*mQ/(mP + mQ);
    vector Ucm = (mP*UP + mQ*UQ)/(mP + mQ);
    scalar cRsqr = magSqr(UP - UQ);
    scalar availableEnergy = 0.5*mR*cRsqr;
    scalar ChiB = 2.5 - omegaPQ;

    if (iDofP > 0)
    {
        if (inverseCollisionNumber > rndGen.scalar01())
        {
            availableEnergy += preCollisionEiP;

            if (iDofP == 2)
            {
                scalar energyRatio = 1.0 - pow(rndGen.scalar01(), (1.0/ChiB));
                EiP = energyRatio*availableEnergy;
            }
            else
            {
                scalar ChiA = 0.5*iDofP;
                EiP = energyRatio(ChiA, ChiB)*availableEnergy;
            }

            availableEnergy -= EiP;
        }
    }

    if (iDofQ > 0)
    {
        if (inverseCollisionNumber > rndGen.scalar01())
        {
            availableEnergy += preCollisionEiQ;

            if (iDofQ == 2)
            {
                scalar energyRatio = 1.0 - pow(rndGen.scalar01(), (1.0/ChiB));
                EiQ = energyRatio*availableEnergy;
            }
            else
            {
                scalar ChiA = 0.5*iDofQ;
                EiQ = energyRatio(ChiA, ChiB)*availableEnergy;
            }

            availableEnergy -= EiQ;
        }
    }

    // Rescale the translational energy
    scalar cR = sqrt(2.0*availableEnergy/mR);

    // Variable Hard Sphere collision part
    scalar cosTheta = 2.0*rndGen.scalar01() - 1.0;
    scalar sinTheta = sqrt(1.0 - cosTheta*cosTheta);
    scalar phi = twoPi*rndGen.scalar01();

    vector postCollisionRelU =
        cR
       *vector
        (
            cosTheta,
            sinTheta*cos(phi),
            sinTheta*sin(phi)
        );

    UP = Ucm + postCollisionRelU*mQ/(mP + mQ);
    UQ = Ucm - postCollisionRelU*mP/(mP + mQ);
}