MFC
Exascale flow solver
Loading...
Searching...
No Matches
m_compute_levelset.fpp.f90
Go to the documentation of this file.
1# 1 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
2!>
3!!@file
4!! @brief Contains module m_compute_levelset
5
6# 1 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp" 1
7# 1 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 1
8# 1 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 1
9# 2 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
10# 3 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
11# 4 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
12# 5 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
13# 6 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
14
15# 8 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
16# 9 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
17# 10 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
18
19# 17 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
20
21# 46 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
22
23# 58 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
24
25# 68 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
26
27# 98 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
28
29# 110 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
30
31# 120 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
32! New line at end of file is required for FYPP
33# 2 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 2
34# 1 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp" 1
35# 1 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 1
36# 2 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
37# 3 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
38# 4 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
39# 5 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
40# 6 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
41
42# 8 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
43# 9 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
44# 10 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
45
46# 17 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
47
48# 46 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
49
50# 58 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
51
52# 68 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
53
54# 98 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
55
56# 110 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
57
58# 120 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
59! New line at end of file is required for FYPP
60# 2 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp" 2
61
62# 4 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
63# 5 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
64# 6 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
65# 7 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
66# 8 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
67
68# 20 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
69
70# 43 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
71
72# 48 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
73
74# 53 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
75
76# 58 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
77
78# 63 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
79
80# 68 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
81
82# 76 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
83
84# 81 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
85
86# 86 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
87
88# 91 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
89
90# 96 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
91
92# 101 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
93
94# 106 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
95
96# 111 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
97
98# 116 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
99
100# 121 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
101
102# 151 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
103
104# 192 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
105
106# 207 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
107
108# 232 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
109
110# 243 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
111
112# 245 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
113# 255 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
114
115# 283 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
116
117# 293 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
118
119# 303 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
120
121# 312 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
122
123# 329 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
124
125# 339 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
126
127# 346 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
128
129# 352 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
130
131# 358 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
132
133# 364 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
134
135# 370 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
136
137# 376 "/home/runner/work/MFC/MFC/src/common/include/omp_macros.fpp"
138! New line at end of file is required for FYPP
139# 3 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 2
140# 1 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp" 1
141# 1 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp" 1
142# 2 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
143# 3 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
144# 4 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
145# 5 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
146# 6 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
147
148# 8 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
149# 9 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
150# 10 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
151
152# 17 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
153
154# 46 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
155
156# 58 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
157
158# 68 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
159
160# 98 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
161
162# 110 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
163
164# 120 "/home/runner/work/MFC/MFC/src/common/include/shared_parallel_macros.fpp"
165! New line at end of file is required for FYPP
166# 2 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp" 2
167
168# 7 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
169
170# 17 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
171
172# 22 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
173
174# 27 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
175
176# 32 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
177
178# 37 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
179
180# 42 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
181
182# 47 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
183
184# 52 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
185
186# 57 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
187
188# 62 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
189
190# 73 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
191
192# 78 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
193
194# 83 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
195
196# 88 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
197
198# 103 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
199
200# 131 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
201
202# 160 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
203
204# 175 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
205
206# 192 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
207
208# 213 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
209
210# 241 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
211
212# 256 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
213
214# 266 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
215
216# 275 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
217
218# 291 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
219
220# 301 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
221
222# 308 "/home/runner/work/MFC/MFC/src/common/include/acc_macros.fpp"
223! New line at end of file is required for FYPP
224# 4 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp" 2
225
226# 21 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
227
228# 37 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
229
230# 50 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
231
232# 104 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
233
234# 119 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
235
236# 130 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
237
238# 143 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
239
240# 171 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
241
242# 182 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
243
244# 193 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
245
246# 204 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
247
248# 214 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
249
250# 225 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
251
252# 236 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
253
254# 246 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
255
256# 252 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
257
258# 258 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
259
260# 264 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
261
262# 270 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
263
264# 272 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
265# 273 "/home/runner/work/MFC/MFC/src/common/include/parallel_macros.fpp"
266! New line at end of file is required for FYPP
267# 2 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp" 2
268
269# 14 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
270
271! Caution:
272! This macro requires the use of a binding script to set CUDA_VISIBLE_DEVICES, such that we have one GPU device per MPI rank.
273! That's because for both cudaMemAdvise (preferred location) and cudaMemPrefetchAsync we use location = device_id = 0.
274! For an example see misc/nvidia_uvm/bind.sh.
275# 63 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
276
277# 81 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
278
279# 88 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
280
281# 111 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
282
283# 127 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
284
285# 153 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
286
287# 159 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
288
289# 167 "/home/runner/work/MFC/MFC/src/common/include/macros.fpp"
290! New line at end of file is required for FYPP
291# 6 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp" 2
292
293!> @brief Computes signed-distance level-set fields and surface normals for immersed-boundary patch geometries
295
296 use m_ib_patches !< the ib patch parameters
297
298 use m_model !< subroutine(s) related to stl files
299
300 use m_derived_types !< definitions of the derived types
301
302 use m_global_parameters !< definitions of the global parameters
303
304 use m_mpi_proxy !< message passing interface (mpi) module proxy
305
306 use m_helper_basic !< functions to compare floating point numbers
307
308 implicit none
309
310 private; public :: s_apply_levelset
311
312contains
313
314 !> @brief Dispatches level-set distance and normal computations for all ghost points based on their patch geometry type.
315 impure subroutine s_apply_levelset(gps, num_gps)
316
317 type(ghost_point), dimension(:), intent(inout) :: gps
318 integer, intent(in) :: num_gps
319
320 integer :: i, patch_id, patch_geometry
321
322 ! 3D Patch Geometries
323 if (p > 0) then
324
325
326# 39 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
327
328# 39 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
329#if defined(MFC_OpenACC)
330# 39 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
331!$acc parallel loop gang vector default(present) private(i, patch_id, patch_geometry) copy(gps) copyin(patch_ib(1:num_ibs), Np)
332# 39 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
333#elif defined(MFC_OpenMP)
334# 39 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
335
336# 39 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
337
338# 39 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
339
340# 39 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
341!$omp target teams loop defaultmap(firstprivate:scalar) bind(teams,parallel) defaultmap(tofrom:aggregate) defaultmap(tofrom:allocatable) defaultmap(tofrom:pointer) private(i, patch_id, patch_geometry) map(tofrom:gps) map(to:patch_ib(1:num_ibs), Np)
342# 39 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
343#endif
344# 39 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
345
346 do i = 1, num_gps
347
348 patch_id = gps(i)%ib_patch_id
349 patch_geometry = patch_ib(patch_id)%geometry
350
351 if (patch_geometry == 8) then
352 call s_sphere_levelset(gps(i))
353 elseif (patch_geometry == 9) then
354 call s_cuboid_levelset(gps(i))
355 elseif (patch_geometry == 10) then
356 call s_cylinder_levelset(gps(i))
357 elseif (patch_geometry == 11) then
358 call s_3d_airfoil_levelset(gps(i))
359 elseif (patch_geometry == 12) then
360 call s_model_levelset(gps(i))
361 end if
362 end do
363
364# 57 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
365
366# 57 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
367#if defined(MFC_OpenACC)
368# 57 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
369!$acc end parallel loop
370# 57 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
371#elif defined(MFC_OpenMP)
372# 57 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
373
374# 57 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
375
376# 57 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
377!$omp end target teams loop
378# 57 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
379#endif
380# 57 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
381
382
383 ! 2D Patch Geometries
384 elseif (n > 0) then
385
386
387# 62 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
388
389# 62 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
390#if defined(MFC_OpenACC)
391# 62 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
392!$acc parallel loop gang vector default(present) private(i, patch_id, patch_geometry) copy(gps) copyin(Np, patch_ib(1:num_ibs))
393# 62 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
394#elif defined(MFC_OpenMP)
395# 62 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
396
397# 62 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
398
399# 62 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
400
401# 62 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
402!$omp target teams loop defaultmap(firstprivate:scalar) bind(teams,parallel) defaultmap(tofrom:aggregate) defaultmap(tofrom:allocatable) defaultmap(tofrom:pointer) private(i, patch_id, patch_geometry) map(tofrom:gps) map(to:Np, patch_ib(1:num_ibs))
403# 62 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
404#endif
405# 62 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
406
407 do i = 1, num_gps
408
409 patch_id = gps(i)%ib_patch_id
410 patch_geometry = patch_ib(patch_id)%geometry
411
412 if (patch_geometry == 2) then
413 call s_circle_levelset(gps(i))
414 elseif (patch_geometry == 3) then
415 call s_rectangle_levelset(gps(i))
416 elseif (patch_geometry == 4) then
417 call s_airfoil_levelset(gps(i))
418 elseif (patch_geometry == 5) then
419 call s_model_levelset(gps(i))
420 elseif (patch_geometry == 6) then
421 call s_ellipse_levelset(gps(i))
422 end if
423 end do
424
425# 80 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
426
427# 80 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
428#if defined(MFC_OpenACC)
429# 80 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
430!$acc end parallel loop
431# 80 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
432#elif defined(MFC_OpenMP)
433# 80 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
434
435# 80 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
436
437# 80 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
438!$omp end target teams loop
439# 80 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
440#endif
441# 80 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
442
443
444 end if
445
446 end subroutine s_apply_levelset
447
448 !> @brief Computes the signed distance and outward normal from a ghost point to a circular immersed boundary.
449 subroutine s_circle_levelset(gp)
450
451
452# 89 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
453#if MFC_OpenACC
454# 89 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
455!$acc routine seq
456# 89 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
457#elif MFC_OpenMP
458# 89 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
459
460# 89 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
461
462# 89 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
463!$omp declare target device_type(any)
464# 89 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
465#endif
466
467 type(ghost_point), intent(inout) :: gp
468
469 real(wp) :: radius, dist
470 real(wp), dimension(2) :: center
471 real(wp), dimension(3) :: dist_vec
472
473 integer :: i, j, ib_patch_id !< Loop index variables
474
475 ib_patch_id = gp%ib_patch_id
476 i = gp%loc(1)
477 j = gp%loc(2)
478
479 radius = patch_ib(ib_patch_id)%radius
480
481 dist_vec(1) = x_cc(i) - patch_ib(ib_patch_id)%x_centroid - real(gp%x_periodicity, wp)*(x_domain%end - x_domain%beg)
482 dist_vec(2) = y_cc(j) - patch_ib(ib_patch_id)%y_centroid - real(gp%y_periodicity, wp)*(y_domain%end - y_domain%beg)
483 dist_vec(3) = 0._wp
484 dist = sqrt(sum(dist_vec**2))
485
486 gp%levelset = dist - radius
487 if (f_approx_equal(dist, 0._wp)) then
488 gp%levelset_norm = 0._wp
489 else
490 gp%levelset_norm = dist_vec(:)/dist
491 end if
492
493 end subroutine s_circle_levelset
494
495 !> @brief Computes the signed distance and outward normal from a ghost point to a 2D NACA airfoil surface.
496 subroutine s_airfoil_levelset(gp)
497
498
499# 122 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
500#if MFC_OpenACC
501# 122 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
502!$acc routine seq
503# 122 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
504#elif MFC_OpenMP
505# 122 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
506
507# 122 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
508
509# 122 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
510!$omp declare target device_type(any)
511# 122 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
512#endif
513
514 type(ghost_point), intent(inout) :: gp
515
516 real(wp) :: dist, global_dist
517 integer :: global_id
518 real(wp), dimension(3) :: dist_vec
519
520 real(wp), dimension(1:3) :: xy_local, offset !< x and y coordinates in local IB frame
521 real(wp), dimension(1:2) :: center
522 real(wp), dimension(1:3, 1:3) :: rotation, inverse_rotation
523
524 integer :: i, j, k, ib_patch_id !< Loop index variables
525
526 ib_patch_id = gp%ib_patch_id
527 i = gp%loc(1)
528 j = gp%loc(2)
529
530 center(1) = patch_ib(ib_patch_id)%x_centroid + real(gp%x_periodicity, wp)*(x_domain%end - x_domain%beg)
531 center(2) = patch_ib(ib_patch_id)%y_centroid + real(gp%y_periodicity, wp)*(y_domain%end - y_domain%beg)
532 inverse_rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix_inverse(:, :)
533 rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix(:, :)
534 offset(:) = patch_ib(ib_patch_id)%centroid_offset(:)
535
536 xy_local = [x_cc(i) - center(1), y_cc(j) - center(2), 0._wp] ! get coordinate frame centered on IB
537 xy_local = matmul(inverse_rotation, xy_local) ! rotate the frame into the IB's coordinate
538 xy_local = xy_local - offset ! airfoils are a patch that require a centroid offset
539
540 if (xy_local(2) >= 0._wp) then
541 ! finds the location on the airfoil grid with the minimum distance (closest)
542 do k = 1, np
543 dist_vec(1) = xy_local(1) - airfoil_grid_u(k)%x
544 dist_vec(2) = xy_local(2) - airfoil_grid_u(k)%y
545 dist_vec(3) = 0._wp
546 dist = sqrt(sum(dist_vec**2))
547 if (k == 1) then
548 global_dist = dist
549 global_id = k
550 else
551 if (dist < global_dist) then
552 global_dist = dist
553 global_id = k
554 end if
555 end if
556 end do
557 dist_vec(1) = xy_local(1) - airfoil_grid_u(global_id)%x
558 dist_vec(2) = xy_local(2) - airfoil_grid_u(global_id)%y
559 dist_vec(3) = 0
560 dist = global_dist
561 else
562 do k = 1, np
563 dist_vec(1) = xy_local(1) - airfoil_grid_l(k)%x
564 dist_vec(2) = xy_local(2) - airfoil_grid_l(k)%y
565 dist_vec(3) = 0
566 dist = sqrt(sum(dist_vec**2))
567 if (k == 1) then
568 global_dist = dist
569 global_id = k
570 else
571 if (dist < global_dist) then
572 global_dist = dist
573 global_id = k
574 end if
575 end if
576 end do
577 dist_vec(1) = xy_local(1) - airfoil_grid_l(global_id)%x
578 dist_vec(2) = xy_local(2) - airfoil_grid_l(global_id)%y
579 dist_vec(3) = 0
580 dist = global_dist
581 end if
582
583 gp%levelset = dist
584 if (f_approx_equal(dist, 0._wp)) then
585 gp%levelset_norm = 0._wp
586 else
587 gp%levelset_norm = matmul(rotation, dist_vec(:))/dist ! convert the normal vector back to global grid coordinates
588 end if
589
590 end subroutine s_airfoil_levelset
591
592 !> @brief Computes the signed distance and outward normal from a ghost point to a 3D extruded airfoil surface including spanwise end caps.
594
595
596# 205 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
597#if MFC_OpenACC
598# 205 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
599!$acc routine seq
600# 205 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
601#elif MFC_OpenMP
602# 205 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
603
604# 205 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
605
606# 205 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
607!$omp declare target device_type(any)
608# 205 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
609#endif
610
611 type(ghost_point), intent(inout) :: gp
612
613 real(wp) :: dist, dist_surf, dist_side, global_dist
614 integer :: global_id
615 real(wp) :: lz, z_max, z_min
616 real(wp), dimension(3) :: dist_vec
617
618 real(wp), dimension(1:3) :: xyz_local, center, offset, normal !< x, y, z coordinates in local IB frame
619 real(wp), dimension(1:3, 1:3) :: rotation, inverse_rotation
620
621 real(wp) :: length_z
622
623 integer :: i, j, k, l, ib_patch_id !< Loop index variables
624
625 ib_patch_id = gp%ib_patch_id
626 i = gp%loc(1)
627 j = gp%loc(2)
628 l = gp%loc(3)
629
630 center(1) = patch_ib(ib_patch_id)%x_centroid + real(gp%x_periodicity, wp)*(x_domain%end - x_domain%beg)
631 center(2) = patch_ib(ib_patch_id)%y_centroid + real(gp%y_periodicity, wp)*(y_domain%end - y_domain%beg)
632 center(3) = patch_ib(ib_patch_id)%z_centroid + real(gp%z_periodicity, wp)*(z_domain%end - z_domain%beg)
633 lz = patch_ib(ib_patch_id)%length_z
634 inverse_rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix_inverse(:, :)
635 rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix(:, :)
636 offset(:) = patch_ib(ib_patch_id)%centroid_offset(:)
637
638 z_max = lz/2
639 z_min = -lz/2
640
641 xyz_local = [x_cc(i), y_cc(j), z_cc(l)] - center
642 xyz_local = matmul(inverse_rotation, xyz_local) ! rotate the frame into the IB's coordinates
643 xyz_local = xyz_local - offset ! airfoils are a patch that require a centroid offset
644
645 if (xyz_local(2) >= 0._wp) then
646 do k = 1, np
647 dist_vec(1) = xyz_local(1) - airfoil_grid_u(k)%x
648 dist_vec(2) = xyz_local(2) - airfoil_grid_u(k)%y
649 dist_vec(3) = 0._wp
650 dist_surf = sqrt(sum(dist_vec**2))
651 if (k == 1) then
652 global_dist = dist_surf
653 global_id = k
654 else
655 if (dist_surf < global_dist) then
656 global_dist = dist_surf
657 global_id = k
658 end if
659 end if
660 end do
661 dist_vec(1) = xyz_local(1) - airfoil_grid_u(global_id)%x
662 dist_vec(2) = xyz_local(2) - airfoil_grid_u(global_id)%y
663 dist_vec(3) = 0._wp
664 dist_surf = global_dist
665 else
666 do k = 1, np
667 dist_vec(1) = xyz_local(1) - airfoil_grid_l(k)%x
668 dist_vec(2) = xyz_local(2) - airfoil_grid_l(k)%y
669 dist_vec(3) = 0
670 dist_surf = sqrt(sum(dist_vec**2))
671 if (k == 1) then
672 global_dist = dist_surf
673 global_id = k
674 else
675 if (dist_surf < global_dist) then
676 global_dist = dist_surf
677 global_id = k
678 end if
679 end if
680 end do
681 dist_vec(1) = xyz_local(1) - airfoil_grid_l(global_id)%x
682 dist_vec(2) = xyz_local(2) - airfoil_grid_l(global_id)%y
683 dist_vec(3) = 0._wp
684 dist_surf = global_dist
685 end if
686
687 dist_side = min(abs(xyz_local(3) - z_min), abs(z_max - xyz_local(3)))
688
689 if (dist_side < dist_surf) then
690 gp%levelset = dist_side
691 normal = 0._wp
692 if (f_approx_equal(dist_side, abs(xyz_local(3) - z_min))) then
693 normal(3) = -1._wp
694 else
695 normal(3) = 1._wp
696 end if
697 gp%levelset_norm = matmul(rotation, normal)
698 else
699 gp%levelset = dist_surf
700 if (f_approx_equal(dist_surf, 0._wp)) then
701 gp%levelset_norm = 0._wp
702 else
703 gp%levelset_norm = matmul(rotation, dist_vec(:)/dist_surf)
704 end if
705 end if
706
707 end subroutine s_3d_airfoil_levelset
708
709 !> Subroutine for computing the levelset values at a ghost point belonging to the rectangle IB
710 subroutine s_rectangle_levelset(gp)
711
712
713# 308 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
714#if MFC_OpenACC
715# 308 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
716!$acc routine seq
717# 308 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
718#elif MFC_OpenMP
719# 308 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
720
721# 308 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
722
723# 308 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
724!$omp declare target device_type(any)
725# 308 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
726#endif
727
728 type(ghost_point), intent(inout) :: gp
729
730 real(wp) :: top_right(2), bottom_left(2)
731 real(wp) :: min_dist
732 real(wp) :: side_dists(4)
733
734 real(wp) :: length_x, length_y
735 real(wp), dimension(1:3) :: xy_local, dist_vec !< x and y coordinates in local IB frame
736 real(wp), dimension(2) :: center !< x and y coordinates in local IB frame
737 real(wp), dimension(1:3, 1:3) :: rotation, inverse_rotation
738
739 integer :: i, j, k !< Loop index variables
740 integer :: idx !< Shortest path direction indicator
741 integer :: ib_patch_id !< patch ID
742
743 ib_patch_id = gp%ib_patch_id
744 i = gp%loc(1)
745 j = gp%loc(2)
746
747 length_x = patch_ib(ib_patch_id)%length_x
748 length_y = patch_ib(ib_patch_id)%length_y
749 center(1) = patch_ib(ib_patch_id)%x_centroid + real(gp%x_periodicity, wp)*(x_domain%end - x_domain%beg)
750 center(2) = patch_ib(ib_patch_id)%y_centroid + real(gp%y_periodicity, wp)*(y_domain%end - y_domain%beg)
751 inverse_rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix_inverse(:, :)
752 rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix(:, :)
753
754 top_right(1) = length_x/2
755 top_right(2) = length_y/2
756 bottom_left(1) = -length_x/2
757 bottom_left(2) = -length_y/2
758
759 ! convert grid to local coordinates
760 xy_local = [x_cc(i) - center(1), y_cc(j) - center(2), 0._wp]
761 xy_local = matmul(inverse_rotation, xy_local)
762
763 side_dists(1) = bottom_left(1) - xy_local(1)
764 side_dists(2) = top_right(1) - xy_local(1)
765 side_dists(3) = bottom_left(2) - xy_local(2)
766 side_dists(4) = top_right(2) - xy_local(2)
767 min_dist = side_dists(1)
768 idx = 1
769
770 do k = 2, 4
771 if (abs(side_dists(k)) < abs(min_dist)) then
772 idx = k
773 min_dist = side_dists(idx)
774 end if
775 end do
776
777 gp%levelset = side_dists(idx)
778 dist_vec = 0._wp
779 if (.not. f_approx_equal(side_dists(idx), 0._wp)) then
780 if (idx == 1 .or. idx == 2) then
781 ! vector points along the x axis
782 dist_vec(1) = side_dists(idx)/abs(side_dists(idx))
783 else
784 ! vector points along the y axis
785 dist_vec(2) = side_dists(idx)/abs(side_dists(idx))
786 end if
787 ! convert the normal vector back into the global coordinate system
788 gp%levelset_norm = matmul(rotation, dist_vec)
789 else
790 gp%levelset_norm = 0._wp
791 end if
792
793 end subroutine s_rectangle_levelset
794
795 !> @brief Computes the signed distance and outward normal from a ghost point to an elliptical immersed boundary via a quadratic projection.
796 subroutine s_ellipse_levelset(gp)
797
798
799# 380 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
800#if MFC_OpenACC
801# 380 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
802!$acc routine seq
803# 380 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
804#elif MFC_OpenMP
805# 380 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
806
807# 380 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
808
809# 380 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
810!$omp declare target device_type(any)
811# 380 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
812#endif
813
814 type(ghost_point), intent(inout) :: gp
815
816 real(wp) :: ellipse_coeffs(2) ! a and b in the ellipse equation
817 real(wp) :: quadratic_coeffs(3) ! A, B, C in the quadratic equation to compute levelset
818
819 real(wp) :: length_x, length_y
820 real(wp), dimension(1:3) :: xy_local, normal_vector !< x and y coordinates in local IB frame
821 real(wp), dimension(2) :: center !< x and y coordinates in local IB frame
822 real(wp), dimension(1:3, 1:3) :: rotation, inverse_rotation
823
824 integer :: i, j, k !< Loop index variables
825 integer :: idx !< Shortest path direction indicator
826 integer :: ib_patch_id !< patch ID
827
828 ib_patch_id = gp%ib_patch_id
829 i = gp%loc(1)
830 j = gp%loc(2)
831
832 length_x = patch_ib(ib_patch_id)%length_x
833 length_y = patch_ib(ib_patch_id)%length_y
834 center(1) = patch_ib(ib_patch_id)%x_centroid + real(gp%x_periodicity, wp)*(x_domain%end - x_domain%beg)
835 center(2) = patch_ib(ib_patch_id)%y_centroid + real(gp%y_periodicity, wp)*(y_domain%end - y_domain%beg)
836 inverse_rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix_inverse(:, :)
837 rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix(:, :)
838
839 ellipse_coeffs(1) = 0.5_wp*length_x
840 ellipse_coeffs(2) = 0.5_wp*length_y
841
842 xy_local = [x_cc(i) - center(1), y_cc(j) - center(2), 0._wp]
843 xy_local = matmul(inverse_rotation, xy_local)
844
845 normal_vector = xy_local
846 normal_vector(2) = normal_vector(2)*(ellipse_coeffs(1)/ellipse_coeffs(2))**2._wp ! get the normal direction via the coordinate transformation method
847 normal_vector = normal_vector/sqrt(dot_product(normal_vector, normal_vector)) ! normalize the vector
848 gp%levelset_norm = matmul(rotation, normal_vector) ! save after rotating the vector to the global frame
849
850 ! use the normal vector to set up the quadratic equation for the levelset, using A, B, and C in indices 1, 2, and 3
851 quadratic_coeffs(1) = (normal_vector(1)/ellipse_coeffs(1))**2 + (normal_vector(2)/ellipse_coeffs(2))**2
852 quadratic_coeffs(2) = 2._wp*((xy_local(1)*normal_vector(1)/(ellipse_coeffs(1)**2)) + (xy_local(2)*normal_vector(2)/(ellipse_coeffs(2)**2)))
853 quadratic_coeffs(3) = (xy_local(1)/ellipse_coeffs(1))**2._wp + (xy_local(2)/ellipse_coeffs(2))**2._wp - 1._wp
854
855 ! compute the levelset with the quadratic equation [ -B + sqrt(B^2 - 4AC) ] / 2A
856 gp%levelset = -0.5_wp*(-quadratic_coeffs(2) + sqrt(quadratic_coeffs(2)**2._wp - 4._wp*quadratic_coeffs(1)*quadratic_coeffs(3)))/quadratic_coeffs(1)
857
858 end subroutine s_ellipse_levelset
859
860 !> @brief Computes the signed distance and outward normal from a ghost point to the nearest face of a cuboid immersed boundary.
861 subroutine s_cuboid_levelset(gp)
862
863
864# 431 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
865#if MFC_OpenACC
866# 431 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
867!$acc routine seq
868# 431 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
869#elif MFC_OpenMP
870# 431 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
871
872# 431 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
873
874# 431 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
875!$omp declare target device_type(any)
876# 431 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
877#endif
878
879 type(ghost_point), intent(inout) :: gp
880
881 real(wp) :: Right, Left, Bottom, Top, Front, Back
882 real(wp) :: min_dist
883 real(wp) :: dist_left, dist_right, dist_bottom, dist_top, dist_back, dist_front
884
885 real(wp), dimension(3) :: center
886 real(wp) :: length_x, length_y, length_z
887 real(wp), dimension(1:3) :: xyz_local, dist_vec !< x and y coordinates in local IB frame
888 real(wp), dimension(1:3, 1:3) :: rotation, inverse_rotation
889
890 integer :: i, j, k !< Loop index variables
891 integer :: ib_patch_id !< patch ID
892
893 ib_patch_id = gp%ib_patch_id
894 i = gp%loc(1)
895 j = gp%loc(2)
896 k = gp%loc(3)
897
898 length_x = patch_ib(ib_patch_id)%length_x
899 length_y = patch_ib(ib_patch_id)%length_y
900 length_z = patch_ib(ib_patch_id)%length_z
901
902 center(1) = patch_ib(ib_patch_id)%x_centroid + real(gp%x_periodicity, wp)*(x_domain%end - x_domain%beg)
903 center(2) = patch_ib(ib_patch_id)%y_centroid + real(gp%y_periodicity, wp)*(y_domain%end - y_domain%beg)
904 center(3) = patch_ib(ib_patch_id)%z_centroid + real(gp%z_periodicity, wp)*(z_domain%end - z_domain%beg)
905
906 inverse_rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix_inverse(:, :)
907 rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix(:, :)
908
909 right = length_x/2
910 left = -length_x/2
911 top = length_y/2
912 bottom = -length_y/2
913 front = length_z/2
914 back = -length_z/2
915
916 xyz_local = [x_cc(i), y_cc(j), z_cc(k)] - center ! get coordinate frame centered on IB
917 xyz_local = matmul(inverse_rotation, xyz_local) ! rotate the frame into the IB's coordinate
918
919 dist_left = left - xyz_local(1)
920 dist_right = xyz_local(1) - right
921 dist_bottom = bottom - xyz_local(2)
922 dist_top = xyz_local(2) - top
923 dist_back = back - xyz_local(3)
924 dist_front = xyz_local(3) - front
925
926 min_dist = min(abs(dist_left), abs(dist_right), abs(dist_bottom), &
927 abs(dist_top), abs(dist_back), abs(dist_front))
928 dist_vec = 0._wp
929
930 if (f_approx_equal(min_dist, abs(dist_left))) then
931 gp%levelset = dist_left
932 if (.not. f_approx_equal(dist_left, 0._wp)) then
933 dist_vec(1) = dist_left/abs(dist_left)
934 end if
935 else if (f_approx_equal(min_dist, abs(dist_right))) then
936 gp%levelset = dist_right
937 if (.not. f_approx_equal(dist_right, 0._wp)) then
938 dist_vec(1) = -dist_right/abs(dist_right)
939 end if
940 else if (f_approx_equal(min_dist, abs(dist_bottom))) then
941 gp%levelset = dist_bottom
942 if (.not. f_approx_equal(dist_bottom, 0._wp)) then
943 dist_vec(2) = dist_bottom/abs(dist_bottom)
944 end if
945 else if (f_approx_equal(min_dist, abs(dist_top))) then
946 gp%levelset = dist_top
947 if (.not. f_approx_equal(dist_top, 0._wp)) then
948 dist_vec(2) = -dist_top/abs(dist_top)
949 end if
950 else if (f_approx_equal(min_dist, abs(dist_back))) then
951 gp%levelset = dist_back
952 if (.not. f_approx_equal(dist_back, 0._wp)) then
953 dist_vec(3) = dist_back/abs(dist_back)
954 end if
955 else if (f_approx_equal(min_dist, abs(dist_front))) then
956 gp%levelset = dist_front
957 if (.not. f_approx_equal(dist_front, 0._wp)) then
958 dist_vec(3) = -dist_front/abs(dist_front)
959 end if
960 end if
961
962 gp%levelset_norm = matmul(rotation, dist_vec)
963
964 end subroutine s_cuboid_levelset
965
966 !> @brief Computes the signed distance and outward normal from a ghost point to a spherical immersed boundary.
967 subroutine s_sphere_levelset(gp)
968
969
970# 523 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
971#if MFC_OpenACC
972# 523 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
973!$acc routine seq
974# 523 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
975#elif MFC_OpenMP
976# 523 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
977
978# 523 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
979
980# 523 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
981!$omp declare target device_type(any)
982# 523 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
983#endif
984
985 type(ghost_point), intent(inout) :: gp
986
987 real(wp) :: radius, dist
988 real(wp), dimension(3) :: dist_vec, center, periodicity
989
990 integer :: i, j, k, ib_patch_id !< Loop index variables
991
992 ib_patch_id = gp%ib_patch_id
993 i = gp%loc(1)
994 j = gp%loc(2)
995 k = gp%loc(3)
996
997 radius = patch_ib(ib_patch_id)%radius
998 periodicity(1) = real(gp%x_periodicity, wp)*(x_domain%end - x_domain%beg)
999 periodicity(2) = real(gp%y_periodicity, wp)*(y_domain%end - y_domain%beg)
1000 periodicity(3) = real(gp%z_periodicity, wp)*(z_domain%end - z_domain%beg)
1001 center(1) = patch_ib(ib_patch_id)%x_centroid
1002 center(2) = patch_ib(ib_patch_id)%y_centroid
1003 center(3) = patch_ib(ib_patch_id)%z_centroid
1004 center = center + periodicity
1005
1006 dist_vec(1) = x_cc(i) - center(1)
1007 dist_vec(2) = y_cc(j) - center(2)
1008 dist_vec(3) = z_cc(k) - center(3)
1009 dist = sqrt(sum(dist_vec**2))
1010 gp%levelset = dist - radius
1011 if (f_approx_equal(dist, 0._wp)) then
1012 gp%levelset_norm = (/1, 0, 0/)
1013 else
1014 gp%levelset_norm = dist_vec(:)/dist
1015 end if
1016
1017 end subroutine s_sphere_levelset
1018
1019 !> @brief Computes the signed distance and outward normal from a ghost point to a cylindrical immersed boundary surface and end caps.
1020 subroutine s_cylinder_levelset(gp)
1021
1022
1023# 562 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1024#if MFC_OpenACC
1025# 562 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1026!$acc routine seq
1027# 562 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1028#elif MFC_OpenMP
1029# 562 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1030
1031# 562 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1032
1033# 562 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1034!$omp declare target device_type(any)
1035# 562 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1036#endif
1037
1038 type(ghost_point), intent(inout) :: gp
1039
1040 real(wp) :: radius
1041 real(wp), dimension(3) :: dist_sides_vec, dist_surface_vec, length
1042 real(wp), dimension(2) :: boundary
1043 real(wp) :: dist_side, dist_surface, side_pos
1044 integer :: i, j, k !< Loop index variables
1045 integer :: ib_patch_id !< patch ID
1046
1047 real(wp), dimension(1:3) :: xyz_local, center !< x and y coordinates in local IB frame
1048 real(wp), dimension(1:3, 1:3) :: rotation, inverse_rotation
1049
1050 ib_patch_id = gp%ib_patch_id
1051 i = gp%loc(1)
1052 j = gp%loc(2)
1053 k = gp%loc(3)
1054
1055 radius = patch_ib(ib_patch_id)%radius
1056 center(1) = patch_ib(ib_patch_id)%x_centroid + real(gp%x_periodicity, wp)*(x_domain%end - x_domain%beg)
1057 center(2) = patch_ib(ib_patch_id)%y_centroid + real(gp%y_periodicity, wp)*(y_domain%end - y_domain%beg)
1058 center(3) = patch_ib(ib_patch_id)%z_centroid + real(gp%z_periodicity, wp)*(z_domain%end - z_domain%beg)
1059 length(1) = patch_ib(ib_patch_id)%length_x
1060 length(2) = patch_ib(ib_patch_id)%length_y
1061 length(3) = patch_ib(ib_patch_id)%length_z
1062
1063 inverse_rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix_inverse(:, :)
1064 rotation(:, :) = patch_ib(ib_patch_id)%rotation_matrix(:, :)
1065
1066 if (.not. f_approx_equal(length(1), 0._wp)) then
1067 boundary(1) = -0.5_wp*length(1)
1068 boundary(2) = 0.5_wp*length(1)
1069 dist_sides_vec = (/1, 0, 0/)
1070 dist_surface_vec = (/0, 1, 1/)
1071 else if (.not. f_approx_equal(length(2), 0._wp)) then
1072 boundary(1) = -0.5_wp*length(2)
1073 boundary(2) = 0.5_wp*length(2)
1074 dist_sides_vec = (/0, 1, 0/)
1075 dist_surface_vec = (/1, 0, 1/)
1076 else if (.not. f_approx_equal(length(3), 0._wp)) then
1077 boundary(1) = -0.5_wp*length(3)
1078 boundary(2) = 0.5_wp*length(3)
1079 dist_sides_vec = (/0, 0, 1/)
1080 dist_surface_vec = (/1, 1, 0/)
1081 end if
1082
1083 xyz_local = [x_cc(i), y_cc(j), z_cc(k)] - center ! get coordinate frame centered on IB
1084 xyz_local = matmul(inverse_rotation, xyz_local) ! rotate the frame into the IB's coordinates
1085
1086 ! get distance to flat edge of cylinder
1087 side_pos = dot_product(xyz_local, dist_sides_vec)
1088 dist_side = min(abs(side_pos - boundary(1)), &
1089 abs(boundary(2) - side_pos))
1090 ! get distance to curved side of cylinder
1091 dist_surface = norm2(xyz_local*dist_surface_vec) &
1092 - radius
1093
1094 if (dist_side < abs(dist_surface)) then
1095 ! if the closest edge is flat
1096 gp%levelset = -dist_side
1097 if (f_approx_equal(dist_side, abs(side_pos - boundary(1)))) then
1098 gp%levelset_norm = matmul(rotation, -dist_sides_vec)
1099 else
1100 gp%levelset_norm = matmul(rotation, dist_sides_vec)
1101 end if
1102 else
1103 gp%levelset = dist_surface
1104 xyz_local = xyz_local*dist_surface_vec
1105 xyz_local = xyz_local/max(norm2(xyz_local), sgm_eps)
1106 gp%levelset_norm = matmul(rotation, xyz_local)
1107 end if
1108
1109 end subroutine s_cylinder_levelset
1110
1111 !> The STL patch is a 2/3D geometry that is imported from an STL file.
1112 !! @param gp Ghost point to compute levelset for
1113 subroutine s_model_levelset(gp)
1114
1115
1116# 641 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1117#if MFC_OpenACC
1118# 641 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1119!$acc routine seq
1120# 641 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1121#elif MFC_OpenMP
1122# 641 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1123
1124# 641 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1125
1126# 641 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1127!$omp declare target device_type(any)
1128# 641 "/home/runner/work/MFC/MFC/src/simulation/m_compute_levelset.fpp"
1129#endif
1130
1131 type(ghost_point), intent(inout) :: gp
1132
1133 integer :: i, j, k, patch_id, boundary_edge_count, total_vertices
1134 real(wp), dimension(1:3) :: center, xyz_local
1135 real(wp) :: normals(1:3) !< Boundary normal buffer
1136 real(wp) :: distance
1137 real(wp), dimension(1:3, 1:3) :: inverse_rotation, rotation
1138
1139 patch_id = gp%ib_patch_id
1140 i = gp%loc(1)
1141 j = gp%loc(2)
1142 k = gp%loc(3)
1143
1144 ! load in model values
1145 boundary_edge_count = gpu_boundary_edge_count(patch_id)
1146 total_vertices = gpu_total_vertices(patch_id)
1147
1148 center = 0._wp
1149 if (.not. f_is_default(patch_ib(patch_id)%x_centroid)) center(1) = patch_ib(patch_id)%x_centroid + real(gp%x_periodicity, wp)*(x_domain%end - x_domain%beg)
1150 if (.not. f_is_default(patch_ib(patch_id)%y_centroid)) center(2) = patch_ib(patch_id)%y_centroid + real(gp%y_periodicity, wp)*(y_domain%end - y_domain%beg)
1151 if (p > 0) then
1152 if (.not. f_is_default(patch_ib(patch_id)%z_centroid)) center(3) = patch_ib(patch_id)%z_centroid + real(gp%z_periodicity, wp)*(z_domain%end - z_domain%beg)
1153 end if
1154
1155 inverse_rotation(:, :) = patch_ib(patch_id)%rotation_matrix_inverse(:, :)
1156 rotation(:, :) = patch_ib(patch_id)%rotation_matrix(:, :)
1157
1158 ! determine where we are located in space
1159 xyz_local = (/x_cc(i) - center(1), y_cc(j) - center(2), 0._wp/)
1160 if (p > 0) then
1161 xyz_local(3) = z_cc(k) - center(3)
1162 end if
1163 xyz_local = matmul(inverse_rotation, xyz_local)
1164
1165 ! 3D models
1166 if (p > 0) then
1167 ! Get the boundary normals and shortest distance between the cell center and the model boundary
1168 call s_distance_normals_3d(gpu_ntrs(patch_id), patch_id, xyz_local, normals, distance)
1169
1170 ! Get the shortest distance between the cell center and the model boundary
1171 gp%levelset = distance
1172 gp%levelset = -abs(gp%levelset)
1173
1174 ! Assign the levelset_norm
1175 gp%levelset_norm = matmul(rotation, normals(1:3))
1176 else
1177 ! 2D models
1178 call s_distance_normals_2d(patch_id, &
1179 boundary_edge_count, &
1180 xyz_local, normals, distance)
1181 gp%levelset = -abs(distance)
1182 gp%levelset_norm = matmul(rotation, normals(1:3))
1183 end if
1184
1185 end subroutine s_model_levelset
1186
1187end module m_compute_levelset
Computes signed-distance level-set fields and surface normals for immersed-boundary patch geometries.
impure subroutine, public s_apply_levelset(gps, num_gps)
Dispatches level-set distance and normal computations for all ghost points based on their patch geome...
subroutine s_airfoil_levelset(gp)
Computes the signed distance and outward normal from a ghost point to a 2D NACA airfoil surface.
subroutine s_sphere_levelset(gp)
Computes the signed distance and outward normal from a ghost point to a spherical immersed boundary.
subroutine s_circle_levelset(gp)
Computes the signed distance and outward normal from a ghost point to a circular immersed boundary.
subroutine s_ellipse_levelset(gp)
Computes the signed distance and outward normal from a ghost point to an elliptical immersed boundary...
subroutine s_cylinder_levelset(gp)
Computes the signed distance and outward normal from a ghost point to a cylindrical immersed boundary...
subroutine s_3d_airfoil_levelset(gp)
Computes the signed distance and outward normal from a ghost point to a 3D extruded airfoil surface i...
subroutine s_rectangle_levelset(gp)
Subroutine for computing the levelset values at a ghost point belonging to the rectangle IB.
subroutine s_model_levelset(gp)
The STL patch is a 2/3D geometry that is imported from an STL file.
subroutine s_cuboid_levelset(gp)
Computes the signed distance and outward normal from a ghost point to the nearest face of a cuboid im...
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...
type(ib_patch_parameters), dimension(num_patches_max) patch_ib
type(vec3_dt), dimension(:), allocatable airfoil_grid_u
real(wp), dimension(:), allocatable, target y_cc
real(wp), dimension(:), allocatable, target z_cc
type(vec3_dt), dimension(:), allocatable airfoil_grid_l
real(wp), dimension(:), allocatable, target x_cc
Basic floating-point utilities: approximate equality, default detection, and coordinate bounds.
logical elemental function, public f_approx_equal(a, b, tol_input)
This procedure checks if two floating point numbers of wp are within tolerance.
logical elemental function, public f_is_default(var)
Checks if a real(wp) variable is of default value.
Allocate memory and read initial condition data for IC extrusion.
Binary STL file reader and processor for immersed boundary geometry.
integer, dimension(:), allocatable, public gpu_total_vertices
subroutine, public s_distance_normals_2d(pid, boundary_edge_count, point, normals, distance)
This procedure determines the levelset distance and normals of 2D models by computing the exact close...
integer, dimension(:), allocatable, public gpu_ntrs
subroutine, public s_distance_normals_3d(ntrs, pid, point, normals, distance)
This procedure determines the levelset distance and normals of 3D models by computing the exact close...
integer, dimension(:), allocatable, public gpu_boundary_edge_count
MPI halo exchange, domain decomposition, and buffer packing/unpacking for the simulation solver.
Ghost Point for Immersed Boundaries.