MFC
Exascale flow solver
Loading...
Searching...
No Matches
m_helper.fpp.f90
Go to the documentation of this file.
1# 1 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
2# 1 "/home/runner/work/MFC/MFC/src/common/include/case.fpp" 1
3! This file exists so that Fypp can be run without generating case.fpp files for
4! each target. This is useful when generating documentation, for example. This
5! should also let MFC be built with CMake directly, without invoking mfc.sh.
6
7! For pre-process.
8# 8 "/home/runner/work/MFC/MFC/src/common/include/case.fpp"
9
10! For moving immersed boundaries in simulation
11# 12 "/home/runner/work/MFC/MFC/src/common/include/case.fpp"
12# 2 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp" 2
13# 1 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp" 1
14# 1 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 1
15# 1 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 1
16# 2 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
17# 3 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
18# 4 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
19# 5 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
20# 6 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
21
22# 8 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
23# 9 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
24# 10 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
25
26# 12 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
27# 1 "/home/runner/work/MFC/MFC/src/common/include/defaults/thermochem.fpp" 1
28! Default for Fypp runs outside the toolchain (e.g. documentation). Searched last, so the
29! build/include/<target>/thermochem.fpp the toolchain writes from m_thermochem takes precedence.
30# 4 "/home/runner/work/MFC/MFC/src/common/include/defaults/thermochem.fpp"
31# 5 "/home/runner/work/MFC/MFC/src/common/include/defaults/thermochem.fpp"
32# 13 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 2
33
34# 16 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
35# 17 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
36
37# 24 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
38
39# 53 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
40
41# 65 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
42
43# 75 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
44
45# 105 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
46
47# 117 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
48
49# 127 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
50
51# 174 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
52! New line at end of file is required for FYPP
53# 2 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 2
54# 1 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp" 1
55# 1 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 1
56# 2 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
57# 3 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
58# 4 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
59# 5 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
60# 6 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
61
62# 8 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
63# 9 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
64# 10 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
65
66# 12 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
67# 1 "/home/runner/work/MFC/MFC/src/common/include/defaults/thermochem.fpp" 1
68! Default for Fypp runs outside the toolchain (e.g. documentation). Searched last, so the
69! build/include/<target>/thermochem.fpp the toolchain writes from m_thermochem takes precedence.
70# 4 "/home/runner/work/MFC/MFC/src/common/include/defaults/thermochem.fpp"
71# 5 "/home/runner/work/MFC/MFC/src/common/include/defaults/thermochem.fpp"
72# 13 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 2
73
74# 16 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
75# 17 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
76
77# 24 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
78
79# 53 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
80
81# 65 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
82
83# 75 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
84
85# 105 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
86
87# 117 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
88
89# 127 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
90
91# 174 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
92! New line at end of file is required for FYPP
93# 2 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp" 2
94
95# 4 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
96# 5 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
97# 6 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
98# 7 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
99# 8 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
100
101# 20 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
102
103# 43 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
104
105# 48 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
106
107# 53 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
108
109# 58 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
110
111# 63 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
112
113# 68 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
114
115# 81 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
116
117# 95 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
118
119# 100 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
120
121# 105 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
122
123# 110 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
124
125# 115 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
126
127# 120 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
128
129# 125 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
130
131# 130 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
132
133# 135 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
134
135# 165 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
136
137# 219 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
138
139# 233 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
140
141# 258 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
142
143# 269 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
144
145# 271 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
146# 282 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
147
148# 332 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
149
150# 342 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
151
152# 352 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
153
154# 361 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
155
156# 378 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
157
158# 388 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
159
160# 395 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
161
162# 401 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
163
164# 407 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
165
166# 413 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
167
168# 419 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
169
170# 425 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
171! New line at end of file is required for FYPP
172# 3 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 2
173# 1 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp" 1
174# 1 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 1
175# 2 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
176# 3 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
177# 4 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
178# 5 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
179# 6 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
180
181# 8 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
182# 9 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
183# 10 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
184
185# 12 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
186# 1 "/home/runner/work/MFC/MFC/src/common/include/defaults/thermochem.fpp" 1
187! Default for Fypp runs outside the toolchain (e.g. documentation). Searched last, so the
188! build/include/<target>/thermochem.fpp the toolchain writes from m_thermochem takes precedence.
189# 4 "/home/runner/work/MFC/MFC/src/common/include/defaults/thermochem.fpp"
190# 5 "/home/runner/work/MFC/MFC/src/common/include/defaults/thermochem.fpp"
191# 13 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 2
192
193# 16 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
194# 17 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
195
196# 24 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
197
198# 53 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
199
200# 65 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
201
202# 75 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
203
204# 105 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
205
206# 117 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
207
208# 127 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
209
210# 174 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
211! New line at end of file is required for FYPP
212# 2 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp" 2
213
214# 7 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
215
216# 17 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
217
218# 22 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
219
220# 27 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
221
222# 32 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
223
224# 37 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
225
226# 42 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
227
228# 47 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
229
230# 52 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
231
232# 57 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
233
234# 62 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
235
236# 73 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
237
238# 78 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
239
240# 83 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
241
242# 88 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
243
244# 103 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
245
246# 131 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
247
248# 160 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
249
250# 175 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
251
252# 193 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
253
254# 215 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
255
256# 244 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
257
258# 259 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
259
260# 269 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
261
262# 278 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
263
264# 294 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
265
266# 304 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
267
268# 311 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
269! New line at end of file is required for FYPP
270# 4 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 2
271
272! GPU parallel region (scalar reductions, maxval/minval)
273# 23 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
274
275! GPU parallel loop over threads (most common GPU macro)
276# 43 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
277
278! Required closing for GPU_PARALLEL_LOOP
279# 55 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
280
281! Mark routine for device compilation
282# 112 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
283
284! Declare device-resident data
285# 130 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
286
287! Inner loop within a GPU parallel region
288# 145 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
289
290! Scoped GPU data region
291# 164 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
292
293! Host code with device pointers (for MPI with GPU buffers)
294# 193 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
295
296! Allocate device memory (unscoped)
297# 207 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
298
299! Free device memory
300# 219 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
301
302! Atomic operation on device
303# 231 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
304
305! End atomic capture block
306# 242 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
307
308! Copy data between host and device
309# 254 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
310
311! Synchronization barrier
312# 266 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
313
314! Import GPU library module (openacc or omp_lib)
315# 275 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
316
317! Emit code only for AMD compiler
318# 282 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
319
320! Emit code for non-Cray compilers
321# 289 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
322
323! Emit code only for Cray compiler
324# 296 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
325
326! Emit code for non-NVIDIA compilers
327# 303 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
328
329# 305 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
330# 306 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
331! New line at end of file is required for FYPP
332# 2 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp" 2
333
334# 14 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
335
336! Caution: This macro requires the use of a binding script to set CUDA_VISIBLE_DEVICES, such that we have one GPU device per MPI
337! rank. That's because for both cudaMemAdvise (preferred location) and cudaMemPrefetchAsync we use location = device_id = 0. For an
338! example see misc/nvidia_uvm/bind.sh.
339# 52 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
340
341! Allocate and create GPU device memory
342# 72 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
343
344! Free GPU device memory and deallocate
345# 80 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
346
347! Cray-specific GPU pointer setup for vector fields
348# 104 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
349
350! Cray-specific GPU pointer setup for scalar fields
351# 120 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
352
353! Cray-specific GPU pointer setup for acoustic source spatials
354# 145 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
355
356# 151 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
357
358# 158 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
359! New line at end of file is required for FYPP
360# 3 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp" 2
361
362!>
363!! @file
364!! @brief Contains module m_helper
365
366!> @brief Utility routines for bubble model setup, coordinate transforms, array sampling, and special functions
368
371 use m_constants, only: bc_periodic
372 use ieee_arithmetic !< for checking nan
373
374 implicit none
375
376 private
382
383contains
384
385 !> Computes the bubble number density n from the primitive variables
386 subroutine s_comp_n_from_prim(vftmp, Rtmp, ntmp, weights)
387
388
389# 30 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
390#if MFC_OpenACC
391# 30 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
392!$acc routine seq
393# 30 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
394#elif MFC_OpenMP
395# 30 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
396
397# 30 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
398
399# 30 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
400!$omp declare target device_type(any)
401# 30 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
402#endif
403# 31 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
404 real(wp), intent(in) :: vftmp
405 real(wp), dimension(nb), intent(in) :: rtmp
406 real(wp), intent(out) :: ntmp
407 real(wp), dimension(nb), intent(in) :: weights
408 real(wp) :: r3
409
410 r3 = dot_product(weights, rtmp**3._wp)
411 ntmp = (3._wp/(4._wp*pi))*vftmp/r3
412
413 end subroutine s_comp_n_from_prim
414
415 !> Compute the bubble number density from the conservative void fraction and weighted bubble radii.
416 subroutine s_comp_n_from_cons(vftmp, nRtmp, ntmp, weights)
417
418
419# 45 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
420#if MFC_OpenACC
421# 45 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
422!$acc routine seq
423# 45 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
424#elif MFC_OpenMP
425# 45 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
426
427# 45 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
428
429# 45 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
430!$omp declare target device_type(any)
431# 45 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
432#endif
433# 46 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
434 real(wp), intent(in) :: vftmp
435 real(wp), dimension(nb), intent(in) :: nrtmp
436 real(wp), intent(out) :: ntmp
437 real(wp), dimension(nb), intent(in) :: weights
438 real(wp) :: nr3
439
440 nr3 = dot_product(weights, nrtmp**3._wp)
441 ntmp = sqrt((4._wp*pi/3._wp)*nr3/vftmp)
442
443 end subroutine s_comp_n_from_cons
444
445 !> Print a 2D real array to standard output, optionally dividing each element by a given scalar.
446 impure subroutine s_print_2d_array(A, div)
447
448 real(wp), dimension(:,:), intent(in) :: a
449 real(wp), optional, intent(in) :: div
450 integer :: i, j
451 integer :: local_m, local_n
452 real(wp) :: c
453
454 local_m = size(a, 1)
455 local_n = size(a, 2)
456
457 if (present(div)) then
458 c = div
459 else
460 c = 1._wp
461 end if
462
463 print *, local_m, local_n
464
465 do i = 1, local_m
466 do j = 1, local_n
467 write (*, fmt="(F12.4)", advance="no") a(i, j)/c
468 end do
469 write (*, fmt="(A1)") " "
470 end do
471 write (*, fmt="(A1)") " "
472
473 end subroutine s_print_2d_array
474
475 !> Initialize bubble model arrays for Euler or Lagrangian bubbles with polytropic or non-polytropic gas.
476 impure subroutine s_initialize_bubbles_model()
477
478 ! Allocate memory
479 if (bubbles_euler) then
480#ifdef MFC_DEBUG
481# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
482 block
483# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
484 use iso_fortran_env, only: output_unit
485# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
486
487# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
488 print *, 'm_helper.fpp:92: ', '@:ALLOCATE(weight(nb), R0(nb))'
489# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
490
491# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
492 call flush (output_unit)
493# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
494 end block
495# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
496#endif
497# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
498 allocate (weight(nb), r0(nb))
499# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
500
501# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
502
503# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
504
505# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
506#if defined(MFC_OpenACC)
507# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
508!$acc enter data create(weight, R0)
509# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
510#elif defined(MFC_OpenMP)
511# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
512!$omp target enter data map(always,alloc:weight, R0)
513# 92 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
514#endif
515# 93 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
516 if (.not. polytropic) then
517#ifdef MFC_DEBUG
518# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
519 block
520# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
521 use iso_fortran_env, only: output_unit
522# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
523
524# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
525 print *, 'm_helper.fpp:94: ', '@:ALLOCATE(pb0(nb), Pe_T(nb), k_g(nb), k_v(nb), mass_g0(nb), mass_v0(nb))'
526# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
527
528# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
529 call flush (output_unit)
530# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
531 end block
532# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
533#endif
534# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
535 allocate (pb0(nb), pe_t(nb), k_g(nb), k_v(nb), mass_g0(nb), mass_v0(nb))
536# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
537
538# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
539
540# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
541
542# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
543
544# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
545
546# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
547
548# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
549
550# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
551#if defined(MFC_OpenACC)
552# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
553!$acc enter data create(pb0, Pe_T, k_g, k_v, mass_g0, mass_v0)
554# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
555#elif defined(MFC_OpenMP)
556# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
557!$omp target enter data map(always,alloc:pb0, Pe_T, k_g, k_v, mass_g0, mass_v0)
558# 94 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
559#endif
560# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
561#ifdef MFC_DEBUG
562# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
563 block
564# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
565 use iso_fortran_env, only: output_unit
566# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
567
568# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
569 print *, 'm_helper.fpp:95: ', '@:ALLOCATE(Re_trans_T(nb), Re_trans_c(nb), Im_trans_T(nb), Im_trans_c(nb))'
570# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
571
572# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
573 call flush (output_unit)
574# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
575 end block
576# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
577#endif
578# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
579 allocate (re_trans_t(nb), re_trans_c(nb), im_trans_t(nb), im_trans_c(nb))
580# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
581
582# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
583
584# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
585
586# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
587
588# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
589
590# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
591#if defined(MFC_OpenACC)
592# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
593!$acc enter data create(Re_trans_T, Re_trans_c, Im_trans_T, Im_trans_c)
594# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
595#elif defined(MFC_OpenMP)
596# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
597!$omp target enter data map(always,alloc:Re_trans_T, Re_trans_c, Im_trans_T, Im_trans_c)
598# 95 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
599#endif
600# 96 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
601 else if (qbmm) then
602#ifdef MFC_DEBUG
603# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
604 block
605# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
606 use iso_fortran_env, only: output_unit
607# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
608
609# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
610 print *, 'm_helper.fpp:97: ', '@:ALLOCATE(pb0(nb))'
611# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
612
613# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
614 call flush (output_unit)
615# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
616 end block
617# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
618#endif
619# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
620 allocate (pb0(nb))
621# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
622
623# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
624
625# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
626#if defined(MFC_OpenACC)
627# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
628!$acc enter data create(pb0)
629# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
630#elif defined(MFC_OpenMP)
631# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
632!$omp target enter data map(always,alloc:pb0)
633# 97 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
634#endif
635# 98 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
636 end if
637
638 ! Compute quadrature weights and nodes for polydisperse simulations
639 if (nb > 1) then
640 call s_simpson(weight, r0)
641 else if (nb == 1) then
642 r0 = 1._wp
643 weight = 1._wp
644 else
645 stop 'Invalid value of nb'
646 end if
647 r0 = r0*bub_pp%R0ref
648 end if
649
650 ! Initialize bubble variables
652
653 end subroutine s_initialize_bubbles_model
654
655 !> Set bubble physical parameters and nondimensional numbers from the input configuration.
656 impure subroutine s_initialize_bubble_vars()
657
658 r0ref = bub_pp%R0ref; p0ref = bub_pp%p0ref
659 rho0ref = bub_pp%rho0ref
660 ss = bub_pp%ss; pv = bub_pp%pv; vd = bub_pp%vd
661 mu_l = bub_pp%mu_l; mu_v = bub_pp%mu_v; mu_g = bub_pp%mu_g
662 gam_v = bub_pp%gam_v; gam_g = bub_pp%gam_g
663 if (.not. polytropic) then
664 if (bubbles_euler) then
665 m_v = bub_pp%M_v; m_g = bub_pp%M_g
666 k_v = bub_pp%k_v; k_g = bub_pp%k_g
667 end if
668 r_v = bub_pp%R_v; r_g = bub_pp%R_g
669 tw = bub_pp%T0ref
670 end if
671 if (bubbles_lagrange) then
672 cp_v = bub_pp%cp_v; cp_g = bub_pp%cp_g
673 k_vl = bub_pp%k_v; k_gl = bub_pp%k_g
674 end if
675
676 ! Input quantities
677 if (bubbles_euler .and. (.not. polytropic)) then
678 if (thermal == 2) then
679 gam_m = 1._wp
680 else
681 gam_m = gam_g
682 end if
683 end if
684
685 ! Nondimensional numbers
686 eu = p0ref
687 ca = eu - pv
688 if (.not. f_is_default(bub_pp%ss)) web = 1._wp/ss
689 if (.not. f_is_default(bub_pp%mu_l)) re_inv = mu_l
690 if (.not. polytropic) pe_c = 1._wp/vd
691
692 if (bubbles_euler) then
693 ! Initialize variables for non-polytropic (Preston) model
694 if (.not. polytropic) then
696 end if
697 ! Initialize pb based on surface tension for qbmm (polytropic)
698 if (qbmm .and. polytropic) then
699 pb0 = eu
700 if (.not. f_is_default(web)) then
701 pb0 = pb0 + 2._wp/web/r0
702 end if
703 end if
704 end if
705
706 end subroutine s_initialize_bubble_vars
707
708 !> Initializes non-polydisperse bubble modeling
709 impure subroutine s_initialize_nonpoly()
710
711 integer :: ir
712 real(wp), dimension(nb) :: chi_vw0, cp_m0, k_m0, rho_m0, x_vw, omegan
713 real(wp), parameter :: k_poly = 1._wp !< polytropic index used to compute isothermal natural frequency
714 ! Chapman-Enskog transport coefficients for vapor-gas mixture, Ando JAS (2010)
715
716 phi_vg = (1._wp + sqrt(mu_v/mu_g)*(m_g/m_v)**(0.25_wp))**2/(sqrt(8._wp)*sqrt(1._wp + m_v/m_g))
717 phi_gv = (1._wp + sqrt(mu_g/mu_v)*(m_v/m_g)**(0.25_wp))**2/(sqrt(8._wp)*sqrt(1._wp + m_g/m_v))
718
719 ! Initial internal bubble pressure (Euler number + Laplace pressure)
720 pb0 = eu + 2._wp/web/r0
721
722 ! Vapor mass fraction at bubble wall, Ando JAS (2010)
723 chi_vw0 = 1._wp/(1._wp + r_v/r_g*(pb0/pv - 1._wp))
724
725 ! Mixture specific heat from mass-weighted vapor/gas contributions
726 cp_m0 = chi_vw0*r_v*gam_v/(gam_v - 1._wp) + (1._wp - chi_vw0)*r_g*gam_g/(gam_g - 1._wp)
727
728 ! mole fraction of vapor (Eq. 2.23 in Ando 2010)
729 x_vw = m_g*chi_vw0/(m_v + (m_g - m_v)*chi_vw0)
730
731 ! thermal conductivity for gas/vapor mixture (Eq. 2.21 in Ando 2010)
732 k_m0 = x_vw*k_v/(x_vw + (1._wp - x_vw)*phi_vg) + (1._wp - x_vw)*k_g/(x_vw*phi_gv + 1._wp - x_vw)
733 k_g(:) = k_g(:)/k_m0(:)
734 k_v(:) = k_v(:)/k_m0(:)
735
736 ! mixture density (Eq. 2.20 in Ando 2010)
737 rho_m0 = pv/(chi_vw0*r_v*tw)
738
739 ! mass of gas/vapor
740 mass_g0(:) = (4._wp*pi/3._wp)*(pb0(:) - pv)/(r_g*tw)*r0(:)**3
741 mass_v0(:) = (4._wp*pi/3._wp)*pv/(r_v*tw)*r0(:)**3
742
743 ! Peclet numbers
744 pe_t(:) = rho_m0*cp_m0(:)/k_m0(:)
745
746 ! Bubble natural frequency, Ando JAS (2010)
747 omegan(:) = sqrt(3._wp*k_poly*ca + 2._wp*(3._wp*k_poly - 1._wp)/(web*r0))/r0/sqrt(rho0ref)
748 do ir = 1, nb
749 call s_transcoeff(omegan(ir)*r0(ir), pe_t(ir)*r0(ir), re_trans_t(ir), im_trans_t(ir))
750 call s_transcoeff(omegan(ir)*r0(ir), pe_c*r0(ir), re_trans_c(ir), im_trans_c(ir))
751 end do
752 im_trans_t = 0._wp
753
754 end subroutine s_initialize_nonpoly
755
756 !> Computes the transfer coefficient for the non-polytropic bubble compression process
757 elemental subroutine s_transcoeff(omega, peclet, Re_trans, Im_trans)
758
759 real(wp), intent(in) :: omega, peclet
760 real(wp), intent(out) :: re_trans, im_trans
761 complex(wp) :: imag, trans, c1, c2, c3
762
763 imag = (0._wp, 1._wp)
764
765 c1 = imag*omega*peclet
766 c2 = sqrt(c1)
767 c3 = (exp(c2) - exp(-c2))/(exp(c2) + exp(-c2)) ! TANH(c2)
768 trans = ((c2/c3 - 1._wp)**(-1) - 3._wp/c1)**(-1) ! transfer function
769
770 re_trans = trans
771 im_trans = aimag(trans)
772
773 end subroutine s_transcoeff
774
775 !> Convert an integer to its trimmed string representation.
776 elemental subroutine s_int_to_str(i, res)
777
778 integer, intent(in) :: i
779 character(len=*), intent(inout) :: res
780
781 write (res, '(I0)') i
782 res = trim(res)
783
784 end subroutine s_int_to_str
785
786 !> Compute the Simpson weights for quadrature
787 subroutine s_simpson(local_weight, local_R0)
788
789 real(wp), dimension(:), intent(inout) :: local_weight
790 real(wp), dimension(:), intent(inout) :: local_r0
791 integer :: ir
792 real(wp) :: r0mn, r0mx, dphi, tmp, sd
793 real(wp), dimension(nb) :: phi
794
795 sd = poly_sigma
796 r0mn = 0.8_wp*exp(-2.8_wp*sd)
797 r0mx = 0.2_wp*exp(9.5_wp*sd) + 1._wp
798
799 ! phi = ln( R0 ) & return R0
800 do ir = 1, nb
801 phi(ir) = log(r0mn) + (ir - 1._wp)*log(r0mx/r0mn)/(nb - 1._wp)
802 local_r0(ir) = exp(phi(ir))
803 end do
804
805# 268 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
806 dphi = phi(2) - phi(1)
807# 270 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
808
809 ! weights for quadrature using Simpson's rule
810 do ir = 2, nb - 1
811 ! Gaussian
812 tmp = exp(-0.5_wp*(phi(ir)/sd)**2)/sqrt(2._wp*pi)/sd
813 if (mod(ir, 2) == 0) then
814 local_weight(ir) = tmp*4._wp*dphi/3._wp
815 else
816 local_weight(ir) = tmp*2._wp*dphi/3._wp
817 end if
818 end do
819 tmp = exp(-0.5_wp*(phi(1)/sd)**2)/sqrt(2._wp*pi)/sd
820 local_weight(1) = tmp*dphi/3._wp
821 tmp = exp(-0.5_wp*(phi(nb)/sd)**2)/sqrt(2._wp*pi)/sd
822 local_weight(nb) = tmp*dphi/3._wp
823
824 end subroutine s_simpson
825
826 !> Compute the cross product of two vectors.
827 pure function f_cross(a, b) result(c)
828
829
830# 291 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
831#if MFC_OpenACC
832# 291 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
833!$acc routine seq
834# 291 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
835#elif MFC_OpenMP
836# 291 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
837
838# 291 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
839
840# 291 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
841!$omp declare target device_type(any)
842# 291 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
843#endif
844# 292 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
845
846 real(wp), dimension(3), intent(in) :: a, b
847 real(wp), dimension(3) :: c
848
849 c(1) = a(2)*b(3) - a(3)*b(2)
850 c(2) = a(3)*b(1) - a(1)*b(3)
851 c(3) = a(1)*b(2) - a(2)*b(1)
852
853 end function f_cross
854
855 !> Generate a unit vector uniformly distributed on the sphere from two random parameters.
856 function f_unit_vector(theta, eta) result(vec)
857
858
859# 305 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
860#if MFC_OpenACC
861# 305 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
862!$acc routine seq
863# 305 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
864#elif MFC_OpenMP
865# 305 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
866
867# 305 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
868
869# 305 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
870!$omp declare target device_type(any)
871# 305 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
872#endif
873# 306 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
874 real(wp), intent(in) :: theta, eta
875 real(wp) :: zeta, xi
876 real(wp), dimension(3) :: vec
877
878 xi = 2._wp*pi*theta
879 zeta = acos(2._wp*eta - 1._wp)
880 vec(1) = sin(zeta)*cos(xi)
881 vec(2) = sin(zeta)*sin(xi)
882 vec(3) = cos(zeta)
883
884 end function f_unit_vector
885
886 !> Generate a pseudo-random number between 0 and 1 using a linear congruential generator.
887 subroutine s_prng(var, seed)
888
889
890# 321 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
891#if MFC_OpenACC
892# 321 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
893!$acc routine seq
894# 321 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
895#elif MFC_OpenMP
896# 321 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
897
898# 321 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
899
900# 321 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
901!$omp declare target device_type(any)
902# 321 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
903#endif
904# 322 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
905 integer, intent(inout) :: seed
906 real(wp), intent(out) :: var
907
908 seed = mod(modmul(seed), modulus)
909 var = seed/real(modulus, wp)
910
911 end subroutine s_prng
912
913 !> Compute a modular multiplication step for the linear congruential pseudo-random number generator.
914 function modmul(a) result(val)
915
916
917# 333 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
918#if MFC_OpenACC
919# 333 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
920!$acc routine seq
921# 333 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
922#elif MFC_OpenMP
923# 333 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
924
925# 333 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
926
927# 333 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
928!$omp declare target device_type(any)
929# 333 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
930#endif
931# 334 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
932 integer, intent(in) :: a
933 integer :: val
934 real(wp) :: x, y
935
936 x = (multiplier/real(modulus, wp))*a + (increment/real(modulus, wp))
937 y = nint((x - floor(x))*decimal_trim)/decimal_trim
938 val = nint(y*modulus)
939
940 end function modmul
941
942 !> Uniform draw in [0, 1) (1 only via single-precision rounding) from a 32-bit SplitMix-style generator (Weyl sequence hashed by
943 !! the MurmurHash3 finalizer). Exact integer arithmetic, so the stream is compiler-independent; period 2^32, and different seeds
944 !! give unrelated streams.
945 subroutine s_prng_splitmix32(var, state)
946
947 integer, parameter :: int64_kind = selected_int_kind(18)
948 real(wp), intent(out) :: var
949 integer(kind=int64_kind), intent(inout) :: state !< reduced mod 2^32 on each draw
950 integer(kind=int64_kind) :: z
951
952 state = iand(state + 2654435769_int64_kind, 4294967295_int64_kind)
953 z = f_mulmod32(ieor(state, ishft(state, -16)), 2246822507_int64_kind)
954 z = f_mulmod32(ieor(z, ishft(z, -13)), 3266489909_int64_kind)
955 z = ieor(z, ishft(z, -16))
956 var = real(z, wp)/4294967296._wp
957
958 end subroutine s_prng_splitmix32
959
960 !> a*b mod 2^32 for a, b in [0, 2^32), split into 16-bit halves of b so no intermediate exceeds 2^49
961 pure function f_mulmod32(a, b) result(c)
962
963 integer, parameter :: int64_kind = selected_int_kind(18)
964 integer(kind=int64_kind), intent(in) :: a, b
965 integer(kind=int64_kind) :: c
966
967 c = iand(a*iand(b, 65535_int64_kind) + iand(a*ishft(b, -16), 65535_int64_kind)*65536_int64_kind, 4294967295_int64_kind)
968
969 end function f_mulmod32
970
971 !> Compute the cross product c = a x b of two 3D vectors.
972 subroutine s_cross_product(a, b, c)
973
974
975# 376 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
976#if MFC_OpenACC
977# 376 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
978!$acc routine seq
979# 376 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
980#elif MFC_OpenMP
981# 376 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
982
983# 376 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
984
985# 376 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
986!$omp declare target device_type(any)
987# 376 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
988#endif
989# 377 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
990 real(wp), intent(in) :: a(3), b(3)
991 real(wp), intent(out) :: c(3)
992
993 c(1) = a(2)*b(3) - a(3)*b(2)
994 c(2) = a(3)*b(1) - a(1)*b(3)
995 c(3) = a(1)*b(2) - a(2)*b(1)
996
997 end subroutine s_cross_product
998
999 !> Swap two real numbers.
1000 elemental subroutine s_swap(lhs, rhs)
1001
1002 real(wp), intent(inout) :: lhs, rhs
1003 real(wp) :: ltemp
1004
1005 ltemp = lhs
1006 lhs = rhs
1007 rhs = ltemp
1008
1009 end subroutine s_swap
1010
1011 !> Sort the key-value pair by the key
1012 pure subroutine s_sort_int_key_value(keys, vals, n)
1013
1014 integer, dimension(:), intent(inout) :: keys, vals
1015 integer, intent(in) :: n
1016 integer :: i, j, key, val
1017
1018 do i = 2, n
1019 key = keys(i); val = vals(i)
1020
1021 j = i
1022 do while (j > 1)
1023 if (keys(j - 1) <= key) exit
1024 j = j - 1
1025 end do
1026
1027 keys(j + 1:i) = keys(j:i - 1)
1028 vals(j + 1:i) = vals(j:i - 1)
1029 keys(j) = key; vals(j) = val
1030 end do
1031
1032 end subroutine s_sort_int_key_value
1033
1034 !> Create a transformation matrix.
1035 function f_create_transform_matrix(param, center) result(out_matrix)
1036
1037 type(ic_model_parameters), intent(in) :: param
1038 real(wp), dimension(1:3), optional, intent(in) :: center
1039 real(wp), dimension(1:4,1:4) :: sc, rz, rx, ry, tr, t_back, t_to_origin, out_matrix
1040
1041 sc = transpose(reshape([param%scale(1), 0._wp, 0._wp, 0._wp, 0._wp, param%scale(2), 0._wp, 0._wp, 0._wp, 0._wp, &
1042 & param%scale(3), 0._wp, 0._wp, 0._wp, 0._wp, 1._wp], shape(sc)))
1043
1044 rz = transpose(reshape([cos(param%rotate(3)), -sin(param%rotate(3)), 0._wp, 0._wp, sin(param%rotate(3)), &
1045 & cos(param%rotate(3)), 0._wp, 0._wp, 0._wp, 0._wp, 1._wp, 0._wp, 0._wp, 0._wp, 0._wp, 1._wp], shape(rz)))
1046
1047 rx = transpose(reshape([1._wp, 0._wp, 0._wp, 0._wp, 0._wp, cos(param%rotate(1)), -sin(param%rotate(1)), 0._wp, 0._wp, &
1048 & sin(param%rotate(1)), cos(param%rotate(1)), 0._wp, 0._wp, 0._wp, 0._wp, 1._wp], shape(rx)))
1049
1050 ry = transpose(reshape([cos(param%rotate(2)), 0._wp, sin(param%rotate(2)), 0._wp, 0._wp, 1._wp, 0._wp, 0._wp, &
1051 & -sin(param%rotate(2)), 0._wp, cos(param%rotate(2)), 0._wp, 0._wp, 0._wp, 0._wp, 1._wp], shape(ry)))
1052
1053 tr = transpose(reshape([1._wp, 0._wp, 0._wp, param%translate(1), 0._wp, 1._wp, 0._wp, param%translate(2), 0._wp, 0._wp, &
1054 & 1._wp, param%translate(3), 0._wp, 0._wp, 0._wp, 1._wp], shape(tr)))
1055
1056 if (present(center)) then
1057 ! Translation matrix to move center to the origin
1058 t_to_origin = transpose(reshape([1._wp, 0._wp, 0._wp, -center(1), 0._wp, 1._wp, 0._wp, -center(2), 0._wp, 0._wp, &
1059 & 1._wp, -center(3), 0._wp, 0._wp, 0._wp, 1._wp], shape(tr)))
1060
1061 ! Translation matrix to move center back to original position
1062 t_back = transpose(reshape([1._wp, 0._wp, 0._wp, center(1), 0._wp, 1._wp, 0._wp, center(2), 0._wp, 0._wp, 1._wp, &
1063 & center(3), 0._wp, 0._wp, 0._wp, 1._wp], shape(tr)))
1064
1065 out_matrix = matmul(tr, matmul(t_back, matmul(ry, matmul(rx, matmul(rz, matmul(sc, t_to_origin))))))
1066 else
1067 out_matrix = matmul(ry, matmul(rx, rz))
1068 end if
1069
1070 end function f_create_transform_matrix
1071
1072 !> Transform a vector by a matrix.
1073 subroutine s_transform_vec(vec, matrix)
1074
1075 real(wp), dimension(1:3), intent(inout) :: vec
1076 real(wp), dimension(1:4,1:4), intent(in) :: matrix
1077 real(wp), dimension(1:4) :: tmp
1078
1079 tmp = matmul(matrix, [vec(1), vec(2), vec(3), 1._wp])
1080 vec = tmp(1:3)
1081
1082 end subroutine s_transform_vec
1083
1084 !> Transform a triangle by a matrix, one vertex at a time.
1085 subroutine s_transform_triangle(triangle, matrix, matrix_n)
1086
1087 type(t_triangle), intent(inout) :: triangle
1088 real(wp), dimension(1:4,1:4), intent(in) :: matrix, matrix_n
1089 integer :: i
1090
1091 do i = 1, 3
1092 call s_transform_vec(triangle%v(i,:), matrix)
1093 end do
1094
1095 call s_transform_vec(triangle%n(1:3), matrix_n)
1096
1097 end subroutine s_transform_triangle
1098
1099 !> Transform a model by a matrix, one triangle at a time.
1100 subroutine s_transform_model(model, matrix, matrix_n)
1101
1102 type(t_model), intent(inout) :: model
1103 real(wp), dimension(1:4,1:4), intent(in) :: matrix, matrix_n
1104 integer :: i
1105
1106 do i = 1, size(model%trs)
1107 call s_transform_triangle(model%trs(i), matrix, matrix_n)
1108 end do
1109
1110 end subroutine s_transform_model
1111
1112 !> Create a bounding box for a model.
1113 function f_create_bbox(model) result(bbox)
1114
1115 type(t_model), intent(in) :: model
1116 type(t_bbox) :: bbox
1117 integer :: i, j
1118
1119 if (size(model%trs) == 0) then
1120 bbox%min = 0._wp
1121 bbox%max = 0._wp
1122 return
1123 end if
1124
1125 bbox%min = model%trs(1)%v(1,:)
1126 bbox%max = model%trs(1)%v(1,:)
1127
1128 do i = 1, size(model%trs)
1129 do j = 1, 3
1130 bbox%min = min(bbox%min, model%trs(i)%v(j,:))
1131 bbox%max = max(bbox%max, model%trs(i)%v(j,:))
1132 end do
1133 end do
1134
1135 end function f_create_bbox
1136
1137 !> Perform XOR on lhs and rhs.
1138 elemental function f_xor(lhs, rhs) result(res)
1139
1140 logical, intent(in) :: lhs, rhs
1141 logical :: res
1142
1143 res = (lhs .and. .not. rhs) .or. (.not. lhs .and. rhs)
1144
1145 end function f_xor
1146
1147 !> Convert a logical to 1 or 0.
1148 elemental function f_logical_to_int(predicate) result(int)
1149
1150 logical, intent(in) :: predicate
1151 integer :: int
1152
1153 if (predicate) then
1154 int = 1
1155 else
1156 int = 0
1157 end if
1158
1159 end function f_logical_to_int
1160
1161 !> Real spherical harmonic Y_lm(theta, phi). theta = polar angle from +z (acos(z/r)), phi = atan2(y,x). Uses associated Legendre
1162 !! P_l^|m|(cos theta). Standard normalisation.
1163 function real_ylm(theta, phi, l, m) result(Y)
1164
1165 integer, intent(in) :: l, m
1166 real(wp), intent(in) :: theta, phi
1167 real(wp) :: y, x, prefac
1168 integer :: m_abs
1169
1170 m_abs = abs(m)
1171 if (m_abs > l) then
1172 y = 0._wp
1173 return
1174 end if
1175 x = cos(theta)
1176 prefac = sqrt((2*l + 1)*real(factorial(l - m_abs), wp)/real(factorial(l + m_abs), wp)/(4._wp*pi))
1177 if (m == 0) then
1178 y = prefac*associated_legendre(x, l, 0)
1179 else if (m > 0) then
1180 y = prefac*sqrt(2._wp)*associated_legendre(x, l, m_abs)*cos(m*phi)
1181 else
1182 y = prefac*sqrt(2._wp)*associated_legendre(x, l, m_abs)*sin(m_abs*phi)
1183 end if
1184
1185 end function real_ylm
1186
1187 !> Associated Legendre polynomial P_l^m(x) (Ferrers function, Condon-Shortley phase). Valid for integer l >= 0, 0 <= m <= l, and
1188 !! x in [-1,1]. Returns 0 for |m| > l or l < 0. Formulas: DLMF 14.10.3 (recurrence in degree), Wikipedia "Associated Legendre
1189 !! polynomials" (P_l^l and P_l^{l-1} identities). Recurrence: (l-m)P_l^m = (2l-1)x P_{l-1}^m - (l+m-1)P_{l-2}^m.
1190 !! @param x argument (typically cos(theta)), should be in [-1,1]
1191 !! @param l degree (>= 0)
1192 !! @param m_order order (0 <= m_order <= l)
1193 recursive function associated_legendre(x, l, m_order) result(result_P)
1194
1195 integer, intent(in) :: l, m_order
1196 real(wp), intent(in) :: x
1197 real(wp) :: result_p
1198 real(wp) :: one_minus_x2
1199
1200 ! Out-of-domain: P_l^m = 0 for |m| > l or l < 0 (standard convention)
1201
1202 if (l < 0 .or. m_order < 0 .or. m_order > l) then
1203 result_p = 0._wp
1204 return
1205 end if
1206
1207 if (m_order <= 0 .and. l <= 0) then
1208 result_p = 1._wp
1209 else if (l == 1 .and. m_order <= 0) then
1210 result_p = x
1211 else if (l == 1 .and. m_order == 1) then
1212 one_minus_x2 = max(0._wp, 1._wp - x**2)
1213 result_p = -sqrt(one_minus_x2)
1214 else if (m_order == l) then
1215 ! P_l^l(x) = (-1)^l (2l-1)!! (1-x^2)^(l/2). Use real exponent for odd l
1216 one_minus_x2 = max(0._wp, 1._wp - x**2)
1217 result_p = (-1)**l*real(double_factorial(2*l - 1), wp)*one_minus_x2**(0.5_wp*real(l, wp))
1218 else if (m_order == l - 1) then
1219 result_p = x*(2*l - 1)*associated_legendre(x, l - 1, l - 1)
1220 else
1221 result_p = ((2*l - 1)*x*associated_legendre(x, l - 1, m_order) - (l + m_order - 1)*associated_legendre(x, l - 2, &
1222 & m_order))/(l - m_order)
1223 end if
1224
1225 end function associated_legendre
1226
1227 !> Calculate the double factorial of an integer
1228 elemental function double_factorial(n_in) result(R_result)
1229
1230 integer, intent(in) :: n_in
1231 integer, parameter :: int64_kind = selected_int_kind(18) !< 18 bytes for 64-bit integer
1232 integer(kind=int64_kind) :: r_result
1233 integer :: i
1234
1235 r_result = product((/(i, i=n_in, 1, -2)/))
1236
1237 end function double_factorial
1238
1239 !> Calculate the factorial of an integer
1240 elemental function factorial(n_in) result(R_result)
1241
1242 integer, intent(in) :: n_in
1243 integer, parameter :: int64_kind = selected_int_kind(18) !< 18 bytes for 64-bit integer
1244 integer(kind=int64_kind) :: r_result
1245 integer :: i
1246
1247 r_result = product((/(i, i=n_in, 1, -1)/))
1248
1249 end function factorial
1250
1251 !> Calculate a smooth cut-on function that is zero for x values smaller than zero and goes to one, for generating smooth initial
1252 !! conditions
1253 function f_cut_on(x, eps) result(fx)
1254
1255 real(wp), intent(in) :: x, eps
1256 real(wp) :: fx
1257
1258 fx = 1 - f_gx(x/eps)/(f_gx(x/eps) + f_gx(1 - x/eps))
1259
1260 end function f_cut_on
1261
1262 !> Calculate a smooth cut-off function that is one for x values smaller than zero and goes to zero, for generating smooth
1263 !! initial conditions
1264 function f_cut_off(x, eps) result(fx)
1265
1266 real(wp), intent(in) :: x, eps
1267 real(wp) :: fx
1268
1269 fx = f_gx(x/eps)/(f_gx(x/eps) + f_gx(1 - x/eps))
1270
1271 end function f_cut_off
1272
1273 !> Helper function for f_cut_on and f_cut_off
1274 function f_gx(x) result(gx)
1275
1276 real(wp), intent(in) :: x
1277 real(wp) :: gx
1278
1279 if (x > 0) then
1280 gx = exp(-1._wp/x)
1281 else
1282 gx = 0._wp
1283 end if
1284
1285 end function f_gx
1286
1287 !> Downsample conservative variable fields by a factor of 3 in each direction using volume averaging.
1288 subroutine s_downsample_data(q_cons_vf, q_cons_temp, m_ds, n_ds, p_ds, m_glb_ds, n_glb_ds, p_glb_ds)
1289
1290 type(scalar_field), dimension(sys_size), intent(inout) :: q_cons_vf, q_cons_temp
1291
1292 ! Down sampling variables
1293 integer :: i, j, k, l
1294 integer :: ix, iy, iz, x_id, y_id, z_id
1295 integer, intent(inout) :: m_ds, n_ds, p_ds, m_glb_ds, n_glb_ds, p_glb_ds
1296
1297 m_ds = int((m + 1)/3) - 1
1298 n_ds = int((n + 1)/3) - 1
1299 p_ds = int((p + 1)/3) - 1
1300
1301 m_glb_ds = int((m_glb + 1)/3) - 1
1302 n_glb_ds = int((n_glb + 1)/3) - 1
1303 p_glb_ds = int((p_glb + 1)/3) - 1
1304
1305 do l = -1, p_ds + 1
1306 do k = -1, n_ds + 1
1307 do j = -1, m_ds + 1
1308 x_id = 3*j + 1
1309 y_id = 3*k + 1
1310 z_id = 3*l + 1
1311 do i = 1, sys_size
1312 q_cons_temp(i)%sf(j, k, l) = 0
1313
1314 do iz = -1, 1
1315 do iy = -1, 1
1316 do ix = -1, 1
1317 q_cons_temp(i)%sf(j, k, l) = q_cons_temp(i)%sf(j, k, &
1318 & l) + (1._wp/27._wp)*q_cons_vf(i)%sf(x_id + ix, y_id + iy, z_id + iz)
1319 end do
1320 end do
1321 end do
1322 end do
1323 end do
1324 end do
1325 end do
1326
1327 end subroutine s_downsample_data
1328
1329 !> Upsample conservative variable fields from a coarsened grid back to the original resolution using interpolation.
1330 subroutine s_upsample_data(q_cons_vf, q_cons_temp)
1331
1332 type(scalar_field), intent(inout), dimension(sys_size) :: q_cons_vf, q_cons_temp
1333 integer :: i, j, k, l
1334 integer :: ix, iy, iz
1335 integer :: x_id, y_id, z_id
1336 real(wp), dimension(4) :: temp
1337
1338 do l = 0, p
1339 do k = 0, n
1340 do j = 0, m
1341 do i = 1, sys_size
1342 ix = int(j/3._wp)
1343 iy = int(k/3._wp)
1344 iz = int(l/3._wp)
1345
1346 x_id = j - int(3*ix) - 1
1347 y_id = k - int(3*iy) - 1
1348 z_id = l - int(3*iz) - 1
1349
1350 temp(1) = (2._wp/3._wp)*q_cons_temp(i)%sf(ix, iy, iz) + (1._wp/3._wp)*q_cons_temp(i)%sf(ix + x_id, iy, iz)
1351 temp(2) = (2._wp/3._wp)*q_cons_temp(i)%sf(ix, iy + y_id, iz) + (1._wp/3._wp)*q_cons_temp(i)%sf(ix + x_id, &
1352 & iy + y_id, iz)
1353 temp(3) = (2._wp/3._wp)*temp(1) + (1._wp/3._wp)*temp(2)
1354
1355 temp(1) = (2._wp/3._wp)*q_cons_temp(i)%sf(ix, iy, iz + z_id) + (1._wp/3._wp)*q_cons_temp(i)%sf(ix + x_id, &
1356 & iy, iz + z_id)
1357 temp(2) = (2._wp/3._wp)*q_cons_temp(i)%sf(ix, iy + y_id, &
1358 & iz + z_id) + (1._wp/3._wp)*q_cons_temp(i)%sf(ix + x_id, iy + y_id, iz + z_id)
1359 temp(4) = (2._wp/3._wp)*temp(1) + (1._wp/3._wp)*temp(2)
1360
1361 q_cons_vf(i)%sf(j, k, l) = (2._wp/3._wp)*temp(3) + (1._wp/3._wp)*temp(4)
1362 end do
1363 end do
1364 end do
1365 end do
1366
1367 end subroutine s_upsample_data
1368
1369 !> @brief True if `location` falls within this rank's own subdomain (a strict partition - each location is owned by exactly one
1370 !! rank, unlike an overlapping multi-rank ghost-stencil neighborhood). Used by both pre_process (to decide which
1371 !! generated/namelist IBs a rank writes to its own restart_data/ib_state_0.dat chunk) and simulation (to decide which IBs a rank
1372 !! owns for its own periodic IB-state writes) so the two stay consistent. glb_bounds_in is the global domain extent, used only
1373 !! to project a location that falls just outside the domain (floating-point edge case) onto the domain so some rank still claims
1374 !! it.
1375 function f_local_rank_owns_location(location, glb_bounds_in) result(owns_location)
1376
1377
1378# 764 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1379#if MFC_OpenACC
1380# 764 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1381!$acc routine seq
1382# 764 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1383#elif MFC_OpenMP
1384# 764 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1385
1386# 764 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1387
1388# 764 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1389!$omp declare target device_type(any)
1390# 764 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1391#endif
1392# 765 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1393
1394 real(wp), dimension(3), intent(in) :: location
1395 type(bounds_info), dimension(3), intent(in) :: glb_bounds_in
1396 logical :: owns_location
1397 real(wp), dimension(3) :: projected_location
1398
1399 owns_location = .true.
1400
1401#ifdef MFC_MPI
1402 if (num_procs > 1) then
1403 projected_location(:) = location(:)
1404
1405 ! catch the edge case where the location lies just outside the computational domain
1406# 779 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1407 if (num_dims >= 1) then
1408# 780 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1409 if (ib_bc_x%beg /= bc_periodic) then
1410# 781 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1411 ! if it is outside the domain in one direction, project it somewhere inside so at least one rank owns it
1412 if (location(1) < glb_bounds_in(1)%beg) then
1413# 783 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1414 projected_location(1) = glb_bounds_in(1)%beg
1415# 784 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1416 else if (glb_bounds_in(1)%end < location(1)) then
1417# 785 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1418 projected_location(1) = glb_bounds_in(1)%end - 1.0e-10_wp
1419# 786 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1420 end if
1421 end if
1422 owns_location = owns_location .and. x_cb(-1) <= projected_location(1) &
1423# 789 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1424 & .and. projected_location(1) < x_cb(m)
1425# 790 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1426 end if
1427# 779 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1428 if (num_dims >= 2) then
1429# 780 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1430 if (ib_bc_y%beg /= bc_periodic) then
1431# 781 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1432 ! if it is outside the domain in one direction, project it somewhere inside so at least one rank owns it
1433 if (location(2) < glb_bounds_in(2)%beg) then
1434# 783 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1435 projected_location(2) = glb_bounds_in(2)%beg
1436# 784 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1437 else if (glb_bounds_in(2)%end < location(2)) then
1438# 785 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1439 projected_location(2) = glb_bounds_in(2)%end - 1.0e-10_wp
1440# 786 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1441 end if
1442 end if
1443 owns_location = owns_location .and. y_cb(-1) <= projected_location(2) &
1444# 789 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1445 & .and. projected_location(2) < y_cb(n)
1446# 790 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1447 end if
1448# 779 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1449 if (num_dims >= 3) then
1450# 780 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1451 if (ib_bc_z%beg /= bc_periodic) then
1452# 781 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1453 ! if it is outside the domain in one direction, project it somewhere inside so at least one rank owns it
1454 if (location(3) < glb_bounds_in(3)%beg) then
1455# 783 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1456 projected_location(3) = glb_bounds_in(3)%beg
1457# 784 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1458 else if (glb_bounds_in(3)%end < location(3)) then
1459# 785 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1460 projected_location(3) = glb_bounds_in(3)%end - 1.0e-10_wp
1461# 786 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1462 end if
1463 end if
1464 owns_location = owns_location .and. z_cb(-1) <= projected_location(3) &
1465# 789 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1466 & .and. projected_location(3) < z_cb(p)
1467# 790 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1468 end if
1469# 792 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
1470 end if
1471#endif
1472
1473 end function f_local_rank_owns_location
1474
1475end module m_helper
type(scalar_field), dimension(sys_size), intent(inout) q_cons_vf
integer, intent(in) k
integer, intent(in) j
integer, intent(in) l
Compile-time constant parameters: default values, tolerances, and physical constants.
real(wp), parameter pi
Pi.
integer, parameter bc_periodic
Shared derived types for field data, patch geometry, bubble dynamics, and MPI I/O structures.
Global parameters for the computational domain, fluid properties, and simulation algorithm configurat...
real(wp), dimension(:), allocatable weight
Simpson quadrature weights.
real(wp), dimension(:), allocatable r0
Bubble sizes.
Utility routines for bubble model setup, coordinate transforms, array sampling, and special functions...
subroutine, public s_comp_n_from_prim(vftmp, rtmp, ntmp, weights)
Computes the bubble number density n from the primitive variables.
subroutine, public s_cross_product(a, b, c)
Compute the cross product c = a x b of two 3D vectors.
integer function, public modmul(a)
Compute a modular multiplication step for the linear congruential pseudo-random number generator.
impure subroutine, public s_initialize_nonpoly()
Initializes non-polydisperse bubble modeling.
recursive real(wp) function, public associated_legendre(x, l, m_order)
Associated Legendre polynomial P_l^m(x) (Ferrers function, Condon-Shortley phase)....
subroutine, public s_transform_triangle(triangle, matrix, matrix_n)
Transform a triangle by a matrix, one vertex at a time.
real(wp) function, dimension(3), public f_unit_vector(theta, eta)
Generate a unit vector uniformly distributed on the sphere from two random parameters.
logical function, public f_local_rank_owns_location(location, glb_bounds_in)
True if location falls within this rank's own subdomain (a strict partition - each location is owned ...
real(wp) function, public f_cut_on(x, eps)
Calculate a smooth cut-on function that is zero for x values smaller than zero and goes to one,...
subroutine, public s_transform_model(model, matrix, matrix_n)
Transform a model by a matrix, one triangle at a time.
type(t_bbox) function, public f_create_bbox(model)
Create a bounding box for a model.
real(wp) function f_gx(x)
Helper function for f_cut_on and f_cut_off.
subroutine, public s_simpson(local_weight, local_r0)
Compute the Simpson weights for quadrature.
elemental integer(kind=int64_kind) function, public double_factorial(n_in)
Calculate the double factorial of an integer.
impure subroutine s_initialize_bubble_vars()
Set bubble physical parameters and nondimensional numbers from the input configuration.
elemental integer(kind=int64_kind) function, public factorial(n_in)
Calculate the factorial of an integer.
subroutine, public s_upsample_data(q_cons_vf, q_cons_temp)
Upsample conservative variable fields from a coarsened grid back to the original resolution using int...
real(wp) function, dimension(1:4, 1:4), public f_create_transform_matrix(param, center)
Create a transformation matrix.
pure integer(kind=int64_kind) function f_mulmod32(a, b)
a*b mod 2^32 for a, b in [0, 2^32), split into 16-bit halves of b so no intermediate exceeds 2^49
real(wp) function, public f_cut_off(x, eps)
Calculate a smooth cut-off function that is one for x values smaller than zero and goes to zero,...
subroutine, public s_transform_vec(vec, matrix)
Transform a vector by a matrix.
impure subroutine, public s_initialize_bubbles_model()
Initialize bubble model arrays for Euler or Lagrangian bubbles with polytropic or non-polytropic gas.
subroutine, public s_prng_splitmix32(var, state)
Uniform draw in [0, 1) (1 only via single-precision rounding) from a 32-bit SplitMix-style generator ...
impure subroutine, public s_print_2d_array(a, div)
Print a 2D real array to standard output, optionally dividing each element by a given scalar.
elemental subroutine, public s_transcoeff(omega, peclet, re_trans, im_trans)
Computes the transfer coefficient for the non-polytropic bubble compression process.
subroutine, public s_prng(var, seed)
Generate a pseudo-random number between 0 and 1 using a linear congruential generator.
pure real(wp) function, dimension(3), public f_cross(a, b)
Compute the cross product of two vectors.
subroutine, public s_downsample_data(q_cons_vf, q_cons_temp, m_ds, n_ds, p_ds, m_glb_ds, n_glb_ds, p_glb_ds)
Downsample conservative variable fields by a factor of 3 in each direction using volume averaging.
elemental logical function, public f_xor(lhs, rhs)
Perform XOR on lhs and rhs.
pure subroutine, public s_sort_int_key_value(keys, vals, n)
Sort the key-value pair by the key.
subroutine, public s_comp_n_from_cons(vftmp, nrtmp, ntmp, weights)
Compute the bubble number density from the conservative void fraction and weighted bubble radii.
real(wp) function, public real_ylm(theta, phi, l, m)
Real spherical harmonic Y_lm(theta, phi). theta = polar angle from +z (acos(z/r)),...
elemental integer function, public f_logical_to_int(predicate)
Convert a logical to 1 or 0.
elemental subroutine, public s_int_to_str(i, res)
Convert an integer to its trimmed string representation.
elemental subroutine, public s_swap(lhs, rhs)
Swap two real numbers.