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# 9 "/home/runner/work/MFC/MFC/src/common/include/case.fpp"
9
10! For moving immersed boundaries in simulation
11# 14 "/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# 17 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
27
28# 46 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
29
30# 58 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
31
32# 68 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
33
34# 98 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
35
36# 110 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
37
38# 120 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
39! New line at end of file is required for FYPP
40# 2 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 2
41# 1 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp" 1
42# 1 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 1
43# 2 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
44# 3 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
45# 4 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
46# 5 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
47# 6 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
48
49# 8 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
50# 9 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
51# 10 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
52
53# 17 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
54
55# 46 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
56
57# 58 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
58
59# 68 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
60
61# 98 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
62
63# 110 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
64
65# 120 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
66! New line at end of file is required for FYPP
67# 2 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp" 2
68
69# 4 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
70# 5 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
71# 6 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
72# 7 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
73# 8 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
74
75# 20 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
76
77# 43 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
78
79# 48 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
80
81# 53 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
82
83# 58 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
84
85# 63 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
86
87# 68 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
88
89# 76 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
90
91# 81 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
92
93# 86 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
94
95# 91 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
96
97# 96 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
98
99# 101 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
100
101# 106 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
102
103# 111 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
104
105# 116 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
106
107# 121 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
108
109# 151 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
110
111# 192 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
112
113# 207 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
114
115# 232 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
116
117# 243 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
118
119# 245 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
120# 255 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
121
122# 283 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
123
124# 293 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
125
126# 303 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
127
128# 312 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
129
130# 329 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
131
132# 339 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
133
134# 346 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
135
136# 352 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
137
138# 358 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
139
140# 364 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
141
142# 370 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
143
144# 376 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
145! New line at end of file is required for FYPP
146# 3 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 2
147# 1 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp" 1
148# 1 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 1
149# 2 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
150# 3 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
151# 4 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
152# 5 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
153# 6 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
154
155# 8 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
156# 9 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
157# 10 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
158
159# 17 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
160
161# 46 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
162
163# 58 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
164
165# 68 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
166
167# 98 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
168
169# 110 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
170
171# 120 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
172! New line at end of file is required for FYPP
173# 2 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp" 2
174
175# 7 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
176
177# 17 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
178
179# 22 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
180
181# 27 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
182
183# 32 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
184
185# 37 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
186
187# 42 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
188
189# 47 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
190
191# 52 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
192
193# 57 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
194
195# 62 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
196
197# 73 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
198
199# 78 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
200
201# 83 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
202
203# 88 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
204
205# 103 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
206
207# 131 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
208
209# 160 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
210
211# 175 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
212
213# 192 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
214
215# 213 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
216
217# 241 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
218
219# 256 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
220
221# 266 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
222
223# 275 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
224
225# 291 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
226
227# 301 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
228
229# 308 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
230! New line at end of file is required for FYPP
231# 4 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 2
232
233# 21 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
234
235# 37 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
236
237# 50 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
238
239# 104 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
240
241# 119 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
242
243# 130 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
244
245# 143 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
246
247# 171 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
248
249# 182 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
250
251# 193 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
252
253# 204 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
254
255# 214 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
256
257# 225 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
258
259# 236 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
260
261# 246 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
262
263# 252 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
264
265# 258 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
266
267# 264 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
268
269# 270 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
270
271# 272 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
272# 273 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
273! New line at end of file is required for FYPP
274# 2 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp" 2
275
276# 14 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
277
278! Caution:
279! This macro requires the use of a binding script to set CUDA_VISIBLE_DEVICES, such that we have one GPU device per MPI rank.
280! That's because for both cudaMemAdvise (preferred location) and cudaMemPrefetchAsync we use location = device_id = 0.
281! For an example see misc/nvidia_uvm/bind.sh.
282# 63 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
283
284# 81 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
285
286# 88 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
287
288# 111 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
289
290# 127 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
291
292# 153 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
293
294# 159 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
295
296# 167 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
297! New line at end of file is required for FYPP
298# 3 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp" 2
299
300!>
301!! @file
302!! @brief Contains module m_helper
303
304!> @brief Utility routines for bubble model setup, coordinate transforms, array sampling, and special functions
306
307 use m_derived_types !< definitions of the derived types
308
309 use m_global_parameters !< definitions of the global parameters
310
311 use ieee_arithmetic !< for checking nan
312
313 implicit none
314
315 private;
316 public :: s_comp_n_from_prim, &
320 s_simpson, &
321 s_transcoeff, &
322 s_int_to_str, &
326 s_swap, &
327 f_cross, &
331 f_xor, &
334 real_ylm, &
336 factorial, &
337 f_cut_on, &
338 f_cut_off, &
341
342contains
343
344 !> Computes the bubble number density n from the primitive variables
345 !! @param vftmp is the void fraction
346 !! @param Rtmp is the bubble radii
347 !! @param ntmp is the output number bubble density
348 !! @param weights is the quadrature weights
349 subroutine s_comp_n_from_prim(vftmp, Rtmp, ntmp, weights)
350
351# 54 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
352#if MFC_OpenACC
353# 54 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
354!$acc routine seq
355# 54 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
356#elif MFC_OpenMP
357# 54 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
358
359# 54 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
360
361# 54 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
362!$omp declare target device_type(any)
363# 54 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
364#endif
365 real(wp), intent(in) :: vftmp
366 real(wp), dimension(nb), intent(in) :: rtmp
367 real(wp), intent(out) :: ntmp
368 real(wp), dimension(nb), intent(in) :: weights
369
370 real(wp) :: r3
371
372 r3 = dot_product(weights, rtmp**3._wp)
373 ntmp = (3._wp/(4._wp*pi))*vftmp/r3
374
375 end subroutine s_comp_n_from_prim
376
377 !> @brief Computes the bubble number density from the conservative void fraction and weighted bubble radii.
378 subroutine s_comp_n_from_cons(vftmp, nRtmp, ntmp, weights)
379
380# 69 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
381#if MFC_OpenACC
382# 69 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
383!$acc routine seq
384# 69 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
385#elif MFC_OpenMP
386# 69 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
387
388# 69 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
389
390# 69 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
391!$omp declare target device_type(any)
392# 69 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
393#endif
394 real(wp), intent(in) :: vftmp
395 real(wp), dimension(nb), intent(in) :: nrtmp
396 real(wp), intent(out) :: ntmp
397 real(wp), dimension(nb), intent(in) :: weights
398
399 real(wp) :: nr3
400
401 nr3 = dot_product(weights, nrtmp**3._wp)
402 ntmp = sqrt((4._wp*pi/3._wp)*nr3/vftmp)
403
404 end subroutine s_comp_n_from_cons
405
406 !> @brief Prints a 2D real array to standard output, optionally dividing each element by a given scalar.
407 impure subroutine s_print_2d_array(A, div)
408
409 real(wp), dimension(:, :), intent(in) :: a
410 real(wp), optional, intent(in) :: div
411
412 integer :: i, j
413 integer :: local_m, local_n
414 real(wp) :: c
415
416 local_m = size(a, 1)
417 local_n = size(a, 2)
418
419 if (present(div)) then
420 c = div
421 else
422 c = 1._wp
423 end if
424
425 print *, local_m, local_n
426
427 do i = 1, local_m
428 do j = 1, local_n
429 write (*, fmt="(F12.4)", advance="no") a(i, j)/c
430 end do
431 write (*, fmt="(A1)") " "
432 end do
433 write (*, fmt="(A1)") " "
434
435 end subroutine s_print_2d_array
436
437 !>
438 !! bubbles_euler + polytropic
439 !! bubbles_euler + non-polytropic
440 !! bubbles_lagrange + non-polytropic
441 impure subroutine s_initialize_bubbles_model()
442
443 ! Allocate memory
444 if (bubbles_euler) then
445#ifdef MFC_DEBUG
446# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
447 block
448# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
449 use iso_fortran_env, only: output_unit
450# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
451
452# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
453 print *, 'm_helper.fpp:121: ', '@:ALLOCATE(weight(nb), R0(nb))'
454# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
455
456# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
457 call flush (output_unit)
458# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
459 end block
460# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
461#endif
462# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
463 allocate (weight(nb), r0(nb))
464# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
465
466# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
467
468# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
469
470# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
471#if defined(MFC_OpenACC)
472# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
473!$acc enter data create(weight, R0)
474# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
475#elif defined(MFC_OpenMP)
476# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
477!$omp target enter data map(always,alloc:weight, R0)
478# 121 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
479#endif
480 if (.not. polytropic) then
481#ifdef MFC_DEBUG
482# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
483 block
484# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
485 use iso_fortran_env, only: output_unit
486# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
487
488# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
489 print *, 'm_helper.fpp:123: ', '@:ALLOCATE(pb0(nb), Pe_T(nb), k_g(nb), k_v(nb), mass_g0(nb), mass_v0(nb))'
490# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
491
492# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
493 call flush (output_unit)
494# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
495 end block
496# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
497#endif
498# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
499 allocate (pb0(nb), pe_t(nb), k_g(nb), k_v(nb), mass_g0(nb), mass_v0(nb))
500# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
501
502# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
503
504# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
505
506# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
507
508# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
509
510# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
511
512# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
513
514# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
515#if defined(MFC_OpenACC)
516# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
517!$acc enter data create(pb0, Pe_T, k_g, k_v, mass_g0, mass_v0)
518# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
519#elif defined(MFC_OpenMP)
520# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
521!$omp target enter data map(always,alloc:pb0, Pe_T, k_g, k_v, mass_g0, mass_v0)
522# 123 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
523#endif
524#ifdef MFC_DEBUG
525# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
526 block
527# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
528 use iso_fortran_env, only: output_unit
529# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
530
531# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
532 print *, 'm_helper.fpp:124: ', '@:ALLOCATE(Re_trans_T(nb), Re_trans_c(nb), Im_trans_T(nb), Im_trans_c(nb))'
533# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
534
535# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
536 call flush (output_unit)
537# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
538 end block
539# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
540#endif
541# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
542 allocate (re_trans_t(nb), re_trans_c(nb), im_trans_t(nb), im_trans_c(nb))
543# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
544
545# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
546
547# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
548
549# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
550
551# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
552
553# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
554#if defined(MFC_OpenACC)
555# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
556!$acc enter data create(Re_trans_T, Re_trans_c, Im_trans_T, Im_trans_c)
557# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
558#elif defined(MFC_OpenMP)
559# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
560!$omp target enter data map(always,alloc:Re_trans_T, Re_trans_c, Im_trans_T, Im_trans_c)
561# 124 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
562#endif
563 else if (qbmm) then
564#ifdef MFC_DEBUG
565# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
566 block
567# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
568 use iso_fortran_env, only: output_unit
569# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
570
571# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
572 print *, 'm_helper.fpp:126: ', '@:ALLOCATE(pb0(nb))'
573# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
574
575# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
576 call flush (output_unit)
577# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
578 end block
579# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
580#endif
581# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
582 allocate (pb0(nb))
583# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
584
585# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
586
587# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
588#if defined(MFC_OpenACC)
589# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
590!$acc enter data create(pb0)
591# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
592#elif defined(MFC_OpenMP)
593# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
594!$omp target enter data map(always,alloc:pb0)
595# 126 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
596#endif
597 end if
598
599 ! Compute quadrature weights and nodes for polydisperse simulations
600 if (nb > 1) then
601 call s_simpson(weight, r0)
602 else if (nb == 1) then
603 r0 = 1._wp
604 weight = 1._wp
605 else
606 stop 'Invalid value of nb'
607 end if
608 r0 = r0*bub_pp%R0ref
609 end if
610
611 ! Initialize bubble variables
613
614 end subroutine s_initialize_bubbles_model
615
616 !>
617 impure subroutine s_initialize_bubble_vars()
618
619 r0ref = bub_pp%R0ref; p0ref = bub_pp%p0ref
620 rho0ref = bub_pp%rho0ref;
621 ss = bub_pp%ss; pv = bub_pp%pv; vd = bub_pp%vd
622 mu_l = bub_pp%mu_l; mu_v = bub_pp%mu_v; mu_g = bub_pp%mu_g
623 gam_v = bub_pp%gam_v; gam_g = bub_pp%gam_g
624 if (.not. polytropic) then
625 if (bubbles_euler) then
626 m_v = bub_pp%M_v; m_g = bub_pp%M_g
627 k_v = bub_pp%k_v; k_g = bub_pp%k_g
628 end if
629 r_v = bub_pp%R_v; r_g = bub_pp%R_g
630 tw = bub_pp%T0ref
631 end if
632 if (bubbles_lagrange) then
633 cp_v = bub_pp%cp_v; cp_g = bub_pp%cp_g
634 k_vl = bub_pp%k_v; k_gl = bub_pp%k_g
635 end if
636
637 ! Input quantities
638 if (bubbles_euler .and. (.not. polytropic)) then
639 if (thermal == 2) then
640 gam_m = 1._wp
641 else
642 gam_m = gam_g
643 end if
644 end if
645
646 ! Nondimensional numbers
647 eu = p0ref
648 ca = eu - pv
649 if (.not. f_is_default(bub_pp%ss)) web = 1._wp/ss
650 if (.not. f_is_default(bub_pp%mu_l)) re_inv = mu_l
651 if (.not. polytropic) pe_c = 1._wp/vd
652
653 if (bubbles_euler) then
654 ! Initialize variables for non-polytropic (Preston) model
655 if (.not. polytropic) then
657 end if
658 ! Initialize pb based on surface tension for qbmm (polytropic)
659 if (qbmm .and. polytropic) then
660 pb0 = eu
661 if (.not. f_is_default(web)) then
662 pb0 = pb0 + 2._wp/web/r0
663 end if
664 end if
665 end if
666
667 end subroutine s_initialize_bubble_vars
668
669 !> Initializes non-polydisperse bubble modeling
670 impure subroutine s_initialize_nonpoly()
671 integer :: ir
672 real(wp), dimension(nb) :: chi_vw0, cp_m0, k_m0, rho_m0, x_vw, omegan, rhol0
673
674 real(wp), parameter :: k_poly = 1._wp !<
675 !! polytropic index used to compute isothermal natural frequency
676
677 ! phi_vg & phi_gv (phi_gg = phi_vv = 1) (Eq. 2.22 in Ando 2010)
678 phi_vg = (1._wp + sqrt(mu_v/mu_g)*(m_g/m_v)**(0.25_wp))**2 &
679 /(sqrt(8._wp)*sqrt(1._wp + m_v/m_g))
680 phi_gv = (1._wp + sqrt(mu_g/mu_v)*(m_v/m_g)**(0.25_wp))**2 &
681 /(sqrt(8._wp)*sqrt(1._wp + m_g/m_v))
682
683 ! internal bubble pressure
684 pb0 = eu + 2._wp/web/r0
685
686 ! mass fraction of vapor (Eq. 2.19 in Ando 2010)
687 chi_vw0 = 1._wp/(1._wp + r_v/r_g*(pb0/pv - 1._wp))
688
689 ! specific heat for gas/vapor mixture
690 cp_m0 = chi_vw0*r_v*gam_v/(gam_v - 1._wp) &
691 + (1._wp - chi_vw0)*r_g*gam_g/(gam_g - 1._wp)
692
693 ! mole fraction of vapor (Eq. 2.23 in Ando 2010)
694 x_vw = m_g*chi_vw0/(m_v + (m_g - m_v)*chi_vw0)
695
696 ! thermal conductivity for gas/vapor mixture (Eq. 2.21 in Ando 2010)
697 k_m0 = x_vw*k_v/(x_vw + (1._wp - x_vw)*phi_vg) &
698 + (1._wp - x_vw)*k_g/(x_vw*phi_gv + 1._wp - x_vw)
699 k_g(:) = k_g(:)/k_m0(:)
700 k_v(:) = k_v(:)/k_m0(:)
701
702 ! mixture density (Eq. 2.20 in Ando 2010)
703 rho_m0 = pv/(chi_vw0*r_v*tw)
704
705 ! mass of gas/vapor
706 mass_g0(:) = (4._wp*pi/3._wp)*(pb0(:) - pv)/(r_g*tw)*r0(:)**3
707 mass_v0(:) = (4._wp*pi/3._wp)*pv/(r_v*tw)*r0(:)**3
708
709 ! Peclet numbers
710 pe_t(:) = rho_m0*cp_m0(:)/k_m0(:)
711
712 ! natural frequencies (Eq. B.1)
713 omegan(:) = sqrt(3._wp*k_poly*ca + 2._wp*(3._wp*k_poly - 1._wp)/(web*r0))/r0/sqrt(rho0ref)
714 do ir = 1, nb
715 call s_transcoeff(omegan(ir)*r0(ir), pe_t(ir)*r0(ir), &
716 re_trans_t(ir), im_trans_t(ir))
717 call s_transcoeff(omegan(ir)*r0(ir), pe_c*r0(ir), &
718 re_trans_c(ir), im_trans_c(ir))
719 end do
720 im_trans_t = 0._wp
721
722 end subroutine s_initialize_nonpoly
723
724 !> Computes the transfer coefficient for the non-polytropic bubble compression process
725 !! @param omega natural frequencies
726 !! @param peclet Peclet number
727 !! @param Re_trans Real part of the transport coefficients
728 !! @param Im_trans Imaginary part of the transport coefficients
729 elemental subroutine s_transcoeff(omega, peclet, Re_trans, Im_trans)
730
731 real(wp), intent(in) :: omega, peclet
732 real(wp), intent(out) :: re_trans, im_trans
733
734 complex(wp) :: imag, trans, c1, c2, c3
735
736 imag = (0._wp, 1._wp)
737
738 c1 = imag*omega*peclet
739 c2 = sqrt(c1)
740 c3 = (exp(c2) - exp(-c2))/(exp(c2) + exp(-c2)) ! TANH(c2)
741 trans = ((c2/c3 - 1._wp)**(-1) - 3._wp/c1)**(-1) ! transfer function
742
743 re_trans = trans
744 im_trans = aimag(trans)
745
746 end subroutine s_transcoeff
747
748 !> @brief Converts an integer to its trimmed string representation.
749 elemental subroutine s_int_to_str(i, res)
750
751 integer, intent(in) :: i
752 character(len=*), intent(inout) :: res
753
754 write (res, '(I0)') i
755 res = trim(res)
756 end subroutine s_int_to_str
757
758 !> Computes the Simpson weights for quadrature
759 subroutine s_simpson(local_weight, local_R0)
760
761 real(wp), dimension(:), intent(inout) :: local_weight
762 real(wp), dimension(:), intent(inout) :: local_r0
763 integer :: ir
764 real(wp) :: r0mn, r0mx, dphi, tmp, sd
765 real(wp), dimension(nb) :: phi
766
767 sd = poly_sigma
768 r0mn = 0.8_wp*exp(-2.8_wp*sd)
769 r0mx = 0.2_wp*exp(9.5_wp*sd) + 1._wp
770
771 ! phi = ln( R0 ) & return R0
772 do ir = 1, nb
773 phi(ir) = log(r0mn) &
774 + (ir - 1._wp)*log(r0mx/r0mn)/(nb - 1._wp)
775 local_r0(ir) = exp(phi(ir))
776 end do
777
778# 309 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
779 dphi = phi(2) - phi(1)
780# 311 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
781
782 ! weights for quadrature using Simpson's rule
783 do ir = 2, nb - 1
784 ! Gaussian
785 tmp = exp(-0.5_wp*(phi(ir)/sd)**2)/sqrt(2._wp*pi)/sd
786 if (mod(ir, 2) == 0) then
787 local_weight(ir) = tmp*4._wp*dphi/3._wp
788 else
789 local_weight(ir) = tmp*2._wp*dphi/3._wp
790 end if
791 end do
792 tmp = exp(-0.5_wp*(phi(1)/sd)**2)/sqrt(2._wp*pi)/sd
793 local_weight(1) = tmp*dphi/3._wp
794 tmp = exp(-0.5_wp*(phi(nb)/sd)**2)/sqrt(2._wp*pi)/sd
795 local_weight(nb) = tmp*dphi/3._wp
796
797 end subroutine s_simpson
798
799 !> This procedure computes the cross product of two vectors.
800 !! @param a First vector.
801 !! @param b Second vector.
802 !! @return The cross product of the two vectors.
803 pure function f_cross(a, b) result(c)
804
805
806# 335 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
807#if MFC_OpenACC
808# 335 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
809!$acc routine seq
810# 335 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
811#elif MFC_OpenMP
812# 335 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
813
814# 335 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
815
816# 335 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
817!$omp declare target device_type(any)
818# 335 "/home/runner/work/MFC/MFC/src/common/m_helper.fpp"
819#endif
820
821 real(wp), dimension(3), intent(in) :: a, b
822 real(wp), dimension(3) :: c
823
824 c(1) = a(2)*b(3) - a(3)*b(2)
825 c(2) = a(3)*b(1) - a(1)*b(3)
826 c(3) = a(1)*b(2) - a(2)*b(1)
827 end function f_cross
828
829 !> This procedure swaps two real numbers.
830 !! @param lhs Left-hand side.
831 !! @param rhs Right-hand side.
832 elemental subroutine s_swap(lhs, rhs)
833
834 real(wp), intent(inout) :: lhs, rhs
835 real(wp) :: ltemp
836
837 ltemp = lhs
838 lhs = rhs
839 rhs = ltemp
840 end subroutine s_swap
841
842 !> This procedure creates a transformation matrix.
843 !! @param param Parameters for the transformation.
844 !! @param center Optional center point for the transformation.
845 !! @return Transformation matrix.
846 function f_create_transform_matrix(param, center) result(out_matrix)
847
848 type(ic_model_parameters), intent(in) :: param
849 real(wp), dimension(1:3), optional, intent(in) :: center
850 real(wp), dimension(1:4, 1:4) :: sc, rz, rx, ry, tr, t_back, t_to_origin, out_matrix
851
852 sc = transpose(reshape([ &
853 param%scale(1), 0._wp, 0._wp, 0._wp, &
854 0._wp, param%scale(2), 0._wp, 0._wp, &
855 0._wp, 0._wp, param%scale(3), 0._wp, &
856 0._wp, 0._wp, 0._wp, 1._wp], shape(sc)))
857
858 rz = transpose(reshape([ &
859 cos(param%rotate(3)), -sin(param%rotate(3)), 0._wp, 0._wp, &
860 sin(param%rotate(3)), cos(param%rotate(3)), 0._wp, 0._wp, &
861 0._wp, 0._wp, 1._wp, 0._wp, &
862 0._wp, 0._wp, 0._wp, 1._wp], shape(rz)))
863
864 rx = transpose(reshape([ &
865 1._wp, 0._wp, 0._wp, 0._wp, &
866 0._wp, cos(param%rotate(1)), -sin(param%rotate(1)), 0._wp, &
867 0._wp, sin(param%rotate(1)), cos(param%rotate(1)), 0._wp, &
868 0._wp, 0._wp, 0._wp, 1._wp], shape(rx)))
869
870 ry = transpose(reshape([ &
871 cos(param%rotate(2)), 0._wp, sin(param%rotate(2)), 0._wp, &
872 0._wp, 1._wp, 0._wp, 0._wp, &
873 -sin(param%rotate(2)), 0._wp, cos(param%rotate(2)), 0._wp, &
874 0._wp, 0._wp, 0._wp, 1._wp], shape(ry)))
875
876 tr = transpose(reshape([ &
877 1._wp, 0._wp, 0._wp, param%translate(1), &
878 0._wp, 1._wp, 0._wp, param%translate(2), &
879 0._wp, 0._wp, 1._wp, param%translate(3), &
880 0._wp, 0._wp, 0._wp, 1._wp], shape(tr)))
881
882 if (present(center)) then
883 ! Translation matrix to move center to the origin
884 t_to_origin = transpose(reshape([ &
885 1._wp, 0._wp, 0._wp, -center(1), &
886 0._wp, 1._wp, 0._wp, -center(2), &
887 0._wp, 0._wp, 1._wp, -center(3), &
888 0._wp, 0._wp, 0._wp, 1._wp], shape(tr)))
889
890 ! Translation matrix to move center back to original position
891 t_back = transpose(reshape([ &
892 1._wp, 0._wp, 0._wp, center(1), &
893 0._wp, 1._wp, 0._wp, center(2), &
894 0._wp, 0._wp, 1._wp, center(3), &
895 0._wp, 0._wp, 0._wp, 1._wp], shape(tr)))
896
897 out_matrix = matmul(tr, matmul(t_back, matmul(ry, matmul(rx, matmul(rz, matmul(sc, t_to_origin))))))
898 else
899 out_matrix = matmul(ry, matmul(rx, rz))
900 end if
901
902 end function f_create_transform_matrix
903
904 !> This procedure transforms a vector by a matrix.
905 !! @param vec Vector to transform.
906 !! @param matrix Transformation matrix.
907 subroutine s_transform_vec(vec, matrix)
908
909 real(wp), dimension(1:3), intent(inout) :: vec
910 real(wp), dimension(1:4, 1:4), intent(in) :: matrix
911
912 real(wp), dimension(1:4) :: tmp
913
914 tmp = matmul(matrix, [vec(1), vec(2), vec(3), 1._wp])
915 vec = tmp(1:3)
916
917 end subroutine s_transform_vec
918
919 !> This procedure transforms a triangle by a matrix, one vertex at a time.
920 !! @param triangle Triangle to transform.
921 !! @param matrix Transformation matrix.
922 !! @param matrix_n Normal transformation matrix.
923 subroutine s_transform_triangle(triangle, matrix, matrix_n)
924
925 type(t_triangle), intent(inout) :: triangle
926 real(wp), dimension(1:4, 1:4), intent(in) :: matrix, matrix_n
927
928 integer :: i
929
930 do i = 1, 3
931 call s_transform_vec(triangle%v(i, :), matrix)
932 end do
933
934 call s_transform_vec(triangle%n(1:3), matrix_n)
935
936 end subroutine s_transform_triangle
937
938 !> This procedure transforms a model by a matrix, one triangle at a time.
939 !! @param model Model to transform.
940 !! @param matrix Transformation matrix.
941 !! @param matrix_n Normal transformation matrix.
942 subroutine s_transform_model(model, matrix, matrix_n)
943
944 type(t_model), intent(inout) :: model
945 real(wp), dimension(1:4, 1:4), intent(in) :: matrix, matrix_n
946
947 integer :: i
948
949 do i = 1, size(model%trs)
950 call s_transform_triangle(model%trs(i), matrix, matrix_n)
951 end do
952
953 end subroutine s_transform_model
954
955 !> This procedure creates a bounding box for a model.
956 !! @param model Model to create bounding box for.
957 !! @return Bounding box.
958 function f_create_bbox(model) result(bbox)
959
960 type(t_model), intent(in) :: model
961 type(t_bbox) :: bbox
962
963 integer :: i, j
964
965 if (size(model%trs) == 0) then
966 bbox%min = 0._wp
967 bbox%max = 0._wp
968 return
969 end if
970
971 bbox%min = model%trs(1)%v(1, :)
972 bbox%max = model%trs(1)%v(1, :)
973
974 do i = 1, size(model%trs)
975 do j = 1, 3
976 bbox%min = min(bbox%min, model%trs(i)%v(j, :))
977 bbox%max = max(bbox%max, model%trs(i)%v(j, :))
978 end do
979 end do
980
981 end function f_create_bbox
982
983 !> This procedure performs xor on lhs and rhs.
984 !! @param lhs logical input.
985 !! @param rhs other logical input.
986 !! @return xored result.
987 elemental function f_xor(lhs, rhs) result(res)
988
989 logical, intent(in) :: lhs, rhs
990 logical :: res
991
992 res = (lhs .and. .not. rhs) .or. (.not. lhs .and. rhs)
993 end function f_xor
994
995 !> This procedure converts logical to 1 or 0.
996 !! @param predicate A Logical argument.
997 !! @return 1 if .true., 0 if .false..
998 elemental function f_logical_to_int(predicate) result(int)
999
1000 logical, intent(in) :: predicate
1001 integer :: int
1002
1003 if (predicate) then
1004 int = 1
1005 else
1006 int = 0
1007 end if
1008 end function f_logical_to_int
1009
1010 !> Real spherical harmonic Y_lm(theta, phi). theta = polar angle from +z (acos(z/r)),
1011 !! phi = atan2(y,x). Uses associated Legendre P_l^|m|(cos theta). Standard normalisation.
1012 function real_ylm(theta, phi, l, m) result(Y)
1013 integer, intent(in) :: l, m
1014 real(wp), intent(in) :: theta, phi
1015 real(wp) :: y, x, prefac
1016 integer :: m_abs
1017
1018 m_abs = abs(m)
1019 if (m_abs > l) then
1020 y = 0._wp
1021 return
1022 end if
1023 x = cos(theta)
1024 prefac = sqrt((2*l + 1)*real(factorial(l - m_abs), wp)/real(factorial(l + m_abs), wp)/(4._wp*pi))
1025 if (m == 0) then
1026 y = prefac*associated_legendre(x, l, 0)
1027 else if (m > 0) then
1028 y = prefac*sqrt(2._wp)*associated_legendre(x, l, m_abs)*cos(m*phi)
1029 else
1030 y = prefac*sqrt(2._wp)*associated_legendre(x, l, m_abs)*sin(m_abs*phi)
1031 end if
1032 end function real_ylm
1033
1034 !> Associated Legendre polynomial P_l^m(x) (Ferrers function, Condon-Shortley phase).
1035 !! Valid for integer l >= 0, 0 <= m <= l, and x in [-1,1]. Returns 0 for |m| > l or l < 0.
1036 !! Formulas: DLMF 14.10.3 (recurrence in degree), Wikipedia "Associated Legendre polynomials"
1037 !! (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.
1038 !! @param x argument (typically cos(theta)), should be in [-1,1]
1039 !! @param l degree (>= 0)
1040 !! @param m_order order (0 <= m_order <= l)
1041 !! @return result_P P_l^m(x)
1042 recursive function associated_legendre(x, l, m_order) result(result_P)
1043
1044 integer, intent(in) :: l, m_order
1045 real(wp), intent(in) :: x
1046 real(wp) :: result_p
1047 real(wp) :: one_minus_x2
1048
1049 ! Out-of-domain: P_l^m = 0 for |m| > l or l < 0 (standard convention)
1050 if (l < 0 .or. m_order < 0 .or. m_order > l) then
1051 result_p = 0._wp
1052 return
1053 end if
1054
1055 if (m_order <= 0 .and. l <= 0) then
1056 result_p = 1._wp
1057 elseif (l == 1 .and. m_order <= 0) then
1058 result_p = x
1059 elseif (l == 1 .and. m_order == 1) then
1060 one_minus_x2 = max(0._wp, 1._wp - x**2)
1061 result_p = -sqrt(one_minus_x2)
1062 elseif (m_order == l) then
1063 ! P_l^l(x) = (-1)^l (2l-1)!! (1-x^2)^(l/2). Use real exponent for odd l
1064 one_minus_x2 = max(0._wp, 1._wp - x**2)
1065 result_p = (-1)**l*real(double_factorial(2*l - 1), wp)*one_minus_x2**(0.5_wp*real(l, wp))
1066 elseif (m_order == l - 1) then
1067 result_p = x*(2*l - 1)*associated_legendre(x, l - 1, l - 1)
1068 else
1069 result_p = ((2*l - 1)*x*associated_legendre(x, l - 1, m_order) - (l + m_order - 1)*associated_legendre(x, l - 2, m_order))/(l - m_order)
1070 end if
1071
1072 end function associated_legendre
1073
1074 !> This function calculates the double factorial value of an integer
1075 !! @param n_in is the input integer
1076 !! @return R is the double factorial value of n
1077 elemental function double_factorial(n_in) result(R_result)
1078
1079 integer, intent(in) :: n_in
1080 integer, parameter :: int64_kind = selected_int_kind(18) ! 18 bytes for 64-bit integer
1081 integer(kind=int64_kind) :: r_result
1082 integer :: i
1083
1084 r_result = product((/(i, i=n_in, 1, -2)/))
1085
1086 end function double_factorial
1087
1088 !> The following function calculates the factorial value of an integer
1089 !! @param n_in is the input integer
1090 !! @return R is the factorial value of n
1091 elemental function factorial(n_in) result(R_result)
1092
1093 integer, intent(in) :: n_in
1094 integer, parameter :: int64_kind = selected_int_kind(18) ! 18 bytes for 64-bit integer
1095 integer(kind=int64_kind) :: r_result
1096
1097 integer :: i
1098
1099 r_result = product((/(i, i=n_in, 1, -1)/))
1100
1101 end function factorial
1102
1103 !> This function calculates a smooth cut-on function that is zero for x values
1104 !! smaller than zero and goes to one. It can be used for generating smooth
1105 !! initial conditions
1106 !! @param x is the input value
1107 !! @param eps is the smoothing parameter
1108 !! @return fx is the cut-on function evaluated at x
1109 function f_cut_on(x, eps) result(fx)
1110
1111 real(wp), intent(in) :: x, eps
1112 real(wp) :: fx
1113
1114 fx = 1 - f_gx(x/eps)/(f_gx(x/eps) + f_gx(1 - x/eps))
1115
1116 end function f_cut_on
1117
1118 !> This function calculates a smooth cut-off function that is one for x values
1119 !! smaller than zero and goes to zero. It can be used for generating smooth
1120 !! initial conditions
1121 !! @param x is the input value
1122 !! @param eps is the smoothing parameter
1123 !! @return fx is the cut-ff function evaluated at x
1124 function f_cut_off(x, eps) result(fx)
1125
1126 real(wp), intent(in) :: x, eps
1127 real(wp) :: fx
1128
1129 fx = f_gx(x/eps)/(f_gx(x/eps) + f_gx(1 - x/eps))
1130
1131 end function f_cut_off
1132
1133 !> This function is a helper function for the functions f_cut_on and f_cut_off
1134 !! @param x is the input value
1135 !! @return gx is the result
1136 function f_gx(x) result(gx)
1137
1138 real(wp), intent(in) :: x
1139 real(wp) :: gx
1140
1141 if (x > 0) then
1142 gx = exp(-1._wp/x)
1143 else
1144 gx = 0._wp
1145 end if
1146
1147 end function f_gx
1148
1149 !> @brief Downsamples conservative variable fields by a factor of 3 in each direction using volume averaging.
1150 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)
1151
1152 type(scalar_field), dimension(sys_size), intent(inout) :: q_cons_vf, q_cons_temp
1153
1154 ! Down sampling variables
1155 integer :: i, j, k, l
1156 integer :: ix, iy, iz, x_id, y_id, z_id
1157 integer, intent(inout) :: m_ds, n_ds, p_ds, m_glb_ds, n_glb_ds, p_glb_ds
1158
1159 m_ds = int((m + 1)/3) - 1
1160 n_ds = int((n + 1)/3) - 1
1161 p_ds = int((p + 1)/3) - 1
1162
1163 m_glb_ds = int((m_glb + 1)/3) - 1
1164 n_glb_ds = int((n_glb + 1)/3) - 1
1165 p_glb_ds = int((p_glb + 1)/3) - 1
1166
1167 do l = -1, p_ds + 1
1168 do k = -1, n_ds + 1
1169 do j = -1, m_ds + 1
1170 x_id = 3*j + 1
1171 y_id = 3*k + 1
1172 z_id = 3*l + 1
1173 do i = 1, sys_size
1174 q_cons_temp(i)%sf(j, k, l) = 0
1175
1176 do iz = -1, 1
1177 do iy = -1, 1
1178 do ix = -1, 1
1179 q_cons_temp(i)%sf(j, k, l) = q_cons_temp(i)%sf(j, k, l) &
1180 + (1._wp/27._wp)*q_cons_vf(i)%sf(x_id + ix, y_id + iy, z_id + iz)
1181 end do
1182 end do
1183 end do
1184 end do
1185 end do
1186 end do
1187 end do
1188
1189 end subroutine s_downsample_data
1190
1191 !> @brief Upsamples conservative variable fields from a coarsened grid back to the original resolution using interpolation.
1192 subroutine s_upsample_data(q_cons_vf, q_cons_temp)
1193
1194 type(scalar_field), intent(inout), dimension(sys_size) :: q_cons_vf, q_cons_temp
1195 integer :: i, j, k, l
1196 integer :: ix, iy, iz
1197 integer :: x_id, y_id, z_id
1198 real(wp), dimension(4) :: temp
1199
1200 do l = 0, p
1201 do k = 0, n
1202 do j = 0, m
1203 do i = 1, sys_size
1204
1205 ix = int(j/3._wp)
1206 iy = int(k/3._wp)
1207 iz = int(l/3._wp)
1208
1209 x_id = j - int(3*ix) - 1
1210 y_id = k - int(3*iy) - 1
1211 z_id = l - int(3*iz) - 1
1212
1213 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)
1214 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, iy + y_id, iz)
1215 temp(3) = (2._wp/3._wp)*temp(1) + (1._wp/3._wp)*temp(2)
1216
1217 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, iy, iz + z_id)
1218 temp(2) = (2._wp/3._wp)*q_cons_temp(i)%sf(ix, iy + y_id, iz + z_id) + (1._wp/3._wp)*q_cons_temp(i)%sf(ix + x_id, iy + y_id, iz + z_id)
1219 temp(4) = (2._wp/3._wp)*temp(1) + (1._wp/3._wp)*temp(2)
1220
1221 q_cons_vf(i)%sf(j, k, l) = (2._wp/3._wp)*temp(3) + (1._wp/3._wp)*temp(4)
1222
1223 end do
1224 end do
1225 end do
1226 end do
1227
1228 end subroutine s_upsample_data
1229
1230end 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
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...
logical bubbles_euler
Bubbles euler on/off.
real(wp), dimension(:), allocatable weight
Simpson quadrature weights.
real(wp), dimension(:), allocatable r0
Bubble sizes.
logical polytropic
Polytropic switch.
integer nb
Number of eq. 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.
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)
This procedure transforms a triangle by a matrix, one vertex at a time.
real(wp) function, public f_cut_on(x, eps)
This function calculates a smooth cut-on function that is zero for x values smaller than zero and goe...
subroutine, public s_transform_model(model, matrix, matrix_n)
This procedure transforms a model by a matrix, one triangle at a time.
type(t_bbox) function, public f_create_bbox(model)
This procedure creates a bounding box for a model.
real(wp) function f_gx(x)
This function is a helper function for the functions f_cut_on and f_cut_off.
subroutine, public s_simpson(local_weight, local_r0)
Computes the Simpson weights for quadrature.
elemental integer(kind=int64_kind) function, public double_factorial(n_in)
This function calculates the double factorial value of an integer.
impure subroutine s_initialize_bubble_vars()
elemental integer(kind=int64_kind) function, public factorial(n_in)
The following function calculates the factorial value of an integer.
subroutine, public s_upsample_data(q_cons_vf, q_cons_temp)
Upsamples conservative variable fields from a coarsened grid back to the original resolution using in...
real(wp) function, public f_cut_off(x, eps)
This function calculates a smooth cut-off function that is one for x values smaller than zero and goe...
subroutine, public s_transform_vec(vec, matrix)
This procedure transforms a vector by a matrix.
impure subroutine, public s_initialize_bubbles_model()
bubbles_euler + polytropic bubbles_euler + non-polytropic bubbles_lagrange + non-polytropic
impure subroutine, public s_print_2d_array(a, div)
Prints 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.
pure real(wp) function, dimension(3), public f_cross(a, b)
This procedure computes 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)
Downsamples conservative variable fields by a factor of 3 in each direction using volume averaging.
elemental logical function, public f_xor(lhs, rhs)
This procedure performs xor on lhs and rhs.
subroutine, public s_comp_n_from_cons(vftmp, nrtmp, ntmp, weights)
Computes 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)),...
real(wp) function, dimension(1:4, 1:4), public f_create_transform_matrix(param, center)
This procedure creates a transformation matrix.
elemental integer function, public f_logical_to_int(predicate)
This procedure converts logical to 1 or 0.
elemental subroutine, public s_int_to_str(i, res)
Converts an integer to its trimmed string representation.
elemental subroutine, public s_swap(lhs, rhs)
This procedure swaps two real numbers.