Skip to content
  • 最新
  • 版块
  • 东岳流体
  • 随机看[请狂点我]
皮肤
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(不使用皮肤)
  • 不使用皮肤
折叠
CFD中文网

CFD中文网

  1. CFD中文网
  2. OpenFOAM
  3. 分享以及讨论 欧拉拉格朗日模型中 ParcelCollector

分享以及讨论 欧拉拉格朗日模型中 ParcelCollector

已定时 已固定 已锁定 已移动 OpenFOAM
7 帖子 2 发布者 4.8k 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • 星 离线
    星 离线
    星星星星晴
    写于2020年5月15日 09:06 最后由 编辑
    #1

    下面是我修改的ParcelCollector.C 及.H 基于OF4.1
    目的是通过在domain中建立一个面(同心圆或多边形),对碰到该面的parcel进行一些统计。
    原code中只计算了mass 以及massflowrate。
    我在做喷雾,在validation中需要做一个sauter mean diameter(D32)VS axial diameter 的图。
    在试过其他方法并没有特别好的效果的情况下,试着修改了一下parcelcollector这个cloudfunction。

    #include "ParticleCollector.H"
    #include "Pstream.H"
    #include "surfaceWriter.H"
    #include "unitConversion.H"
    #include "Random.H"
    #include "triangle.H"
    #include "cloud.H"
    // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
    template<class CloudType>
    void Foam::ParticleCollector<CloudType>::makeLogFile
    (
    const faceList& faces,
    const Field<point>& points,
    const Field<scalar>& area
    )
    {
    // Create the output file if not already created
    if (log_)
    {
    if (debug)
    {
    Info<< "Creating output file" << endl;
    }
    if (Pstream::master())
    {
    // Create directory if does not exist
    mkDir(this->writeTimeDir());
    // Open new file at start up
    outputFilePtr_.reset
    (
    new OFstream(this->writeTimeDir()/(type() + ".dat"))
    );
    outputFilePtr_()
    << "# Source : " << type() << nl
    << "# Bins : " << faces.size() << nl
    << "# Total area : " << sum(area) << nl;
    outputFilePtr_()
    << "# Geometry :" << nl
    << '#'
    << tab << "Bin"
    << tab << "(Centre_x Centre_y Centre_z)"
    << tab << "Area"
    << nl;
    forAll(faces, i)
    {
    outputFilePtr_()
    << '#'
    << tab << i
    << tab << faces[i].centre(points)
    << tab << area[i]
    << nl;
    }
    outputFilePtr_()
    << '#' << nl
    << "# Output format:" << nl;
    forAll(faces, i)
    {
    word id = Foam::name(i);
    word binId = "bin_" + id;
    outputFilePtr_()
    << '#'
    << tab << "Time"
    << tab << binId
    << tab << "mass[" << id << "]"
    << tab << "massFlowRate[" << id << "]"
    << tab << "D3[" << id << "]"
    << tab << "D2[" << id << "]"
    << endl;
    }
    }
    }
    }
    template<class CloudType>
    void Foam::ParticleCollector<CloudType>::initPolygons
    (
    const List<Field<point>>& polygons
    )
    {
    mode_ = mtPolygon;
    label nPoints = 0;
    forAll(polygons, polyI)
    {
    label np = polygons[polyI].size();
    if (np < 3)
    {
    FatalIOErrorInFunction(this->coeffDict())
    << "polygons must consist of at least 3 points"
    << exit(FatalIOError);
    }
    nPoints += np;
    }
    label pointOffset = 0;
    points_.setSize(nPoints);
    faces_.setSize(polygons.size());
    faceTris_.setSize(polygons.size());
    area_.setSize(polygons.size());
    forAll(faces_, facei)
    {
    const Field<point>& polyPoints = polygons[facei];
    face f(identity(polyPoints.size()) + pointOffset);
    UIndirectList<point>(points_, f) = polyPoints;
    area_[facei] = f.mag(points_);
    DynamicList<face> tris;
    f.triangles(points_, tris);
    faceTris_[facei].transfer(tris);
    faces_[facei].transfer(f);
    pointOffset += polyPoints.size();
    }
    }
    template<class CloudType>
    void Foam::ParticleCollector<CloudType>::initConcentricCircles()
    {
    mode_ = mtConcentricCircle;
    vector origin(this->coeffDict().lookup("origin"));
    radius_ = this->coeffDict().lookup("radius");
    nSector_ = readLabel(this->coeffDict().lookup("nSector"));
    label nS = nSector_;
    vector refDir;
    if (nSector_ > 1)
    {
    refDir = this->coeffDict().lookup("refDir");
    refDir -= normal_[0]*(normal_[0] & refDir);
    refDir /= mag(refDir);
    }
    else
    {
    // set 4 quadrants for single sector cases
    nS = 4;
    vector tangent = Zero;
    scalar magTangent = 0.0;
    Random rnd(1234);
    while (magTangent < SMALL)
    {
    vector v = rnd.vector01();
    tangent = v - (v & normal_[0])*normal_[0];
    magTangent = mag(tangent);
    }
    refDir = tangent/magTangent;
    }
    scalar dTheta = 5.0;
    scalar dThetaSector = 360.0/scalar(nS);
    label intervalPerSector = max(1, ceil(dThetaSector/dTheta));
    dTheta = dThetaSector/scalar(intervalPerSector);
    label nPointPerSector = intervalPerSector + 1;
    label nPointPerRadius = nS*(nPointPerSector - 1);
    label nPoint = radius_.size()*nPointPerRadius;
    label nFace = radius_.size()*nS;
    // add origin
    nPoint++;
    points_.setSize(nPoint);
    faces_.setSize(nFace);
    area_.setSize(nFace);
    coordSys_ = cylindricalCS("coordSys", origin, normal_[0], refDir, false);
    List<label> ptIDs(identity(nPointPerRadius));
    points_[0] = origin;
    // points
    forAll(radius_, radI)
    {
    label pointOffset = radI*nPointPerRadius + 1;
    for (label i = 0; i < nPointPerRadius; i++)
    {
    label pI = i + pointOffset;
    point pCyl(radius_[radI], degToRad(i*dTheta), 0.0);
    points_[pI] = coordSys_.globalPosition(pCyl);
    }
    }
    // faces
    DynamicList<label> facePts(2*nPointPerSector);
    forAll(radius_, radI)
    {
    if (radI == 0)
    {
    for (label secI = 0; secI < nS; secI++)
    {
    facePts.clear();
    // append origin point
    facePts.append(0);
    for (label ptI = 0; ptI < nPointPerSector; ptI++)
    {
    label i = ptI + secI*(nPointPerSector - 1);
    label id = ptIDs.fcIndex(i - 1) + 1;
    facePts.append(id);
    }
    label facei = secI + radI*nS;
    faces_[facei] = face(facePts);
    area_[facei] = faces_[facei].mag(points_);
    }
    }
    else
    {
    for (label secI = 0; secI < nS; secI++)
    {
    facePts.clear();
    label offset = (radI - 1)*nPointPerRadius + 1;
    for (label ptI = 0; ptI < nPointPerSector; ptI++)
    {
    label i = ptI + secI*(nPointPerSector - 1);
    label id = offset + ptIDs.fcIndex(i - 1);
    facePts.append(id);
    }
    for (label ptI = nPointPerSector-1; ptI >= 0; ptI--)
    {
    label i = ptI + secI*(nPointPerSector - 1);
    label id = offset + nPointPerRadius + ptIDs.fcIndex(i - 1);
    facePts.append(id);
    }
    label facei = secI + radI*nS;
    faces_[facei] = face(facePts);
    area_[facei] = faces_[facei].mag(points_);
    }
    }
    }
    }
    template<class CloudType>
    void Foam::ParticleCollector<CloudType>::collectParcelPolygon
    (
    const point& p1,
    const point& p2
    ) const
    {
    label dummyNearType = -1;
    label dummyNearLabel = -1;
    forAll(faces_, facei)
    {
    const label facePoint0 = faces_[facei][0];
    const point& pf = points_[facePoint0];
    const scalar d1 = normal_[facei] & (p1 - pf);
    const scalar d2 = normal_[facei] & (p2 - pf);
    if (sign(d1) == sign(d2))
    {
    // did not cross polygon plane
    continue;
    }
    // intersection point
    const point pIntersect = p1 + (d1/(d1 - d2))*(p2 - p1);
    const List<face>& tris = faceTris_[facei];
    // identify if point is within poly bounds
    forAll(tris, triI)
    {
    const face& tri = tris[triI];
    triPointRef t
    (
    points_[tri[0]],
    points_[tri[1]],
    points_[tri[2]]
    );
    if (t.classify(pIntersect, dummyNearType, dummyNearLabel))
    {
    hitFaceIDs_.append(facei);
    }
    }
    }
    }
    template<class CloudType>
    void Foam::ParticleCollector<CloudType>::collectParcelConcentricCircles
    (
    const point& p1,
    const point& p2
    ) const
    {
    label secI = -1;
    const scalar d1 = normal_[0] & (p1 - coordSys_.origin());
    const scalar d2 = normal_[0] & (p2 - coordSys_.origin());
    if (sign(d1) == sign(d2))
    {
    // did not cross plane
    return;
    }
    // intersection point in cylindrical co-ordinate system
    const point pCyl = coordSys_.localPosition(p1 + (d1/(d1 - d2))*(p2 - p1));
    scalar r = pCyl[0];
    if (r < radius_.last())
    {
    label radI = 0;
    while (r > radius_[radI])
    {
    radI++;
    }
    if (nSector_ == 1)
    {
    secI = 4*radI;
    }
    else
    {
    scalar theta = pCyl[1] + constant::mathematical::pi;
    secI =
    nSector_*radI
    + floor
    (
    scalar(nSector_)*theta/constant::mathematical::twoPi
    );
    }
    }
    hitFaceIDs_.append(secI);
    }
    template<class CloudType>
    void Foam::ParticleCollector<CloudType>::write()
    {
    const fvMesh& mesh = this->owner().mesh();
    const Time& time = mesh.time();
    scalar timeNew = time.value();
    scalar timeElapsed = timeNew - timeOld_;
    totalTime_ += timeElapsed;
    const scalar alpha = (totalTime_ - timeElapsed)/totalTime_;
    const scalar beta = timeElapsed/totalTime_;
    forAll(faces_, facei)
    {
    massFlowRate_[facei] =
    alpha*massFlowRate_[facei] + beta*mass_[facei]/timeElapsed;
    massTotal_[facei] += mass_[facei];
    d3Total_[facei] += d3_[facei];
    d2Total_[facei] += d2_[facei];
    }
    const label proci = Pstream::myProcNo();
    Field<scalar> faceMassTotal(mass_.size(), 0.0);
    this->getModelProperty("massTotal", faceMassTotal);
    Field<scalar> faceMassFlowRate(massFlowRate_.size(), 0.0);
    this->getModelProperty("massFlowRate", faceMassFlowRate);
    Field<scalar> faceD3Total(d3_.size(), 0.0);
    this->getModelProperty("d3Total", faceD3Total);
    Field<scalar> faceD2Total(d2_.size(), 0.0);
    this->getModelProperty("d2Total", faceD2Total);
    scalar sumTotalMass = 0.0;
    scalar sumAverageMFR = 0.0;
    scalar sumTotalD3 = 0.0;
    scalar sumTotalD2 = 0.0;
    forAll(faces_, facei)
    {
    scalarList allProcMass(Pstream::nProcs());
    allProcMass[proci] = massTotal_[facei];
    Pstream::gatherList(allProcMass);
    faceMassTotal[facei] += sum(allProcMass);
    scalarList allProcMassFlowRate(Pstream::nProcs());
    allProcMassFlowRate[proci] = massFlowRate_[facei];
    Pstream::gatherList(allProcMassFlowRate);
    faceMassFlowRate[facei] += sum(allProcMassFlowRate);
    scalarList allProcD3(Pstream::nProcs());
    allProcD3[proci] = d3Total_[facei];
    Pstream::gatherList(allProcD3);
    faceD3Total[facei] += sum(allProcD3);
    scalarList allProcD2(Pstream::nProcs());
    allProcD2[proci] = d2Total_[facei];
    Pstream::gatherList(allProcD2);
    faceD2Total[facei] += sum(allProcD2);
    sumTotalMass += faceMassTotal[facei];
    sumAverageMFR += faceMassFlowRate[facei];
    sumTotalD3 += faceD3Total[facei];
    sumTotalD2 += faceD2Total[facei];
    //- Display values for each face
    if (outputFilePtr_.valid())
    {
    outputFilePtr_()
    << time.timeName()
    << tab << facei
    << tab << faceMassTotal[facei]
    << tab << faceMassFlowRate[facei]
    << tab << faceD3Total[facei]
    << tab << faceD2Total[facei]
    << endl;
    }
    }
    Info<< " sum(total mass) = " << sumTotalMass << nl
    << " sum(average mass flow rate) = " << sumAverageMFR << nl
    << " sum(total d3) = " << sumTotalD3 << nl
    << " sum(total d2) = " << sumTotalD2 << nl
    << " radius.size = " << radius_.size() << nl
    << endl;
    if (surfaceFormat_ != "none")
    {
    if (Pstream::master())
    {
    autoPtr<surfaceWriter> writer(surfaceWriter::New(surfaceFormat_));
    writer->write
    (
    this->writeTimeDir(),
    "collector",
    points_,
    faces_,
    "massTotal",
    faceMassTotal,
    false
    );
    writer->write
    (
    this->writeTimeDir(),
    "collector",
    points_,
    faces_,
    "massFlowRate",
    faceMassFlowRate,
    false
    );
    writer->write
    (
    this->writeTimeDir(),
    "collector",
    points_,
    faces_,
    "d3Total",
    faceD3Total,
    false
    );
    writer->write
    (
    this->writeTimeDir(),
    "collector",
    points_,
    faces_,
    "d2Total",
    faceD2Total,
    false
    );
    }
    }
    if (resetOnWrite_)
    {
    Field<scalar> dummy(faceMassTotal.size(), 0.0);
    this->setModelProperty("massTotal", dummy);
    this->setModelProperty("massFlowRate", dummy);
    this->setModelProperty("d3Total", dummy);
    this->setModelProperty("d2Total", dummy);
    timeOld_ = timeNew;
    totalTime_ = 0.0;
    }
    else
    {
    this->setModelProperty("massTotal", faceMassTotal);
    this->setModelProperty("massFlowRate", faceMassFlowRate);
    this->setModelProperty("d3Total", faceD3Total);
    this->setModelProperty("d2Total", faceD2Total);
    }
    forAll(faces_, facei)
    {
    mass_[facei] = 0.0;
    massTotal_[facei] = 0.0;
    massFlowRate_[facei] = 0.0;
    d3_[facei] = 0.0;
    d3Total_[facei] = 0.0;
    d2_[facei] = 0.0;
    d2Total_[facei] = 0.0;
    }
    }
    // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
    template<class CloudType>
    Foam::ParticleCollector<CloudType>::ParticleCollector
    (
    const dictionary& dict,
    CloudType& owner,
    const word& modelName
    )
    :
    CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
    mode_(mtUnknown),
    parcelType_(this->coeffDict().lookupOrDefault("parcelType", -1)),
    removeCollected_(this->coeffDict().lookup("removeCollected")),
    points_(),
    faces_(),
    faceTris_(),
    nSector_(0),
    radius_(),
    coordSys_(false),
    normal_(),
    negateParcelsOppositeNormal_
    (
    readBool(this->coeffDict().lookup("negateParcelsOppositeNormal"))
    ),
    surfaceFormat_(this->coeffDict().lookup("surfaceFormat")),
    resetOnWrite_(this->coeffDict().lookup("resetOnWrite")),
    totalTime_(0.0),
    mass_(),
    massTotal_(),
    massFlowRate_(),
    d3_(),
    d2_(),
    d3Total_(),
    d2Total_(),
    log_(this->coeffDict().lookup("log")),
    outputFilePtr_(),
    timeOld_(owner.mesh().time().value()),
    hitFaceIDs_()
    {
    normal_ /= mag(normal_);
    word mode(this->coeffDict().lookup("mode"));
    if (mode == "polygon")
    {
    List<Field<point>> polygons(this->coeffDict().lookup("polygons"));
    initPolygons(polygons);
    vector n0(this->coeffDict().lookup("normal"));
    normal_ = vectorField(faces_.size(), n0);
    }
    else if (mode == "polygonWithNormal")
    {
    List<Tuple2<Field<point>, vector>> polygonAndNormal
    (
    this->coeffDict().lookup("polygons")
    );
    List<Field<point>> polygons(polygonAndNormal.size());
    normal_.setSize(polygonAndNormal.size());
    forAll(polygons, polyI)
    {
    polygons[polyI] = polygonAndNormal[polyI].first();
    normal_[polyI] = polygonAndNormal[polyI].second();
    normal_[polyI] /= mag(normal_[polyI]) + ROOTVSMALL;
    }
    initPolygons(polygons);
    }
    else if (mode == "concentricCircle")
    {
    vector n0(this->coeffDict().lookup("normal"));
    normal_ = vectorField(1, n0);
    initConcentricCircles();
    }
    else
    {
    FatalIOErrorInFunction(this->coeffDict())
    << "Unknown mode " << mode << ". Available options are "
    << "polygon, polygonWithNormal and concentricCircle"
    << exit(FatalIOError);
    }
    mass_.setSize(faces_.size(), 0.0);
    massTotal_.setSize(faces_.size(), 0.0);
    massFlowRate_.setSize(faces_.size(), 0.0);
    d3_.setSize(faces_.size(), 0.0);
    d2_.setSize(faces_.size(), 0.0);
    d3Total_.setSize(faces_.size(), 0.0);
    d2Total_.setSize(faces_.size(), 0.0);
    makeLogFile(faces_, points_, area_);
    }
    template<class CloudType>
    Foam::ParticleCollector<CloudType>::ParticleCollector
    (
    const ParticleCollector<CloudType>& pc
    )
    :
    CloudFunctionObject<CloudType>(pc),
    mode_(pc.mode_),
    parcelType_(pc.parcelType_),
    removeCollected_(pc.removeCollected_),
    points_(pc.points_),
    faces_(pc.faces_),
    faceTris_(pc.faceTris_),
    nSector_(pc.nSector_),
    radius_(pc.radius_),
    coordSys_(pc.coordSys_),
    normal_(pc.normal_),
    negateParcelsOppositeNormal_(pc.negateParcelsOppositeNormal_),
    surfaceFormat_(pc.surfaceFormat_),
    resetOnWrite_(pc.resetOnWrite_),
    totalTime_(pc.totalTime_),
    mass_(pc.mass_),
    massTotal_(pc.massTotal_),
    massFlowRate_(pc.massFlowRate_),
    d3_(pc.d3_),
    d2_(pc.d2_),
    d3Total_(pc.d3Total_),
    d2Total_(pc.d2Total_),
    log_(pc.log_),
    outputFilePtr_(),
    timeOld_(0.0),
    hitFaceIDs_()
    {}
    // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
    template<class CloudType>
    Foam::ParticleCollector<CloudType>::~ParticleCollector()
    {}
    // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
    template<class CloudType>
    void Foam::ParticleCollector<CloudType>::postMove
    (
    parcelType& p,
    const label celli,
    const scalar dt,
    const point& position0,
    bool& keepParticle
    )
    {
    if ((parcelType_ != -1) && (parcelType_ != p.typeId()))
    {
    return;
    }
    // slightly extend end position to avoid falling within tracking tolerances
    const point position1 = position0 + 1.0001*(p.position() - position0);
    hitFaceIDs_.clear();
    switch (mode_)
    {
    case mtPolygon:
    {
    collectParcelPolygon(position0, position1);
    break;
    }
    case mtConcentricCircle:
    {
    collectParcelConcentricCircles(position0, position1);
    break;
    }
    default:
    {
    }
    }
    forAll(hitFaceIDs_, i)
    {
    label facei = hitFaceIDs_[i];
    scalar m = p.nParticle() * p.mass();
    scalar d3p = p.nParticle() * p.d() * p.d()* p.d();
    scalar d2p = p.nParticle() * p.d() * p.d();
    if (negateParcelsOppositeNormal_)
    {
    vector Uhat = p.U();
    Uhat /= mag(Uhat) + ROOTVSMALL;
    if ((Uhat & normal_[facei]) < 0)
    {
    m *= -1.0;
    }
    }
    // add mass contribution
    mass_[facei] += m;
    d2_[facei] += d2p;
    d3_[facei] += d3p;
    if (nSector_ == 1)
    {
    mass_[facei + 1] += m;
    mass_[facei + 2] += m;
    mass_[facei + 3] += m;
    d2_[facei + 1] += d2p;
    d2_[facei + 2] += d2p;
    d2_[facei + 3] += d2p;
    d3_[facei + 1] += d3p;
    d3_[facei + 2] += d3p;
    d3_[facei + 3] += d3p;
    }
    if (removeCollected_)
    {
    keepParticle = false;
    }
    }
    }
    #ifndef ParticleCollector_H
    #define ParticleCollector_H
    #include "CloudFunctionObject.H"
    #include "cylindricalCS.H"
    #include "face.H"
    #include "Switch.H"
    #include "OFstream.H"
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    namespace Foam
    {
    /*---------------------------------------------------------------------------*\
    Class ParticleCollector Declaration
    \*---------------------------------------------------------------------------*/
    template<class CloudType>
    class ParticleCollector
    :
    public CloudFunctionObject<CloudType>
    {
    public:
    enum modeType
    {
    mtPolygon,
    mtConcentricCircle,
    mtUnknown
    };
    private:
    // Private Data
    // Typedefs
    //- Convenience typedef for parcel type
    typedef typename CloudType::parcelType parcelType;
    //- Collector mode type
    modeType mode_;
    //- Index of parcel types to collect (-1 by default = all particles)
    const label parcelType_;
    //- Flag to remove collected particles
    Switch removeCollected_;
    //- List of points
    Field<point> points_;
    //- List of faces
    List<face> faces_;
    // Polygon collector
    //- Triangulation of faces
    List<List<face>> faceTris_;
    // Concentric circles collector
    //- Number of sectors per circle
    label nSector_;
    //- List of radii
    List<scalar> radius_;
    //- Cylindrical co-ordinate system
    cylindricalCS coordSys_;
    //- Face areas
    Field<scalar> area_;
    //- Polygon normal vector per face
    Field<vector> normal_;
    //- Remove mass of parcel travelling in opposite direction to normal_
    bool negateParcelsOppositeNormal_;
    //- Surface output format
    const word surfaceFormat_;
    //- Flag to indicate whether data should be reset/cleared on writing
    Switch resetOnWrite_;
    //- Total time
    scalar totalTime_;
    //- Mass storage
    List<scalar> mass_;
    //- Mass total storage
    List<scalar> massTotal_;
    //- Mass flow rate storage
    List<scalar> massFlowRate_;
    List<scalar> d3_;
    List<scalar> d2_;
    List<scalar> d3Total_;
    List<scalar> d2Total_;
    //- Flag to indicate whether data should be written to file
    Switch log_;
    //- Output file pointer
    autoPtr<OFstream> outputFilePtr_;
    //- Last calculation time
    scalar timeOld_;
    //- Work list to store which faces are hit
    mutable DynamicList<label> hitFaceIDs_;
    // Private Member Functions
    //- Helper function to create log files
    void makeLogFile
    (
    const faceList& faces,
    const Field<point>& points,
    const Field<scalar>& area
    );
    //- Initialise polygon collectors
    void initPolygons(const List<Field<point>>& polygons);
    //- Initialise concentric circle collectors
    void initConcentricCircles();
    //- Collect parcels in polygon collectors
    void collectParcelPolygon
    (
    const point& p1,
    const point& p2
    ) const;
    //- Collect parcels in concentric circle collectors
    void collectParcelConcentricCircles
    (
    const point& p1,
    const point& p2
    ) const;
    protected:
    // Protected Member Functions
    //- Write post-processing info
    void write();
    public:
    //- Runtime type information
    TypeName("particleCollector");
    // Constructors
    //- Construct from dictionary
    ParticleCollector
    (
    const dictionary& dict,
    CloudType& owner,
    const word& modelName
    );
    //- Construct copy
    ParticleCollector(const ParticleCollector<CloudType>& pc);
    //- Construct and return a clone
    virtual autoPtr<CloudFunctionObject<CloudType>> clone() const
    {
    return autoPtr<CloudFunctionObject<CloudType>>
    (
    new ParticleCollector<CloudType>(*this)
    );
    }
    //- Destructor
    virtual ~ParticleCollector();
    // Member Functions
    // Access
    //- Return const access to the reset on write flag
    inline const Switch& resetOnWrite() const;
    // Evaluation
    //- Post-move hook
    virtual void postMove
    (
    parcelType& p,
    const label celli,
    const scalar dt,
    const point& position0,
    bool& keepParticle
    );
    };
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    } // End namespace Foam
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    #include "ParticleCollectorI.H"
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    #ifdef NoRepository
    #include "ParticleCollector.C"
    #endif
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    #endif
    // ************************************************************************* //

    游荡

    1 条回复 最后回复
  • 星 离线
    星 离线
    星星星星晴
    写于2020年5月15日 09:08 最后由 编辑
    #2

    现在的情况是这样的,在相同位置有不同的particlecollector,但是得到的数据就完全不同。

     particleCollector1
        {
            type            particleCollector;
            mode            concentricCircle;
            origin          (0.0 0.0 0.975);
            radius          (0.19999);
            nSector         1;
            refDir          (1 0 0);
            normal          (0 0 1);
            negateParcelsOppositeNormal no;
            removeCollected no;
            surfaceFormat   vtk;
            resetOnWrite    no;
            log             yes;
       }
    
     particleCollector2
        {
            type            particleCollector;
            mode            concentricCircle;
            origin          (0.0 0.0 0.975);
            radius          (0.0005 0.0015 0.0025 0.0035 
    0.0045 0.0055 0.0065 0.0075 
    0.0085 0.0095 0.0105 0.0115 
    0.0125 0.0135 0.0145 0.0155 
    0.0165 0.0175 0.0185 0.0195 
    0.0205 0.0215 0.0225 0.0235 
    0.0245 0.0255 0.0265 0.0275 
    0.0285 0.0295 0.0305 0.05 
    0.075 0.1 0.15 0.19999);
            nSector         1;
            refDir          (1 0 0);
            normal          (0 0 1);
            negateParcelsOppositeNormal no;
            removeCollected no;
            surfaceFormat   vtk;
            resetOnWrite    no;
            log             yes;
        }
    
     particleCollector3
        {
            type            particleCollector;
            mode            concentricCircle;
            origin          (0.0 0.0 0.975);
            radius          (0.0005 0.0015 0.0025 0.0035 0.05 0.075 0.1 0.15 0.19999);
            nSector         1;
            refDir          (1 0 0);
            normal          (0 0 1);
            negateParcelsOppositeNormal no;
            removeCollected no;
            surfaceFormat   vtk;
            resetOnWrite    no;
            log             yes;
        }
    
    

    输出结果如下。

        sum(total mass) = 1.75085e-05
        sum(average mass flow rate) = 0.0875421
        sum(total d3) = 3.34387e-08
        sum(total d2) = 0.000615982
        radius.size = 1
        nSector_ = 1
    
        sum(total mass) = 3.51273e-05
        sum(average mass flow rate) = 0.175637
        sum(total d3) = 6.70882e-08
        sum(total d2) = 0.00122567
        radius.size = 36
        nSector_ = 1
    
        sum(total mass) = 1.51653e-05
        sum(average mass flow rate) = 0.0758266
        sum(total d3) = 2.89636e-08
        sum(total d2) = 0.000605451
        radius.size = 9
        nSector_ = 1
    
    

    如果说 mass和 massflow rate是相同的话,我可以理解,因为这个是原生的部分,我并没有修改什么,但是现在就输出成这个样子,我就很费解了。。希望大神能帮忙看一下

    游荡

    chengan.wangC 1 条回复 最后回复 2022年8月28日 03:00
  • chengan.wangC 离线
    chengan.wangC 离线
    chengan.wang
    在 2022年8月28日 03:00 中回复了 星星星星晴 最后由 编辑
    #3

    @星星星星晴 相同的位置统计数据不一样,这个您找到原因了么?有点晕,不知道该怎么统计数据了。还有您的验证validation,sauter mean diameter(D32)VS axial diameter 的图,方便发出来做为一个标准验证么?

    星 1 条回复 最后回复 2022年8月28日 08:45
  • 星 离线
    星 离线
    星星星星晴
    在 2022年8月28日 08:45 中回复了 chengan.wang 最后由 编辑
    #4

    @chengan-wang 我在别的帖子和你说过啦,我后来不用particlecollector这个原生的,就是输出文件,对文件的数据分析,python matlab,excel都行,剩下就是统计了

    游荡

    chengan.wangC 1 条回复 最后回复 2022年9月1日 07:49
  • chengan.wangC 离线
    chengan.wangC 离线
    chengan.wang
    在 2022年9月1日 07:49 中回复了 星星星星晴 最后由 编辑
    #5

    @星星星星晴 您好,我有几个参数想请教您,
    1.您的算例中radius分别设定1个,36个和9个数据,代表采集不同同心圆的数据?
    2.nSector,自带算例设成10, 您设的是1。源代码里面Number of sectors per circle,这个怎么考虑
    3.refDir代表啥意思呢?好像跟nSector数量还有关系
    打扰了

    星 1 条回复 最后回复 2022年9月1日 08:33
  • 星 离线
    星 离线
    星星星星晴
    在 2022年9月1日 08:33 中回复了 chengan.wang 最后由 编辑
    #6

    @chengan-wang 不好意思,我研究了我能用的部分我就再没看了,如果你研究明白了,可以分享一下。自己查code,做几个实验code

    游荡

    chengan.wangC 1 条回复 最后回复 2022年9月4日 02:52
  • chengan.wangC 离线
    chengan.wangC 离线
    chengan.wang
    在 2022年9月4日 02:52 中回复了 星星星星晴 最后由 编辑
    #7

    @星星星星晴 感觉nSector不能设为1,最后输出的sum(total mass),sum(average mass flow rate)是nSector>1的4倍左右。

    if (nSector_ > 1)
    {
    refDir = this->coeffDict().lookup("refDir");
    refDir -= normal_[0]*(normal_[0] & refDir);
    refDir /= mag(refDir);
    }
    else
    {
    // set 4 quadrants for single sector cases
    nS = 4;
    vector tangent = vector::zero;
    scalar magTangent = 0.0;
    Random rnd(1234);
    while (magTangent < SMALL)
    {
    vector v = rnd.vector01();
    tangent = v - (v & normal_[0])*normal_[0];
    magTangent = mag(tangent);
    }
    refDir = tangent/magTangent;
    }

    可能跟源代码中nS = 4;有关系

    1 条回复 最后回复
2020年5月15日 09:06

1/7

2020年5月15日 09:06

未读 6
2022年9月4日 02:52
  • 登录

  • 登录或注册以进行搜索。
1 / 7
  • 第一个帖子
    1/7
    最后一个帖子
0
  • 最新
  • 版块
  • 东岳流体
  • 随机看[请狂点我]