calc function in ReactingMultiPhaseParcel

Discussion about how the calc function is called in ReactingMultiPhaseParcel class

The calc function called in ReactingMultiPhaseParcel.C:

For example, if we have a coalCloud object defined as:

1
2
3
4
5
6
7
8
coalCloud coalParcels
(
"coalCloud1",
rho,
U,
g,
slgThermo
);

If we call coalParcels.evolve(), we will call function evolve() defined in ReactingMultiphaseCloud.C:

1
2
3
4
5
6
7
8
9
10
template<class CloudType>
void Foam::ReactingMultiphaseCloud<CloudType>::evolve()
{
if (this->solution().canEvolve())
{
typename parcelType::trackingData td(*this);

this->solve(*this, td);// here
}
}

This will call the solve function defined in in KinematicCloud.C:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
template<class CloudType>
template<class TrackCloudType>
void Foam::KinematicCloud<CloudType>::solve
(
TrackCloudType& cloud,
typename parcelType::trackingData& td
)
{
if (solution_.steadyState())
{
cloud.storeState();

cloud.preEvolve();

evolveCloud(cloud, td);

if (solution_.coupled())
{
cloud.relaxSources(cloud.cloudCopy());
}
}
else
{
cloud.preEvolve();

evolveCloud(cloud, td);// here

if (solution_.coupled())
{
cloud.scaleSources();
}
}

cloud.info();

cloud.postEvolve();

if (solution_.steadyState())
{
cloud.restoreState();
}
}

In this function, the evolveCloud function (still defined in KinematicCloud.C as other class inherit from this class has no such function) will be called:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
template<class CloudType>
template<class TrackCloudType>
void Foam::KinematicCloud<CloudType>::evolveCloud
(
TrackCloudType& cloud,
typename parcelType::trackingData& td
)
{
if (solution_.coupled())
{
cloud.resetSourceTerms();
}

if (solution_.transient())
{
label preInjectionSize = this->size();

this->surfaceFilm().inject(cloud);

// Update the cellOccupancy if the size of the cloud has changed
// during the injection.
if (preInjectionSize != this->size())
{
updateCellOccupancy();
preInjectionSize = this->size();
}

injectors_.inject(cloud, td);


// Assume that motion will update the cellOccupancy as necessary
// before it is required.
cloud.motion(cloud, td);// here

stochasticCollision().update(td, solution_.trackTime());
}
else
{
// this->surfaceFilm().injectSteadyState(cloud);

injectors_.injectSteadyState(cloud, td, solution_.trackTime());

td.part() = parcelType::trackingData::tpLinearTrack;
CloudType::move(cloud, td, solution_.trackTime()); // or here
}
}

Here the cloud object will call the function motion which also defined in KinematicCloud.C:

1
2
3
4
5
6
7
8
9
10
11
12
13
template<class CloudType>
template<class TrackCloudType>
void Foam::KinematicCloud<CloudType>::motion
(
TrackCloudType& cloud,
typename parcelType::trackingData& td
)
{
td.part() = parcelType::trackingData::tpLinearTrack;
CloudType::move(cloud, td, solution_.trackTime());// here

updateCellOccupancy();
}

In this motion function, the move function defined in KinematicParcel.Cwill be called:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
template<class ParcelType>
template<class TrackCloudType>
bool Foam::KinematicParcel<ParcelType>::move
(
TrackCloudType& cloud,
trackingData& td,
const scalar trackTime
)
{
typename TrackCloudType::parcelType& p =
static_cast<typename TrackCloudType::parcelType&>(*this);
typename TrackCloudType::parcelType::trackingData& ttd =
static_cast<typename TrackCloudType::parcelType::trackingData&>(td);

ttd.switchProcessor = false;
ttd.keepParticle = true;

const scalarField& cellLengthScale = cloud.cellLengthScale();
const scalar maxCo = cloud.solution().maxCo();

while (ttd.keepParticle && !ttd.switchProcessor && p.stepFraction() < 1)
{
// Cache the current position, cell and step-fraction
const point start = p.position();
const scalar sfrac = p.stepFraction();

// Total displacement over the time-step
const vector s = trackTime*U_;

// Cell length scale
const scalar l = cellLengthScale[p.cell()];

// Deviation from the mesh centre for reduced-D cases
const vector d = p.deviationFromMeshCentre();

// Fraction of the displacement to track in this loop. This is limited
// to ensure that the both the time and distance tracked is less than
// maxCo times the total value.
scalar f = 1 - p.stepFraction();
f = min(f, maxCo);
f = min(f, maxCo*l/max(small*l, mag(s)));
if (p.active())
{
// Track to the next face
p.trackToFace(f*s - d, f);
}
else
{
// At present the only thing that sets active_ to false is a stick
// wall interaction. We want the position of the particle to remain
// the same relative to the face that it is on. The local
// coordinates therefore do not change. We still advance in time and
// perform the relevant interactions with the fixed particle.
p.stepFraction() += f;
}

const scalar dt = (p.stepFraction() - sfrac)*trackTime;

// Avoid problems with extremely small timesteps
if (dt > rootVSmall)
{
// Update cell based properties
p.setCellValues(cloud, ttd);

p.calcDispersion(cloud, ttd, dt);

if (cloud.solution().cellValueSourceCorrection())
{
p.cellValueSourceCorrection(cloud, ttd, dt);
}

p.calc(cloud, ttd, dt);//here!!!!!
}

p.age() += dt;

if (p.onFace())
{
cloud.functions().postFace(p, ttd.keepParticle);
}

cloud.functions().postMove(p, dt, start, ttd.keepParticle);

if (p.onFace() && ttd.keepParticle)
{
p.hitFace(s, cloud, ttd);
}
}

return ttd.keepParticle;
}

The p.calc(cloud, ttd, dt) will then call the calc function defined in the ReactingMultiphaseParcel.C. There, e.g. calcDevolatilisation will be called to update the model.