Skip to content

Commit ee37e0f

Browse files
ANSYS Fluent DPM incorporation in PeleLMeX (#547)
* Changes made to include dpm reading * Reading particles through io processor only * Added time periodic injection * Corrected number density * Added subroutine to write spray temporal * Added restart capability * Corrected turbinflow to include turbulence injection * Corrected some bugs * changing abs to fabs * ndecane-isododecane mechanism (Samah's HEFA surrogate) * add 4sp nonreacting mechanism for HEFA surrogate * posf10325/A2/Jet-A HyChem model added * Added submodules * add posf10325 qss mech * add Make.package files * Added Make.package file * note posf10325 mech is high temp only * newer HEFA surrogate mechanism from Samah - nonreacting version * new HEFA surrogate from Samah - reacting * Added coordinate transformation for spray particles using FluentDPM * added submodules * added submo * Clang Tidyied * CT * Spell check correction done * Removed all unnecessary changes * Clang format * Clang format * temp changes * added sub * made changes to be more generic * Corrected some bugs with git merge * removed extra line * Initial commit * reformatted * adding new changes * clang format * merge bugs * formatting converter.py * updated submodules * Added documentation for Fluent DPM capability * Corrected bug in doc * Added doc about DPM file format * Removed table. Sphinx throws an error I am unable to resolve. Hence, provided the description as text * removed ndecane and nundecane mechanisms * first step in addressing github review * formatted * formatted * Second time addressing github pr feedback * Formatting * debug * Addressing github pr * Addressed warnings in checks * clang tidyied * Clang tidyied * removed a bug * added nolint to suppress unnecessary warning * removed unnecessary files * clang tidyied * Unsuppressed statements related to end_time * fixing bug * clang-format * const some functions in fluent dpm * more amrex mpi namespace corrections * fix for amrex RealVect changes --------- Co-authored-by: Bruce Perry <bruce.perry@nrel.gov>
1 parent 170ef8e commit ee37e0f

File tree

10 files changed

+638
-84
lines changed

10 files changed

+638
-84
lines changed

Docs/sphinx/Spray.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,18 @@ Care must be taken to ensure the amount of mass injected during a time step matc
430430

431431
4. If injection occurs, the amount of mass injected, :math:`m_{\rm{actual}}`, is summed and compared with the desired mass flow rate. If :math:`m_{\rm{actual}} / t_{\rm{inj}} - \dot{m}_{\rm{inj}} > 0.05 \dot{m}_{\rm{inj}}`, then :math:`N_{P,\min}` is increased by one to reduce the likelihood of over-injecting in the future. A balance is necessary: the higher the minimum number of parcels, the less likely to over-inject mass but the number of time steps between injections can potentially grow as well.
432432

433+
Spray data derived from ANSYS Fluent DPM solution files can also be used to inject spray particles into the fluid domain. To use this feature, initialize a spray jet (named ``jet_dpm``, say) by using the statement `spray.jetnames=jet_dpm` in the input file as previously mentioned. In order to use the ANSYS Fluent DPM capability, set the boolean input variable ``spray.jet_dpm.read_from_dpm_file`` to true and specify the DPM file name by ``spray.jet_dpm.dpm_filename=<filename>``.
434+
The DPM data in the file will correspond to a specified time-gap, but it can be made to repeat periodically by specifying ``spray.jet_dpm.is_dpm_periodic=true``. Otherwise, spray particle injection will cease after the final DPM time is reached. The spray injection can be set to start from a specific DPM time stamp by specifying
435+
``spray.jet_dpm.initial_injection_dpm_time=<DPM time stamp>``. Similarly, the spray injection can also be set to start from a specific flow time by setting ``spray.jet_dpm.initial_injection_flow_time`` to the appropriate value. If the coordinate system used in the ANSYS Fluent DPM file is different from that in Pele,
436+
one can use ``spray.jet_dpm.trans_matrix`` and ``spray.jet_dpm.translation`` to specify the direction cosine matrix (3X3 matrix) and the translation vector (<dx,dy,dz>) to align both the coordinate systems.
437+
438+
439+
The DPM file has a specific format and a typical file is shown below:
440+
441+
.. figure:: /Visualization/DPMFileFormat.png
442+
:align: center
443+
:figwidth: 60%
444+
433445
Spray Validation
434446
================
435447

184 KB
Loading

Source/Spray/SprayIO.cpp

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,22 @@ SprayParticleContainer::SprayParticleIO(
8282
if (!file.good()) {
8383
FileOpenFailed(filename);
8484
}
85-
file << js->jet_name() << " " << js->num_ppp() << " "
86-
<< js->m_sumInjMass << " " << js->m_sumInjTime << " "
87-
<< js->m_minParcel << " " << js->m_totalInjMass << " "
88-
<< js->m_totalInjTime << "\n";
85+
if (js->m_use_Fluentdpmfile) {
86+
file << js->jet_name() << " " << js->num_ppp() << " "
87+
<< js->m_sumInjMass << " " << js->m_sumInjTime << " "
88+
<< js->m_minParcel << " " << js->m_totalInjMass << " "
89+
<< js->m_totalInjTime << " "
90+
<< js->get_flow_time_initial_injection() << " "
91+
<< js->get_dpm_time_initial_injection() << " "
92+
<< js->m_nxt_inj_flw_time << " " << js->m_cur_inj_dpm_time
93+
<< "\n";
94+
} else {
95+
file << js->jet_name() << " " << js->num_ppp() << " "
96+
<< js->m_sumInjMass << " " << js->m_sumInjTime << " "
97+
<< js->m_minParcel << " " << js->m_totalInjMass << " "
98+
<< js->m_totalInjTime << "\n";
99+
}
100+
89101
file.flush();
90102
file.close();
91103
if (!file.good()) {
@@ -130,10 +142,37 @@ SprayParticleContainer::PostInitRestart(const std::string& dir)
130142
Vector<Real> in_min_parcel(in_numjets);
131143
Vector<Real> in_total_mass(in_numjets);
132144
Vector<Real> in_total_time(in_numjets);
145+
Vector<Real> fluentdpm_inj_init_flw_time(in_numjets);
146+
Vector<Real> fluentdpm_inj_init_dpm_time(in_numjets);
147+
Vector<Real> fluentdpm_inj_nxt_flw_time(in_numjets);
148+
Vector<Real> fluentdpm_inj_nxt_dpm_time(in_numjets);
149+
133150
for (int i = 0; i < in_numjets; ++i) {
134151
JetDataFile >> in_jet_names[i] >> in_inj_ppp[i] >> in_inj_mass[i] >>
135152
in_inj_time[i] >> in_min_parcel[i] >> in_total_mass[i] >>
136153
in_total_time[i];
154+
155+
std::string in_name = in_jet_names[i];
156+
157+
bool jet_is_fluent_dpm_based = false;
158+
// Find if the jet is a fluentdpm based jet
159+
for (int mjets = 0; mjets < numjets; ++mjets) {
160+
SprayJet* js = m_sprayJets[mjets].get();
161+
162+
if (
163+
js->jet_name() == in_name && js->m_use_Fluentdpmfile &&
164+
!js->m_rstrt_Fltdpmsim_from_nonFltDPMChckPointFile) {
165+
JetDataFile >> fluentdpm_inj_init_flw_time[i] >>
166+
fluentdpm_inj_init_dpm_time[i] >> fluentdpm_inj_nxt_flw_time[i] >>
167+
fluentdpm_inj_nxt_dpm_time[i];
168+
jet_is_fluent_dpm_based = true;
169+
}
170+
if (jet_is_fluent_dpm_based) // Not fluent dpm based. Read the values
171+
// the old way
172+
{
173+
break;
174+
}
175+
}
137176
}
138177
for (int ijets = 0; ijets < in_numjets; ++ijets) {
139178
std::string in_name = in_jet_names[ijets];
@@ -146,6 +185,23 @@ SprayParticleContainer::PostInitRestart(const std::string& dir)
146185
js->m_minParcel = in_min_parcel[ijets];
147186
js->m_totalInjMass = in_total_mass[ijets];
148187
js->m_totalInjTime = in_total_time[ijets];
188+
189+
if (
190+
js->m_use_Fluentdpmfile &&
191+
!js->m_rstrt_Fltdpmsim_from_nonFltDPMChckPointFile) {
192+
js->set_initial_injection_flow_time(
193+
fluentdpm_inj_init_flw_time[ijets]);
194+
js->set_initial_injection_dpm_time(
195+
fluentdpm_inj_init_dpm_time[ijets]);
196+
js->m_nxt_inj_flw_time = fluentdpm_inj_nxt_flw_time[ijets];
197+
js->m_cur_inj_dpm_time = fluentdpm_inj_nxt_dpm_time[ijets];
198+
199+
amrex::Print()
200+
<< "\n For jet " << js->jet_name()
201+
<< ", next injection flow time = " << js->m_nxt_inj_flw_time
202+
<< " and next injection dpm time = " << js->m_cur_inj_dpm_time
203+
<< "\n";
204+
}
149205
}
150206
}
151207
}

Source/Spray/SprayInjection.H

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,251 @@
77
problem-specific SprayParticlesInitInsert.cpp file, when necessary.
88
*/
99

10+
std::ifstream&
11+
GotoLine(std::ifstream& file, long int num)
12+
{
13+
file.seekg(std::ios::beg);
14+
for (int i = 0; i < num - 1; ++i) {
15+
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
16+
}
17+
return file;
18+
}
19+
20+
void
21+
SprayParticleContainer::sprayInjectionfromDPMFile(
22+
const amrex::Real time,
23+
SprayJet* spray_jet,
24+
const amrex::Real sim_dt,
25+
const int level)
26+
{
27+
28+
if (!spray_jet->jet_active(time) || sim_dt <= 0.) {
29+
if (m_verbose > 0) {
30+
amrex::Print() << "Warning! Spray jet " << spray_jet->jet_name()
31+
<< " is inactive and hence 0 particles are injected.\n";
32+
}
33+
return;
34+
}
35+
36+
if (amrex::ParallelDescriptor::IOProcessor()) {
37+
amrex::Real dt = sim_dt;
38+
const amrex::Real smallnum = 1e-15;
39+
40+
while ((std::fabs(time - spray_jet->m_nxt_inj_flw_time) < smallnum ||
41+
time >= spray_jet->m_nxt_inj_flw_time) &&
42+
spray_jet->jet_active(time)) {
43+
// Line numbers in the dpm file
44+
long int lineno_current_dpm_time_begin = 0;
45+
long int lineno_current_dpm_time_end = 0;
46+
long int lineno_next_dpm_time_begin = 0;
47+
long int lineno_first_dpm_time_begin;
48+
long int lineno_last_dpm_time_end = 0;
49+
50+
long int ln; // iterating index
51+
amrex::Real dummy_time = -1;
52+
amrex::Real part_loc[3];
53+
amrex::Real part_vel[3];
54+
amrex::Real dia, temperature, parcel_mass, particle_mass, nppp;
55+
const amrex::Real verysmallnum = 1.e-15;
56+
57+
long int dummy_line_no;
58+
std::ifstream is_dpm(spray_jet->m_FluentDPMFile, std::ios::in);
59+
is_dpm >> dummy_line_no; // Reading total number of time instants to a
60+
// dummy variable
61+
62+
long int ctr = 0;
63+
64+
// Locate the current injection dpm time in the dpm file
65+
while (std::fabs(dummy_time - spray_jet->m_cur_inj_dpm_time) >
66+
verysmallnum &&
67+
ctr <= spray_jet->m_dpm_num_of_time_instants) {
68+
if (ctr == 0) {
69+
is_dpm >> dummy_time >> lineno_first_dpm_time_begin;
70+
dummy_line_no = lineno_first_dpm_time_begin;
71+
} else {
72+
is_dpm >> dummy_time >> dummy_line_no;
73+
}
74+
ctr++;
75+
}
76+
// If after one sweep, current injection dpm time is not found
77+
if (ctr > spray_jet->m_dpm_num_of_time_instants) {
78+
amrex::Abort(
79+
"Error! Unable to find the current injection dpm time in file.\n");
80+
}
81+
82+
// If at the last dpm time
83+
if (m_verbose > 0) {
84+
amrex::Print() << "\nCollecting particle data at DPM time "
85+
<< dummy_time << std::endl;
86+
}
87+
if (
88+
dummy_time == spray_jet->m_cur_inj_dpm_time &&
89+
spray_jet->m_cur_inj_dpm_time ==
90+
spray_jet->dpm_final_time()) // The last time in the dpm file
91+
{
92+
if (m_verbose > 0) {
93+
amrex::Print() << " (last dpm time) \n";
94+
}
95+
is_dpm >> lineno_last_dpm_time_end; // includes the last line no
96+
lineno_current_dpm_time_begin = dummy_line_no;
97+
lineno_current_dpm_time_end = lineno_last_dpm_time_end;
98+
99+
// if dpm file is periodic, the next time instant is time=0
100+
if (spray_jet->is_dpm_periodic) {
101+
102+
spray_jet->m_nxt_inj_dpm_time = spray_jet->dpm_intial_time();
103+
// lineno_next_dpm_time_begin = lineno_first_dpm_time_begin;
104+
} else {
105+
amrex::Print() << "\nWARNING! No more injection time found in DPM "
106+
"file. To continue the same injection again, set "
107+
"'is_dpm_periodic' to true.\n ";
108+
spray_jet->m_nxt_inj_dpm_time = -1;
109+
spray_jet->set_end_time(time - verysmallnum);
110+
}
111+
} else if (
112+
dummy_time == spray_jet->m_cur_inj_dpm_time &&
113+
spray_jet->m_cur_inj_dpm_time != spray_jet->dpm_final_time()) {
114+
lineno_current_dpm_time_begin = dummy_line_no;
115+
is_dpm >> spray_jet->m_nxt_inj_dpm_time >> lineno_next_dpm_time_begin;
116+
lineno_current_dpm_time_end = lineno_next_dpm_time_begin - 1;
117+
spray_jet->dt_dpm =
118+
spray_jet->m_nxt_inj_dpm_time - spray_jet->m_cur_inj_dpm_time;
119+
} else {
120+
amrex::Abort("Error! Unable to find the current injection dpm time in "
121+
"the dpm file");
122+
}
123+
is_dpm.close();
124+
125+
// Now reading the particle data
126+
std::ifstream is_dpm1(spray_jet->m_FluentDPMFile, std::ios::in);
127+
GotoLine(
128+
is_dpm1, lineno_current_dpm_time_begin); // Skip lines in dpm file till
129+
// the current injection time
130+
for (ln = 0;
131+
ln <= lineno_current_dpm_time_end - lineno_current_dpm_time_begin;
132+
ln++) {
133+
amrex::Real pmov1 =
134+
amrex::Random(); // Random number to make sure particle is advanced a
135+
// little bit downstream
136+
amrex::Real pmov = amrex::Random();
137+
amrex::Real Y_part[SPRAY_FUEL_NUM]; // Spray fuel mass fraction
138+
bool set_part_Y = false;
139+
140+
// Reading parcel/particle details from dpm input file
141+
is_dpm1 >> dummy_time >> part_loc[0] >> part_loc[1] >> part_loc[2] >>
142+
part_vel[0] >> part_vel[1] >> part_vel[2] >> dia >> temperature >>
143+
parcel_mass >> particle_mass >> nppp;
144+
145+
amrex::ParticleLocData pld;
146+
std::map<std::pair<int, int>, amrex::Gpu::HostVector<ParticleType>>
147+
host_particles;
148+
ParticleType p;
149+
p.id() = ParticleType::NextID();
150+
p.cpu() = amrex::ParallelDescriptor::MyProc();
151+
152+
// Setting particle properties
153+
// Transforming the particle coordinates to user-specified coordinate
154+
// system
155+
spray_jet->transform_to_new_cs(part_loc);
156+
157+
if (
158+
spray_jet->get_override_injection_plane_dir() !=
159+
-1) // Overriding dpm input file particle location on a plane with
160+
// user specified location
161+
{
162+
part_loc[spray_jet->get_override_injection_plane_dir()] =
163+
spray_jet->get_override_injection_plane_loc();
164+
}
165+
166+
spray_jet->transform_to_new_cs(
167+
part_vel); // Transforming the particle velocity to user-specified
168+
// coordinate system
169+
AMREX_D_TERM(p.rdata(SprayComps::pstateVel) = (part_vel[0] + pmov1);
170+
, // Setting the particle velocities
171+
p.rdata(SprayComps::pstateVel + 1) = (part_vel[1] + pmov1);
172+
, p.rdata(SprayComps::pstateVel + 2) =
173+
(part_vel[2] + pmov1););
174+
175+
for (int dir = 0; dir < AMREX_SPACEDIM;
176+
++dir) // Setting the particle coordinates
177+
{
178+
p.pos(dir) =
179+
part_loc[dir] + pmov * dt * p.rdata(SprayComps::pstateVel + dir);
180+
}
181+
182+
p.rdata(SprayComps::pstateDia) = dia; // Setting the particle density
183+
p.rdata(SprayComps::pstateT) =
184+
temperature; // Setting the particle temperature
185+
set_part_Y = // NOLINT(clang-analyzer-deadcode.DeadStores)
186+
spray_jet // NOLINT(clang-analyzer-deadcode.DeadStores)
187+
->get_new_particle( // NOLINT(clang-analyzer-deadcode.DeadStores)
188+
Y_part); // NOLINT(clang-analyzer-deadcode.DeadStores)
189+
190+
if (SPRAY_FUEL_NUM > 1 && set_part_Y) // Setting particle mass fractions
191+
{
192+
for (int spf = 0; spf < SPRAY_FUEL_NUM; ++spf) {
193+
p.rdata(SprayComps::pstateY + spf) = Y_part[spf];
194+
}
195+
} else {
196+
p.rdata(SprayComps::pstateY) = 1.;
197+
}
198+
199+
spray_jet->m_totalInjMass += parcel_mass;
200+
201+
// If KHRT is used, BM1 is shed mass
202+
// If TAB is used, BM1 is y
203+
p.rdata(SprayComps::pstateBM1) = 0.;
204+
p.rdata(SprayComps::pstateBM2) = 0;
205+
p.rdata(SprayComps::pstateFilmHght) = 0.;
206+
p.rdata(SprayComps::pstateN0) = 2;
207+
p.rdata(SprayComps::pstateNumDens) = nppp;
208+
209+
bool where = Where(p, pld);
210+
if (!where) {
211+
amrex::Print() << "\n Problematic particle = " << p.pos(0) << " "
212+
<< p.pos(1) << " " << p.pos(2);
213+
// amrex::Abort("Bad injection particle");
214+
}
215+
216+
std::pair<int, int> ind(pld.m_grid, pld.m_tile);
217+
host_particles[ind].push_back(p);
218+
219+
for (auto& kv : host_particles) {
220+
auto grid = kv.first.first;
221+
auto tile = kv.first.second;
222+
const auto& src_tile = kv.second;
223+
auto& dst_tile = GetParticles(level)[std::make_pair(grid, tile)];
224+
auto old_size = dst_tile.GetArrayOfStructs().size();
225+
auto new_size = old_size + src_tile.size();
226+
dst_tile.resize(new_size);
227+
// Copy the AoS part of the host particles to the GPU
228+
amrex::Gpu::copy(
229+
amrex::Gpu::hostToDevice, src_tile.begin(), src_tile.end(),
230+
dst_tile.GetArrayOfStructs().begin() + old_size);
231+
}
232+
}
233+
is_dpm1.close();
234+
235+
if (m_verbose > 0) {
236+
amrex::Print() << "Injected " << ln << " particles through "
237+
<< spray_jet->jet_name()
238+
<< " at flow time = " << spray_jet->m_nxt_inj_flw_time
239+
<< "\n";
240+
}
241+
spray_jet->m_nxt_inj_flw_time += spray_jet->dt_dpm;
242+
spray_jet->m_cur_inj_dpm_time = spray_jet->m_nxt_inj_dpm_time;
243+
244+
if (m_verbose > 0) {
245+
amrex::Print() << "\tNext injection flow time = "
246+
<< spray_jet->m_nxt_inj_flw_time << "\n";
247+
amrex::Print() << "\tNext injection DPM time = "
248+
<< spray_jet->m_cur_inj_dpm_time << "\n\n";
249+
}
250+
}
251+
}
252+
Redistribute();
253+
}
254+
10255
void
11256
SprayParticleContainer::sprayInjection(
12257
const amrex::Real time,

Source/Spray/SprayInterpolation.H

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ trilinear_interp(
170170
// Note: if near a reflective boundary, ijk has been shifted in check_bounds
171171
AMREX_D_TERM(int i = ijk[0];, int j = ijk[1];, int k = ijk[2];)
172172

173-
const amrex::RealVect sx_hi = lx - ijk;
173+
const amrex::RealVect sx_hi = lx - amrex::RealVect(ijk);
174174
const amrex::RealVect sx_lo = 1. - sx_hi;
175175
amrex::GpuArray<amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>, 2> ssv;
176176
for (int dir = 0; dir < AMREX_SPACEDIM; ++dir) {

0 commit comments

Comments
 (0)