Пример #1
0
atmBoundaryLayer::atmBoundaryLayer(const vectorField& p, const dictionary& dict)
:
    flowDir_(dict.lookup("flowDir")),
    zDir_(dict.lookup("zDir")),
    kappa_(dict.lookupOrDefault<scalar>("kappa", 0.41)),
    Cmu_(dict.lookupOrDefault<scalar>("Cmu", 0.09)),
    Uref_(readScalar(dict.lookup("Uref"))),
    Zref_(readScalar(dict.lookup("Zref"))),
    z0_("z0", dict, p.size()),
    zGround_("zGround", dict, p.size()),
    Ustar_(p.size())
{
    if (mag(flowDir_) < SMALL || mag(zDir_) < SMALL)
    {
        FatalErrorInFunction
            << "magnitude of n or z must be greater than zero"
            << abort(FatalError);
    }

    // Ensure direction vectors are normalized
    flowDir_ /= mag(flowDir_);
    zDir_ /= mag(zDir_);

    Ustar_ = kappa_*Uref_/(log((Zref_ + z0_)/z0_));
}
Пример #2
0
Foam::tmp<Foam::vectorField> Foam::sphericalCS::localToGlobal
(
    const vectorField& local,
    bool translate
) const
{
    const scalarField r(local.component(vector::X));
    const scalarField theta
    (
        local.component(vector::Y)
       *(inDegrees_ ? constant::mathematical::pi/180.0 : 1.0)
    );
    const scalarField phi
    (
        local.component(vector::Z)
       *(inDegrees_ ? constant::mathematical::pi/180.0 : 1.0)
    );

    vectorField lc(local.size());
    lc.replace(vector::X, r*cos(theta)*sin(phi));
    lc.replace(vector::Y, r*sin(theta)*sin(phi));
    lc.replace(vector::Z, r*cos(phi));

    return coordinateSystem::localToGlobal(lc, translate);
}
void Foam::dx<Type>::writeDXData
(
    const pointField& points,
    const vectorField& values,
    Ostream& os
) const
{
    // Write data
    os  << "object 3 class array type float rank 1 shape 3 items "
        << values.size()
        << " data follows" << nl;

    forAll(values, elemI)
    {
        os  << float(values[elemI].x()) << ' '
            << float(values[elemI].y()) << ' '
            << float(values[elemI].z()) << nl;
    }

    if (values.size() == points.size())
    {
        os  << nl << "attribute \"dep\" string \"positions\""
            << nl << nl;
    }
    else
    {
        os  << nl << "attribute \"dep\" string \"connections\""
            << nl << nl;
    }
}
Пример #4
0
// Calculate a simple check on a vector field
void record(vectorField& V)
{
    // Calculate the magnitude of a field
    const int x=0, y=1, z=2;
    double magx = sum(pow2(V[x])) / V.numElements();
    double magy = sum(pow2(V[y])) / V.numElements();
    double magz = sum(pow2(V[z])) / V.numElements();

    cout << "norm = [" << magx
        << " " << magy << " " << magz << " ]" << endl;
}
Пример #5
0
// Update vectorField for all the new cells. Takes over value of
// original cell.
void Foam::multiDirRefinement::update
(
    const Map<label>& splitMap,
    vectorField& field
)
{
    field.setSize(field.size() + splitMap.size());

    forAllConstIter(Map<label>, splitMap, iter)
    {
        field[iter()] = field[iter.key()];
    }
}
Foam::tmp<Foam::Field<Type> >
Foam::basicSymmetryFvPatchField<Type>::snGradTransformDiag() const
{
    const vectorField nHat(this->patch().nf());

    vectorField diag(nHat.size());

    diag.replace(vector::X, mag(nHat.component(vector::X)));
    diag.replace(vector::Y, mag(nHat.component(vector::Y)));
    diag.replace(vector::Z, mag(nHat.component(vector::Z)));

    return transformFieldMask<Type>(pow<vector, pTraits<Type>::rank>(diag));
}
Foam::tmp<Foam::Field<Type> >
Foam::partialSlipFvPatchField<Type>::snGradTransformDiag() const
{
    const vectorField nHat(this->patch().nf());
    vectorField diag(nHat.size());

    diag.replace(vector::X, mag(nHat.component(vector::X)));
    diag.replace(vector::Y, mag(nHat.component(vector::Y)));
    diag.replace(vector::Z, mag(nHat.component(vector::Z)));

    return
        valueFraction_*pTraits<Type>::one
      + (1.0 - valueFraction_)
       *transformFieldMask<Type>(pow<vector, pTraits<Type>::rank>(diag));
}
Пример #8
0
void snapshot(vectorField& P)
{
    static int snapshotNum = 0;

    ++snapshotNum;
    char filename[128];
    sprintf(filename, "velocity%03d.m", snapshotNum);

    ofstream ofs(filename);
    int N = P.length(firstDim);

    int k = N/2;

    ofs << "P" << snapshotNum << " = [ ";
    for (int i=0; i < N; ++i)
    {
        for (int j=0; j < N; ++j)
        {
            float value = norm(P(k,j,N-i-1));
            ofs << value << " ";
        }
        if (i < N-1)
            ofs << ";" << endl;
    }
    ofs << "];" << endl;
}
Пример #9
0
// Update vectorField for all the new cells. Takes over value of
// original cell.
void Foam::multiDirRefinement::update
(
    const Map<label>& splitMap,
    vectorField& field
)
{
    field.setSize(field.size() + splitMap.size());

    for
    (
        Map<label>::const_iterator iter = splitMap.begin();
        iter != splitMap.end();
        ++iter
    )
    {
        field[iter()] = field[iter.key()];
    }
}
Пример #10
0
Foam::tmp<Foam::vectorField> Foam::transform
(
    const quaternion& q,
    const vectorField& tf
)
{
    tmp<vectorField > tranf(new vectorField(tf.size()));
    transform(tranf.ref(), q, tf);
    return tranf;
}
Пример #11
0
Foam::tmp<Foam::vectorField> Foam::waveSuperposition::velocity
(
    const scalar t,
    const vectorField& xyz
) const
{
    vectorField result(xyz.size(), vector::zero);

    forAll(waveModels_, wavei)
    {
        const vector2D d(cos(waveAngles_[wavei]), sin(waveAngles_[wavei]));
        const vector2DField xz
        (
            zip
            (
                d & zip(xyz.component(0), xyz.component(1)),
                tmp<scalarField>(xyz.component(2))
            )
        );
        const vector2DField uw
        (
            waveModels_[wavei].velocity(t, xz)
        );
        result += zip
        (
            d.x()*uw.component(0),
            d.y()*uw.component(0),
            uw.component(1)
        );
    }

    tmp<scalarField> s = scale(zip(xyz.component(0), xyz.component(1)));

    return s*result;
}
Пример #12
0
/*
 * Adjust the time step according to the CFL stability criterion
 */
void adjustTimeStep(vectorField& V)
{
    // Find maximum velocity magnitude
    double maxV = 0.0;

    // NEEDS_WORK: Blitz should provide a norm(vectorField) function.
    // This is ugly.

    for (int i=V.lbound(0); i <= V.ubound(0); ++i)
      for (int j=V.lbound(1); j <= V.ubound(1); ++j)
        for (int k=V.lbound(2); k <= V.ubound(2); ++k)
        {
            double normV = norm(V(i,j,k));
            if (normV > maxV)
                maxV = normV;
        }

    cout << "Maximum velocity is " << maxV << " m/s" << endl;

    maxV += 1e-10;   // Avoid divide-by-zero

    // Steve K: need to have spatialStep^2 / diffusion constant
    // diffusion constant = eta * recip_rho

    delta_t = 0.3 * spatialStep / maxV;
    const double maxTimeStep = 0.01;

    if (delta_t > maxTimeStep)
        delta_t = maxTimeStep;

    cout << "Set time step to " << delta_t << " s" << endl;
}
Пример #13
0
Foam::tmp<Foam::symmTensorField> Foam::STARCDCoordinateRotation::
transformVector
(
    const vectorField& st
) const
{
    tmp<symmTensorField> tfld(new symmTensorField(st.size()));
    symmTensorField& fld = tfld();

    forAll(fld, i)
    {
        fld[i] = transformPrincipal(R_, st[i]);
    }
Пример #14
0
Foam::tmp<Foam::vectorField> Foam::toroidalCS::localToGlobal
(
    const vectorField& local,
    bool translate
) const
{
    const scalarField r = local.component(vector::X);

    const scalarField theta =
        local.component(vector::Y)*mathematicalConstant::pi/180.0;

    const scalarField phi =
        local.component(vector::Z)*mathematicalConstant::pi/180.0;

    const scalarField rprime = radius_ + r*sin(phi);

    vectorField lc(local.size());
    lc.replace(vector::X, rprime*cos(theta));
    lc.replace(vector::Y, rprime*sin(theta));
    lc.replace(vector::Z, r*cos(phi));

    return coordinateSystem::localToGlobal(lc, translate);
}
Foam::tmp<Foam::vectorField> Foam::sphericalCS::globalToLocal
(
    const vectorField& global,
    bool translate
) const
{
    const vectorField lc = coordinateSystem::globalToLocal(global, translate);
    const scalarField r = mag(lc);

    tmp<vectorField> tresult(new vectorField(lc.size()));
    vectorField& result = tresult();

    result.replace
    (
        vector::X, r

    );

    result.replace
    (
        vector::Y,
        atan2
        (
            lc.component(vector::Y),
            lc.component(vector::X)
        )*180.0/mathematicalConstant::pi
    );

    result.replace
    (
        vector::Z,
        acos(lc.component(vector::Z)/(r + SMALL))*180.0/mathematicalConstant::pi
    );

    return tresult;
}
void Foam::rotateSearchableSurface::getNormal
(
    const List<pointIndexHit>& info,
    vectorField& normal
) const
{
    vectorField iNormal;
    
    transformationSearchableSurface::getNormal
        (
            info,
            iNormal
        );

    normal.setSize(iNormal.size());

    forAll(normal,i) {
        normal[i]=transform(iNormal[i]);
    }
void Foam::scaleSearchableSurface::getNormal
(
    const List<pointIndexHit>& info,
    vectorField& normal
) const
{
    vectorField iNormal;

    transformationSearchableSurface::getNormal
        (
            info,
            iNormal
        );

    normal.setSize(iNormal.size());

    forAll(normal,i) {
        normal[i]=inverseTransform(iNormal[i]);
        scalar len=mag(normal[i]);
        if(len>SMALL) {
            normal[i]/=len;
        }
    }
Foam::tmp<Foam::vectorField> Foam::parabolicCylindricalCS::localToGlobal
(
    const vectorField& local,
    bool translate
) const
{
    if (min(local.component(vector::Y)) < 0.0)
    {
        FatalErrorIn
        (
            "parabolicCylindricalCS::localToGlobal"
            "(const vectorField&, bool) const"
        )   << "parabolic cylindrical coordinates v < 0"
            << abort(FatalError);
    }

    vectorField lc(local.size());
    lc.replace
    (
        vector::X,
        0.5*
        (
            sqr(local.component(vector::X))
          - sqr(local.component(vector::Y))
        )
    );

    lc.replace
    (
        vector::Y,
        local.component(vector::X) * local.component(vector::Y)
    );

    lc.replace
    (
        vector::Z,
        local.component(vector::Z)
    );

    return coordinateSystem::localToGlobal(lc, translate);
}
void Foam::meshRefinement::findNearest
(
    const labelList& meshFaces,
    List<pointIndexHit>& nearestInfo,
    labelList& nearestSurface,
    labelList& nearestRegion,
    vectorField& nearestNormal
) const
{
    pointField fc(meshFaces.size());
    forAll(meshFaces, i)
    {
        fc[i] = mesh_.faceCentres()[meshFaces[i]];
    }

    const labelList allSurfaces(identity(surfaces_.surfaces().size()));

    surfaces_.findNearest
    (
        allSurfaces,
        fc,
        scalarField(fc.size(), sqr(GREAT)),    // sqr of attraction
        nearestSurface,
        nearestInfo
    );

    // Do normal testing per surface.
    nearestNormal.setSize(nearestInfo.size());
    nearestRegion.setSize(nearestInfo.size());

    forAll(allSurfaces, surfI)
    {
        DynamicList<pointIndexHit> localHits;

        forAll(nearestSurface, i)
        {
            if (nearestSurface[i] == surfI)
            {
                localHits.append(nearestInfo[i]);
            }
        }

        label geomI = surfaces_.surfaces()[surfI];

        pointField localNormals;
        surfaces_.geometry()[geomI].getNormal(localHits, localNormals);

        labelList localRegion;
        surfaces_.geometry()[geomI].getRegion(localHits, localRegion);

        label localI = 0;
        forAll(nearestSurface, i)
        {
            if (nearestSurface[i] == surfI)
            {
                nearestNormal[i] = localNormals[localI];
                nearestRegion[i] = localRegion[localI];
                localI++;
            }
        }
    }
void Foam::dirichletNeumannFriction::correct
(
    const vectorField& slavePressure,
    const PrimitivePatch<face, List, pointField>& masterFaceZonePatch,
    const PrimitivePatch<face, List, pointField>& slaveFaceZonePatch,
    const intersection::algorithm alg,
    const intersection::direction dir,
    const word interpolationMethod,
    const word fieldName,
    const Switch orthotropic,
    const word nonLinear,
    const vectorField& slaveFaceNormals
)
{
    const fvMesh& mesh = mesh_;
    const label slavePatchIndex = slavePatchID();
    const label masterPatchIndex = masterPatchID();
    contactIterNum_++;

    // we have local masterDU and we want to interpolate it to the slave
    // to get local masterDUInterpToSlave (i.e. masterDU interpolated
    // to the slave)
    // so the method is:
    // create global masterDU field
    // interpolate global masterDU from master global face zone to
    // slave global zone
    // then find local masterDUInterpToSlave from the global interpolated field

    vectorField masterDUInterpToSlave
    (mesh.boundaryMesh()[slavePatchIndex].size(), vector::zero);

    // global master DU
    vectorField globalMasterDU(masterFaceZonePatch.size(), vector::zero);

    // lookup current displacement field
    const volVectorField& dispField =
        mesh.objectRegistry::lookupObject<volVectorField>(fieldName);

    // local master and slave DU increment
    vectorField masterDU = dispField.boundaryField()[masterPatchIndex];
    vectorField slaveDU = dispField.boundaryField()[slavePatchIndex];

    if (fieldName == "U")
    {
        // lookup old U
        const volVectorField& dispOldField =
            mesh.objectRegistry::lookupObject<volVectorField>(fieldName+"_0");

        // subtract old U
        masterDU -= dispOldField.boundaryField()[masterPatchIndex];
        slaveDU -= dispOldField.boundaryField()[slavePatchIndex];
    }
    else if (fieldName != "DU")
    {
        FatalError << "dirichletNeumannFriction::correct()\n"
                   " The displacement field must be called U or DU"
                   << exit(FatalError);
    }

    // put local masterDU into globalMasterDU
    const label masterPatchStart
        = mesh.boundaryMesh()[masterPatchIndex].start();
    forAll(masterDU, i)
    {
        globalMasterDU[
            mesh.faceZones()[masterFaceZoneID()
                            ].whichFace(masterPatchStart + i)] =
                                masterDU[i];
    }
    //- exchange parallel data
    // sum because each face is only on one proc
    reduce(globalMasterDU, sumOp<vectorField>());

    // globalMasterDU is interpolated to the slave
    vectorField globalMasterDUInterpToSlave
    (slaveFaceZonePatch.size(), vector::zero);

    // interpolate DU from master to slave using inverse distance or ggi
    if (interpolationMethod == "patchToPatch")
    {
        PatchToPatchInterpolation<
        PrimitivePatch<
        face, List, pointField
        >, PrimitivePatch<face, List, pointField>
        > masterToSlavePatchToPatchInterpolator
        (
            masterFaceZonePatch, // from zone
            slaveFaceZonePatch, // to zone
            alg,
            dir
        );
        globalMasterDUInterpToSlave =
            masterToSlavePatchToPatchInterpolator.faceInterpolate<vector>
            (
                globalMasterDU
            );
    }
    else if (interpolationMethod == "ggi")
    {
        GGIInterpolation<
        PrimitivePatch<
        face, List, pointField
        >, PrimitivePatch< face, List, pointField >
        > masterToSlaveGgiInterpolator
        (
            masterFaceZonePatch, // master zone
            slaveFaceZonePatch, // slave zone
            tensorField(0),
            tensorField(0),
            vectorField(0),
            0.0,
            0.0,
            true,
            ggiInterpolation::AABB
        );
        globalMasterDUInterpToSlave =
            masterToSlaveGgiInterpolator.masterToSlave
            (
                globalMasterDU
            );
    }
    else
    {
        FatalError << "dirichletNeumannFriction::correct()\n"
                   "interpolationMethod " << interpolationMethod << " not known\n"
                   "interpolationMethod must be patchToPatch or ggi"
                   << exit(FatalError);
    }

    // now put global back into local
    const label slavePatchStart
        = mesh.boundaryMesh()[slavePatchIndex].start();

    forAll(masterDUInterpToSlave, i)
    {
        masterDUInterpToSlave[i] =
            globalMasterDUInterpToSlave
            [
                mesh.faceZones()[slaveFaceZoneID()].whichFace(slavePatchStart + i)
            ];
    }

    // Now masterDUInterpToSlave should have masterDU interpolated to the slave

    // Calculate current slave shear traction from the normal gradient field
    const fvPatch& slavePatch = mesh.boundary()[slavePatchIndex];
    const fvPatchField<tensor>& gradField =
        slavePatch.lookupPatchField<volTensorField, tensor>
        ("grad(" + fieldName + ")");

    bool incremental(fieldName == "DU");

    vectorField slaveShearTraction
    (
        (I - sqr(slaveFaceNormals))
        & tractionBoundaryGradient::traction
        (
            gradField,
            fieldName,
            "U",
            slavePatch,
            orthotropic,
            nonLinearGeometry::nonLinearNames_[nonLinear],
            incremental
        )
    );


    // algorithm
    // if the face pressure is negative/zero then the friction is zero
    // so set valueFrac to zero and traction to zero
    // if the face pressure is positive and the shear traction is less
    // than fricCoeff*pressure then this is a sticking face so
    // set the valueFrac to (I-n^2) and set the disp to remove any
    // slip
    // if the face pressure is positive and the shear traction is greater
    // than fricCoeff*pressure then this is a slipping face so
    // set the valueFrac to zero and set the shear traction to
    // fricCoeff*pressure in the opposite direction to slip
    // if the shear traction on a slipping face is acting in the same
    // direction as the slip then this face should not be slipping
    // so we make it a sticking face
    // const volVectorField& prevSlaveDispField =
    //   mesh.objectRegistry::lookupObject<volVectorField>(fieldName);
    const vectorField prevSlaveShearDisp =
        (I - sqr(slaveFaceNormals))
        & dispField.boundaryField()[slavePatchIndex];
    label numSlipFaces = 0;
    label numStickFaces = 0;
    scalarField& stickSlip = stickSlipFaces();
    const scalarField magSlavePressure = mag(slavePressure);
    scalar maxMagSlavePressure = 0.0;
    if (slavePressure.size() > 0) maxMagSlavePressure = max(magSlavePressure);
    reduce(maxMagSlavePressure, maxOp<scalar>());

    // slip is the difference between the master tangential DU
    // and slave tangential DU
    vectorField slip =
        (I - sqr(slaveFaceNormals)) &
        ( slaveDU - masterDUInterpToSlave);

    // under-relax the slip
    slip = relaxationFactor_*slip + (1.0 - relaxationFactor_)*oldSlip_;
    oldSlip_ = slip;

    vectorField slipDir = slip/(mag(slip)+SMALL);

    const scalar pressureTol = 1e-3*maxMagSlavePressure;


    // first we calculate slaveDisp assuming every face is sticking
    // and we calculate slaveTraction assuming every face is sliding
    // then we use the slaveValueFrac to set the face to slip/stick
    // depending on the slip function
    slaveDisp_ = -slip + prevSlaveShearDisp;
    //slaveDisp_ = -slip + slaveDisp_; // see if convergence is better

    scalarField slipTrac = frictionLawPtr_->slipTraction(magSlavePressure);

    // new
    forAll(slaveDisp_, facei)
    {
        if (mag(slavePressure[facei]) < pressureTol)
        {
            // not in contact
            slaveDisp_[facei] = prevSlaveShearDisp[facei];
            slaveTraction_[facei] = vector::zero;
            slaveValueFrac_[facei] = symmTensor::zero;

            stickSlip[facei] = -1;
        }
        else if (
            (mag(slaveShearTraction[facei]) > 0.999*slipTrac[facei])
            &&
            ((slip[facei] & slaveShearTraction[facei]) < 0.0) // opposite directions
        )
        {
            // slip
            slaveDisp_[facei] =
                -slip[facei] + prevSlaveShearDisp[facei]; // better convergence
            slaveTraction_[facei] = -slipDir[facei] * slipTrac[facei];
            slaveValueFrac_[facei] = symmTensor::zero;
            numSlipFaces++;

            stickSlip[facei] = 0;
        }
        else
        {
            // stick
            slaveDisp_[facei] = -slip[facei] + prevSlaveShearDisp[facei];
            slaveTraction_[facei] = -slipDir[facei] * slipTrac[facei];
            //slaveTraction_[facei] = slaveShearTraction[facei];
            //slaveTraction_[facei] = vector::zero;
            slaveValueFrac_[facei] = (I - sqr(slaveFaceNormals[facei]));
            numStickFaces++;

            stickSlip[facei] = 2;
        }
    }

    // slaveTraction_ = -slipDir * slipTrac;

    // // slipFunc is 1.0 for slip and 0.0 for stick
    // // scalarField slipFunc = mag(slaveShearTraction) - 0.999*slipTrac;
    // scalarField slipFunc = mag(slaveShearTraction) - slipTrac;
    // //slipFunc /= mag(slipFunc+SMALL); // bugfix add SMALL
    // //slipFunc = max(slipFunc, 0.0);
    // //const scalar slipStressTol = 1e-4*gMax(mag(slaveShearTraction));
    // const scalar pressureTol = 1e-3*maxMagSlavePressure;
    // forAll(slipFunc, facei)
    //   {
    //      if (slipFunc[facei] > pressureTol)
    //        {
    //          slipFunc[facei] = 1.0;
    //        }
    //      else
    //        {
    //          slipFunc[facei] = 0.0;
    //        }
    //   }

    // // if the slip and trac are in the same direction then we will change
    // // the face from slip to stick
    // // {
    // //   scalarField changeFace = slip & slaveTraction_;
    // //   forAll(changeFace, facei)
    // //   {
    // //     if (changeFace[facei] > SMALL)
    // //       {
    // //         slipFunc[facei] = 0.0;
    // //       }
    // //   }
    // // }

    // // stickSlip
    // // -1 for faces not in contact
    // // 0 for slipping faces
    // // 1 for stick faces
    // stickSlip = (1.0 - slipFunc);
    // // const scalar pressureTol = 1e-3*maxMagSlavePressure;
    // forAll(slip, facei)
    //   {
    //      if (magSlavePressure[facei] < pressureTol)
    //        {
    //          stickSlip[facei] = -1;
    //        }
    //   }

    // //slaveValueFrac_ = (1.0 - slipFunc) * (I - sqr(slaveFaceNormals));
    // slaveValueFrac_ = max(stickSlip, 0.0) * (I - sqr(slaveFaceNormals));

    // // set valueFace to zero for faces not in contact
    // // and also reset traction on sticking faces and displacement
    // // on slipping faces
    // forAll(slip, facei)
    //   {
    //      if (magSlavePressure[facei] < pressureTol)
    //        {
    //          slaveDisp_[facei] = prevSlaveShearDisp[facei];
    //          slaveTraction_[facei] = vector::zero;
    //          slaveValueFrac_[facei] = symmTensor::zero;
    //          if ( mag(stickSlip[facei] + 1) > SMALL)
    //            Info << "face " << facei << "changed to tracFree" << endl;

    //          stickSlip[facei] = -1;
    //        }
    //      else if (slipFunc[facei] > SMALL)
    //        {
    //          slaveDisp_[facei] = prevSlaveShearDisp[facei];
    //          numSlipFaces++;

    //          if ( mag(stickSlip[facei]) > SMALL)
    //            Info << "face " << facei << "changed to slip" << endl;

    //          stickSlip[facei] = 0;
    //        }
    //      else
    //        {
    //          //slaveTraction_[facei] = slaveShearTraction[facei];
    //          numStickFaces++;

    //          if ( mag(stickSlip[facei] - 1) > SMALL)
    //            Info << "face " << facei << "changed to stick" << endl;

    //          stickSlip[facei] = 1;
    //        }
    //   }

    // correct oscillations
    if (oscillationCorr_)
    {
        //correctOscillations(slaveFaceZonePatch);

        // interpolate face values to points then interpolate back
        // this essentially smooths the field
        primitivePatchInterpolation localSlaveInterpolator
        (mesh.boundaryMesh()[slavePatchIndex]);
        vectorField slaveDispPoints
        (mesh.boundaryMesh()[slavePatchIndex].nPoints(), vector::zero);

        for (int i=0; i<smoothingSteps_; i++)
        {
            slaveDispPoints =
                localSlaveInterpolator.faceToPointInterpolate<vector>(slaveDisp_);
            slaveDisp_ =
                localSlaveInterpolator.pointToFaceInterpolate<vector>
                (slaveDispPoints);

            // make sure no normal component
            slaveDisp_ = (I - sqr(slaveFaceNormals)) & slaveDisp_;
        }
    }

    // under-relax traction
    slaveDisp_ =
        relaxationFactor_*slaveDisp_
        + (1.0 - relaxationFactor_)*prevSlaveShearDisp; //oldSlaveDisp_;
    oldSlaveDisp_ = slaveDisp_;
    slaveValueFrac_ =
        relaxationFactor_*slaveValueFrac_
        + (1.0 - relaxationFactor_)*oldSlaveValueFrac_;
    oldSlaveValueFrac_ = slaveValueFrac_;
    slaveTraction_ =
        relaxationFactor_*slaveTraction_
        + (1.0 - relaxationFactor_)*oldSlaveTraction_;
    oldSlaveTraction_ = slaveTraction_;
    stickSlip =
        relaxationFactor_*stickSlip + (1.0 - relaxationFactor_)*oldStickSlip_;
    oldStickSlip_ = stickSlip;

    // get global values
    // in parallel, the log is poluted with warnings that
    // I am getting max of a list of size zero so
    // I will get the max of procs which have some
    // of the slave faces
    //scalar maxMagMasterTraction = gMax(mag(slaveTraction_))
    scalar maxMagMasterTraction = 0.0;
    if (slaveTraction_.size() > 0)
    {
        maxMagMasterTraction = max(mag(slaveTraction_));
    }
    reduce(maxMagMasterTraction, maxOp<scalar>());
    reduce(numSlipFaces, sumOp<int>());
    reduce(numStickFaces, sumOp<int>());

    // master writes to contact info file
    if (Pstream::master() && (contactIterNum_ %  infoFreq_ == 0))
    {
        OFstream& contactFile = *contactFilePtr_;
        int width = 20;
        contactFile << mesh.time().value();
        contactFile.width(width);
        contactFile << contactIterNum_;
        contactFile.width(width);
        contactFile << relaxationFactor_;
        contactFile.width(width);
        contactFile << numSlipFaces;
        contactFile.width(width);
        contactFile << numStickFaces;
        contactFile.width(width);
        contactFile << maxMagMasterTraction << endl;
    }
}
Пример #21
0
BZ_END_STENCIL


/*
 * Allocate arrays and set their initial state
 */
void setup(const int N, vectorField& V, vectorField& nextV, scalarField& P,
    scalarField& P_rhs, vectorField& advect, vectorField& force)
{
    // A 1m x 1m x 1m domain
    spatialStep = 1.0 / (N - 1);
    geom = UniformCubicGeometry<3>(spatialStep);

    // Allocate arrays
    allocateArrays(shape(N,N,N), advect, V, nextV, force);  // vector fields
    allocateArrays(shape(N,N,N), P, P_rhs);                 // scalar fields

    // Since incompressibility is assumed, pressure only shows up as
    // derivative terms in the equations.  We choose airPressure = 0
    // as an arbitrary datum.

    airPressure = 0;             // Pa
    rho = 1000;                  // density of fluid, kg/m^3
    recip_rho = 1.0 / rho;       // inverse of density
    eta = 1.0e-6;                // kinematic viscosity of fluid, m^2/s
    gravity = 9.81;              // m/s^2
    delta_t = 0.001;             // initial time step, in seconds
    volume = pow3(spatialStep);  // cubic volume associated with grid point

    // Kludge: Set eta high, so that the flow will spread faster.
    // This means the cube is filled with molasses, rather than water.
    eta *= 1000;
   
    // Initial conditions: quiescent
    V = 0.0; 
    P_rhs = 0.0;
    advect = 0.0;
    nextV = 0.0;

    // Initial pressure condition: gravity causes a linear increase
    // in pressure with depth.  Note that tensor::k means the index
    // associated with the z axis (they are labelled i, j, k).
#ifdef NO_GRAVITY
    gravityPressureGradient = 0.0;
    P = 0.0;
#else
    gravityPressureGradient = spatialStep * gravity * rho;

#ifdef BZ_HAVE_NAMESPACES
    P = airPressure + tensor::k * gravityPressureGradient;
#else
    P = airPressure + k * gravityPressureGradient;
#endif

#endif

    // Set up the forcing function: gravity plus a stirring force
    // at the bottom
    double gravity_z = gravity * rho;

    const int x = 0, y = 1, z = 2;
    force[x] = 0.0;
    force[y] = 0.0;
#ifdef NO_GRAVITY
    force[z] = 0.0;
#else
    force[z] = gravity_z;    
#endif

#ifndef NO_STIRRING
    // Centre of the stirring
    int centrex = int(2 * N / 3.0);
    int centrey = int(2 * N / 3.0);
    int centrez = int(4 * N / 5.0);

    const double stirRadius = 1.0 / 3.0;

    vector3d zaxis(0,0,1);

    // Loop through the 2D slice where the stirring occurs

    for (int i=force.lbound(firstDim); i <= force.ubound(firstDim); ++i)
    {
      for (int j=force.lbound(secondDim); j <= force.ubound(secondDim); ++j)
      {
         // Vector from the centre of the stirring to the current
         // coordinate

         vector3d r((i-centrex) * spatialStep, (j-centrey) * spatialStep, 0.0);

         if (norm(r) < stirRadius)
         {
             // The cross product of the z-axis and the vector3d to this
             // coordinate yields the direction of the force.  Multiply
             // by gravity to get a reasonable magnitude (max force =
             // 5 * gravity)
             force(i,j,centrez) += cross(zaxis, r) 
                 * (5 * gravity_z / stirRadius);
         }
      }
    }
#endif // NO_STIRRING
}
Пример #22
0
	void CalculateDragForce
	(
		cfdemCloud& sm,
		const volScalarField& alpf_,
		const volVectorField& Uf_,
		const volScalarField& rho_,
		const bool& verbose_,
		vectorField& DragForce_,
		const labelListList& particleList_
	)
	{
		
		// get viscosity field
		#ifdef comp
		    const volScalarField nufField = sm.turbulence().mu()/rho_;
		#else
		    const volScalarField& nufField = sm.turbulence().nu();
		#endif

		// Local variables	
		label  cellI(-1);
		vector drag(0,0,0);
		vector Ufluid(0,0,0);
		
		vector position(0,0,0);
		scalar voidfraction(1);
		
		vector Up(0,0,0);
		vector Ur(0,0,0);
		scalar ds(0);
		
		scalar nuf(0);
		scalar rhof(0);
		
		vector WenYuDrag(0,0,0);
		
		interpolationCellPoint<scalar> voidfractionInterpolator_(alpf_);
		interpolationCellPoint<vector> UInterpolator_(Uf_);	
				
		// 
		//_AO_Parallel
		DragForce_.resize(particleList_.size());
					
	    	for(int ii =0; ii < particleList_.size(); ii++)
		{
			int index = particleList_[ii][0];
			cellI = sm.cellIDs()[index][0];
			drag = vector(0,0,0);
			Ufluid = vector(0,0,0);
			WenYuDrag = vector(0,0,0);
			DragForce_[ii] = vector(0,0,0);
			    
			if (cellI > -1) // particle Found
			{
				position = sm.position(index);
			
				if ( alpf_[cellI] > 1. ) Pout << " voidfraction > 1 " << alpf_[cellI] << endl;
			
				voidfraction = voidfractionInterpolator_.interpolate(position,cellI);
				Ufluid = UInterpolator_.interpolate(position,cellI);
			
				if ( voidfraction > 1. ) 
				{
						Pout << " Int. voidfraction > 1 " << " value= " << voidfraction;
						voidfraction = alpf_[cellI];
						Pout << " mod. value = " << voidfraction << endl;
				}		
				Up = sm.velocity(index);
			
				Ur = Ufluid-Up;				
				ds = 2*sm.radius(index);		
				rhof = rho_[cellI];
				nuf = nufField[cellI];
			
				// Drag force
				WenYuDragForce(Ur,ds,rhof,nuf,voidfraction,WenYuDrag);
						
				if(verbose_ && index <= 1)
				{
					Info << "" << endl;
					Pout << " index = " << index << endl;
					Pout << " position = " << position << endl; 
					Pout << " Up = " << Up << endl;
					Pout << " Ur = " << Ur << endl;
					Pout << " dp = " << ds << endl;
					Pout << " rho = " << rhof << endl;
					Pout << " nuf = " << nuf << endl;
					Pout << " voidfraction = " << voidfraction << endl;
					Pout << " drag = " << WenYuDrag << endl;
					Info << " " << endl;
				}
			}	
			for(int j=0;j<3;j++) DragForce_[ii][j] = WenYuDrag[j];
		}	
	}
void Foam::waveAbsorptionVelocity2DFvPatchVectorField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    // PHC //
    Info << "3D_2D Absorption BC on patch " << this->patch().name() << endl;

    // 3D Variables
    const vector cMin = gMin(patch().patch().localPoints());
    const vector cMax = gMax(patch().patch().localPoints());
    const vector cSpan = cMax - cMin;

    scalar dMin = 0.0;
    scalar dSpan = 0.0;
    const scalarField patchD = patchDirection( cSpan, &dMin, &dSpan );

    // Variables & constants
    const volScalarField& alpha = 
        db().lookupObject<volScalarField>(alphaName());
    const volVectorField& U = db().lookupObject<volVectorField>("U");

    const fvMesh& mesh = alpha.mesh();
	const word& patchName = this->patch().name();
	const label patchID = mesh.boundaryMesh().findPatchID(patchName);
    const label nF = patch().faceCells().size();

    const scalarField alphaCell = 
    	alpha.boundaryField()[patchID].patchInternalField();
    const vectorField UCell = U.boundaryField()[patchID].patchInternalField();
    scalarField UzCell = UCell.component(2);

    scalarField patchUc = Foam::scalarField(nF, 0.0); // Correction velocity
    scalarField patchVc = Foam::scalarField(nF, 0.0); // Correction velocity
    
    const scalarField patchHeight = patch().Cf().component(2)-cMin[2];
    
    const scalar g = 9.81;

    // Check for errors - Just the first time
    if (!allCheck_)
    {
        // Check if the value of nPaddles is correct for the number of columns
        if (nPaddles_ < 1)
        {
            FatalError
                << "Check nPaddles value."
                << exit(FatalError);
        }

        if ( nPaddles_ > 1 )
        {
            nPaddles_ = decreaseNPaddles( nPaddles_, patchD, dMin, dSpan );
            reduce(nPaddles_, minOp<label>());
        }

        // Check nEdges
        if ( nEdgeMin_ < 0 || nEdgeMax_ < 0 )
        {
            FatalError
                << "Check nEdgeMin/Max value."
                << exit(FatalError); 
        }

        if ( nEdgeMin_ + nEdgeMax_ > nPaddles_ )
        {
            FatalError
                << "Check: nEdges > nPaddles."
                << exit(FatalError); 
        }
    }

    // Grouping part
    labelList faceGroup = Foam::labelList(nF, 0);
    scalarList dBreakPoints = Foam::scalarList(nPaddles_+1, dMin); 
    scalarList xGroup = Foam::scalarList(nPaddles_, 0.0);
    scalarList yGroup = Foam::scalarList(nPaddles_, 0.0);

    for (label i=0; i<nPaddles_; i++)
    {
    	// Breakpoints, X & Y centre of the paddles
        dBreakPoints[i+1] = dMin + dSpan/(nPaddles_)*(i+1);
        xGroup[i] = cMin[0] + cSpan[0]/(2.0*nPaddles_) + cSpan[0]/(nPaddles_)*i;
        yGroup[i] = cMin[1] + cSpan[1]/(2.0*nPaddles_) + cSpan[1]/(nPaddles_)*i;
    }

    forAll(patchD, patchCells) 
    {
        for (label i=0; i<nPaddles_; i++)
        {
            if ( (patchD[patchCells]>=dBreakPoints[i]) && 
            	(patchD[patchCells]<dBreakPoints[i+1]) )
            {
                faceGroup[patchCells] = i+1; // Group of each face
                continue;
            }
        }      
    }

    if (!allCheck_)
    {
	    // Calculate Z bounds of the faces
	    scalarField zSup, zInf;
		faceBoundsZ( &zSup, &zInf );
        // Z-span paddlewise
        zSpanL_ = zSpanList( faceGroup, zInf, zSup );
        //inlinePrint( "Z-span paddlewise", zSpanL_ );

        // Calculate initial water depth
        if ( gMin(initialWaterDepths_) < 0.0 )
        {
            initialWaterDepths_ = calcWL( alphaCell, faceGroup, zSpanL_ );
            inlinePrint( "Initial water depths for absorption", 
            	initialWaterDepths_ );
        }

        // Absorption direction part
        meanAngles_ = initialWaterDepths_;

        // Check if absorption is directional
        if ( absorptionDir_ > 360.0 ) // Automatic
        {
            meanAngles_ = meanPatchDirs( faceGroup );
        }
        else // Fixed
        {
            meanAngles_ = absorptionDir_*PI()/180.0;
        }
        //inlinePrint( "Paddle angles", meanAngles_ );

        allCheck_ = true;
    }

    // Calculate water measured levels
    scalarList measuredLevels = calcWL( alphaCell, faceGroup, zSpanL_ );

    // Correction velocity: U = -sqrt(g/h)*corrL
    scalarList corrLevels = measuredLevels - initialWaterDepths_;
    inlinePrint( "Correction Levels", corrLevels );

    scalarList Uc = -sqrt(g/max(initialWaterDepths_,0.1))*corrLevels;

    // Limit in-flux
    for(label i=0; i<=nPaddles_-1; i++)
    {
        if( (i <= nEdgeMin_-1) || (i > nPaddles_-1-nEdgeMax_) )
        {
            if( pos(Uc[i]) )
            {
                Uc[i] = 0.0;
            }
        }
    }

    forAll(patchUc, cellIndex)    
    {
        patchUc[cellIndex] = pos(alphaCell[cellIndex]-0.9)*
        	Uc[faceGroup[cellIndex]-1]*cos(meanAngles_[faceGroup[cellIndex]-1]);
        patchVc[cellIndex] = pos(alphaCell[cellIndex]-0.9)*
        	Uc[faceGroup[cellIndex]-1]*sin(meanAngles_[faceGroup[cellIndex]-1]);
        UzCell[cellIndex] = pos(alphaCell[cellIndex]-0.9)*UzCell[cellIndex];
    }
Пример #24
0
void Foam::coupledPolyPatch::calcTransformTensors
(
    const vectorField& Cf,
    const vectorField& Cr,
    const vectorField& nf,
    const vectorField& nr,
    const scalarField& smallDist,
    const scalar absTol
) const
{
    if (debug)
    {
        Pout<< "coupledPolyPatch::calcTransformTensors : " << name() << endl
            << "    (half)size:" << Cf.size() << nl
            << "    absTol:" << absTol << nl
            << "    sum(mag(nf & nr)):" << sum(mag(nf & nr)) << endl;
    }

    // Tolerance calculation.
    // - normal calculation: assume absTol is the absolute error in a
    // single normal/transformation calculation. Consists both of numerical
    // precision (on the order of SMALL and of writing precision
    // (from e.g. decomposition)
    // Then the overall error of summing the normals is sqrt(size())*absTol
    // - separation calculation: pass in from the outside an allowable error.

    if (size() == 0)
    {
        // Dummy geometry.
        separation_.setSize(0);
        forwardT_ = I;
        reverseT_ = I;
    }
    else
    {
        scalar error = absTol*Foam::sqrt(1.0*Cf.size());

        if (debug)
        {
            Pout<< "    error:" << error << endl;
        }

        if (sum(mag(nf & nr)) < Cf.size() - error)
        {
            // Rotation, no separation

            separation_.setSize(0);

            forwardT_.setSize(Cf.size());
            reverseT_.setSize(Cf.size());

            forAll (forwardT_, facei)
            {
                forwardT_[facei] = rotationTensor(-nr[facei], nf[facei]);
                reverseT_[facei] = rotationTensor(nf[facei], -nr[facei]);
            }

            if (debug)
            {
                Pout<< "    sum(mag(forwardT_ - forwardT_[0])):"
                    << sum(mag(forwardT_ - forwardT_[0]))
                    << endl;
            }

            if (sum(mag(forwardT_ - forwardT_[0])) < error)
            {
                forwardT_.setSize(1);
                reverseT_.setSize(1);

                if (debug)
                {
                    Pout<< "    difference in rotation less than"
                        << " local tolerance "
                        << error << ". Assuming uniform rotation." << endl;
                }
            }
        }