MFC
Exascale flow solver
Loading...
Searching...
No Matches
m_data_output.fpp.f90
Go to the documentation of this file.
1# 1 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
2!>
3!! @file
4!! @brief Contains module m_data_output
5
6!> @brief Writes post-processed grid and flow-variable data to Silo-HDF5 or binary database files
8
9 use m_derived_types ! Definitions of the derived types
10
11 use m_global_parameters ! Global parameters
12
13 use m_derived_variables !< procedures used to compute quantities derived
14
15 use m_mpi_proxy ! Message passing interface (MPI) module proxy
16
18
19 use m_helper
20
22
23 implicit none
24
25 private; public :: s_initialize_data_output_module, &
40
41 ! Including the Silo Fortran interface library that features the subroutines
42 ! and parameters that are required to write in the Silo-HDF5 database format
43 ! INCLUDE 'silo.inc'
44 include 'silo_f9x.inc'
45
46 ! Generic storage for flow variable(s) that are to be written to formatted
47 ! database file(s). Note that for 1D simulations, q_root_sf is employed to
48 ! gather the flow variable(s) from all sub-domains on to the root process.
49 ! If the run is not parallel, but serial, then q_root_sf is equal to q_sf.
50 real(wp), allocatable, dimension(:, :, :), public :: q_sf
51 real(wp), allocatable, dimension(:, :, :) :: q_root_sf
52 real(wp), allocatable, dimension(:, :, :) :: cyl_q_sf
53
54 ! Single precision storage for flow variables
55 real(sp), allocatable, dimension(:, :, :), public :: q_sf_s
56 real(sp), allocatable, dimension(:, :, :) :: q_root_sf_s
57 real(sp), allocatable, dimension(:, :, :) :: cyl_q_sf_s
58
59 ! The spatial and data extents array variables contain information about the
60 ! minimum and maximum values of the grid and flow variable(s), respectively.
61 ! The purpose of bookkeeping this information is to boost the visualization
62 ! of the Silo-HDF5 database file(s) in VisIt.
63 real(wp), allocatable, dimension(:, :) :: spatial_extents
64 real(wp), allocatable, dimension(:, :) :: data_extents
65
66 ! The size of the ghost zone layer at beginning of each coordinate direction
67 ! (lo) and at end of each coordinate direction (hi). Adding this information
68 ! to Silo-HDF5 database file(s) is recommended since it supplies VisIt with
69 ! connectivity information between the sub-domains of a parallel data set.
70 integer, allocatable, dimension(:) :: lo_offset
71 integer, allocatable, dimension(:) :: hi_offset
72
73 ! For Silo-HDF5 database format, this variable is used to keep track of the
74 ! number of cell-boundaries, for the grid associated with the local process,
75 ! in each of the active coordinate directions.
76 integer, allocatable, dimension(:) :: dims
77
78 ! Locations of various folders in the case's directory tree, associated with
79 ! the choice of the formatted database format. These include, in order, the
80 ! location of the folder named after the selected formatted database format,
81 ! and the locations of two sub-directories of the latter, the first of which
82 ! is named after the local processor rank, while the second is named 'root'.
83 ! The folder associated with the local processor rank contains only the data
84 ! pertaining to the part of the domain taken care of by the local processor.
85 ! The root directory, on the other hand, will contain either the information
86 ! about the connectivity required to put the entire domain back together, or
87 ! the actual data associated with the entire computational domain. This all
88 ! depends on dimensionality and the choice of the formatted database format.
89 character(LEN=path_len + name_len) :: dbdir
90 character(LEN=path_len + 2*name_len) :: proc_rank_dir
91 character(LEN=path_len + 2*name_len) :: rootdir
92
93 ! Handles of the formatted database master/root file, slave/local processor
94 ! file and options list. The list of options is explicitly used in the Silo-
95 ! HDF5 database format to provide additional details about the contents of a
96 ! formatted database file, such as the previously described spatial and data
97 ! extents.
98 integer :: dbroot
99 integer :: dbfile
100 integer :: optlist
101
102 ! The total number of flow variable(s) to be stored in a formatted database
103 ! file. Note that this is only needed when using the Binary format.
104 integer :: dbvars
105
106 ! Generic error flags utilized in the handling, checking and the reporting
107 ! of the input and output operations errors with a formatted database file
108 integer, private :: err
109
110contains
111
112 !> @brief Allocate storage arrays, configure output directories, and count flow variables for formatted database output.
114 ! Description: Computation of parameters, allocation procedures, and/or
115 ! any other tasks needed to properly setup the module
116
117 ! Generic string used to store the location of a particular file
118 character(LEN=len_trim(case_dir) + 2*name_len) :: file_loc
119
120 ! Generic logical used to test the existence of a particular folder
121 logical :: dir_check
122
123 integer :: i
124
125 ! Allocating the generic storage for the flow variable(s) that are
126 ! going to be written to the formatted database file(s). Note once
127 ! more that the root variable is only required for 1D computations.
128 allocate (q_sf(-offset_x%beg:m + offset_x%end, &
129 -offset_y%beg:n + offset_y%end, &
130 -offset_z%beg:p + offset_z%end))
131 if (grid_geometry == 3) then
132 allocate (cyl_q_sf(-offset_y%beg:n + offset_y%end, &
133 -offset_z%beg:p + offset_z%end, &
134 -offset_x%beg:m + offset_x%end))
135 end if
136
137 if (precision == 1) then
138 allocate (q_sf_s(-offset_x%beg:m + offset_x%end, &
139 -offset_y%beg:n + offset_y%end, &
140 -offset_z%beg:p + offset_z%end))
141 if (grid_geometry == 3) then
142 allocate (cyl_q_sf_s(-offset_y%beg:n + offset_y%end, &
143 -offset_z%beg:p + offset_z%end, &
144 -offset_x%beg:m + offset_x%end))
145 end if
146 end if
147
148 if (n == 0) then
149 allocate (q_root_sf(0:m_root, 0:0, 0:0))
150 if (precision == 1) then
151 allocate (q_root_sf_s(0:m_root, 0:0, 0:0))
152 end if
153 end if
154
155 ! Allocating the spatial and data extents and also the variables for
156 ! the offsets and the one bookkeeping the number of cell-boundaries
157 ! in each active coordinate direction. Note that all these variables
158 ! are only needed by the Silo-HDF5 format for multidimensional data.
159 if (format == 1) then
160
161 allocate (data_extents(1:2, 0:num_procs - 1))
162
163 if (p > 0) then
164 allocate (spatial_extents(1:6, 0:num_procs - 1))
165 allocate (lo_offset(1:3))
166 allocate (hi_offset(1:3))
167 allocate (dims(1:3))
168 elseif (n > 0) then
169 allocate (spatial_extents(1:4, 0:num_procs - 1))
170 allocate (lo_offset(1:2))
171 allocate (hi_offset(1:2))
172 allocate (dims(1:2))
173 else
174 allocate (spatial_extents(1:2, 0:num_procs - 1))
175 allocate (lo_offset(1:1))
176 allocate (hi_offset(1:1))
177 allocate (dims(1:1))
178 end if
179
180 end if
181
182 ! The size of the ghost zone layer in each of the active coordinate
183 ! directions was set in the module m_mpi_proxy.f90. The results are
184 ! now transferred to the local variables of this module when they are
185 ! required by the Silo-HDF5 format, for multidimensional data sets.
186 ! With the same, latter, requirements, the variables bookkeeping the
187 ! number of cell-boundaries in each active coordinate direction are
188 ! also set here.
189 if (format == 1) then
190 if (p > 0) then
191 if (grid_geometry == 3) then
192 lo_offset(:) = (/offset_y%beg, offset_z%beg, offset_x%beg/)
193 hi_offset(:) = (/offset_y%end, offset_z%end, offset_x%end/)
194 else
195 lo_offset(:) = (/offset_x%beg, offset_y%beg, offset_z%beg/)
196 hi_offset(:) = (/offset_x%end, offset_y%end, offset_z%end/)
197 end if
198
199 if (grid_geometry == 3) then
200 dims(:) = (/n + offset_y%beg + offset_y%end + 2, &
201 p + offset_z%beg + offset_z%end + 2, &
202 m + offset_x%beg + offset_x%end + 2/)
203 else
204 dims(:) = (/m + offset_x%beg + offset_x%end + 2, &
205 n + offset_y%beg + offset_y%end + 2, &
206 p + offset_z%beg + offset_z%end + 2/)
207 end if
208 elseif (n > 0) then
209 lo_offset(:) = (/offset_x%beg, offset_y%beg/)
210 hi_offset(:) = (/offset_x%end, offset_y%end/)
211
212 dims(:) = (/m + offset_x%beg + offset_x%end + 2, &
213 n + offset_y%beg + offset_y%end + 2/)
214 else
215 lo_offset(:) = (/offset_x%beg/)
216 hi_offset(:) = (/offset_x%end/)
217 dims(:) = (/m + offset_x%beg + offset_x%end + 2/)
218 end if
219 end if
220
221 ! Generating Silo-HDF5 Directory Tree
222 if (format == 1) then
223
224 ! Creating the directory associated with the local process
225 dbdir = trim(case_dir)//'/silo_hdf5'
226
227 write (proc_rank_dir, '(A,I0)') '/p', proc_rank
228
229 proc_rank_dir = trim(dbdir)//trim(proc_rank_dir)
230
231 file_loc = trim(proc_rank_dir)//'/.'
232
233 call my_inquire(file_loc, dir_check)
234 if (dir_check .neqv. .true.) then
236 end if
237
238 ! Creating the directory associated with the root process
239 if (proc_rank == 0) then
240
241 rootdir = trim(dbdir)//'/root'
242
243 file_loc = trim(rootdir)//'/.'
244
245 call my_inquire(file_loc, dir_check)
246 if (dir_check .neqv. .true.) then
247 call s_create_directory(trim(rootdir))
248 end if
249
250 end if
251
252 ! Generating Binary Directory Tree
253
254 else
255
256 ! Creating the directory associated with the local process
257 dbdir = trim(case_dir)//'/binary'
258
259 write (proc_rank_dir, '(A,I0)') '/p', proc_rank
260
261 proc_rank_dir = trim(dbdir)//trim(proc_rank_dir)
262
263 file_loc = trim(proc_rank_dir)//'/.'
264
265 call my_inquire(file_loc, dir_check)
266
267 if (dir_check .neqv. .true.) then
269 end if
270
271 ! Creating the directory associated with the root process
272 if (n == 0 .and. proc_rank == 0) then
273
274 rootdir = trim(dbdir)//'/root'
275
276 file_loc = trim(rootdir)//'/.'
277
278 call my_inquire(file_loc, dir_check)
279
280 if (dir_check .neqv. .true.) then
281 call s_create_directory(trim(rootdir))
282 end if
283
284 end if
285
286 end if
287
288 if (bubbles_lagrange) then !Lagrangian solver
289 if (lag_txt_wrt) then
290 dbdir = trim(case_dir)//'/lag_bubbles_post_process'
291 file_loc = trim(dbdir)//'/.'
292 call my_inquire(file_loc, dir_check)
293
294 if (dir_check .neqv. .true.) then
295 call s_create_directory(trim(dbdir))
296 end if
297 end if
298 end if
299
300 ! Contrary to the Silo-HDF5 database format, handles of the Binary
301 ! database master/root and slave/local process files are perfectly
302 ! static throughout post-process. Hence, they are set here so that
303 ! they do not have to be repetitively computed in later procedures.
304 if (format == 2) then
305 if (n == 0 .and. proc_rank == 0) dbroot = 2
306 dbfile = 1
307 end if
308
309 ! Querying Number of Flow Variable(s) in Binary Output
310
311 if (format == 2) then
312
313 ! Initializing the counter of the number of flow variable(s) to
314 ! be written to the formatted database file(s)
315 dbvars = 0
316
317 ! Partial densities
318 if ((model_eqns == 2) .or. (model_eqns == 3)) then
319 do i = 1, num_fluids
320 if (alpha_rho_wrt(i) &
321 .or. &
322 (cons_vars_wrt .or. prim_vars_wrt)) then
323 dbvars = dbvars + 1
324 end if
325 end do
326 end if
327
328 ! Density
329 if ((rho_wrt .or. (model_eqns == 1 .and. (cons_vars_wrt .or. prim_vars_wrt))) &
330 .and. (.not. relativity)) then
331 dbvars = dbvars + 1
332 end if
333
334 if (relativity .and. (rho_wrt .or. prim_vars_wrt)) dbvars = dbvars + 1
335 if (relativity .and. (rho_wrt .or. cons_vars_wrt)) dbvars = dbvars + 1
336
337 ! Momentum
338 do i = 1, e_idx - mom_idx%beg
339 if (mom_wrt(i) .or. cons_vars_wrt) dbvars = dbvars + 1
340 end do
341
342 ! Velocity
343 do i = 1, e_idx - mom_idx%beg
344 if (vel_wrt(i) .or. prim_vars_wrt) dbvars = dbvars + 1
345 end do
346
347 ! Flux limiter function
348 do i = 1, e_idx - mom_idx%beg
349 if (flux_wrt(i)) dbvars = dbvars + 1
350 end do
351
352 ! Energy
353 if (e_wrt .or. cons_vars_wrt) dbvars = dbvars + 1
354
355 ! Pressure
356 if (pres_wrt .or. prim_vars_wrt) dbvars = dbvars + 1
357
358 ! Elastic stresses
359 if (hypoelasticity) dbvars = dbvars + (num_dims*(num_dims + 1))/2
360
361 ! Damage state variable
362 if (cont_damage) dbvars = dbvars + 1
363
364 ! Hyperbolic cleaning for MHD
365 if (hyper_cleaning) dbvars = dbvars + 1
366
367 ! Magnetic field
368 if (mhd) then
369 if (n == 0) then
370 dbvars = dbvars + 2
371 else
372 dbvars = dbvars + 3
373 end if
374 end if
375
376 ! Volume fraction(s)
377 if ((model_eqns == 2) .or. (model_eqns == 3)) then
378
379 do i = 1, num_fluids - 1
380 if (alpha_wrt(i) &
381 .or. &
382 (cons_vars_wrt .or. prim_vars_wrt)) then
383 dbvars = dbvars + 1
384 end if
385 end do
386
387 if (alpha_wrt(num_fluids) &
388 .or. &
390 then
391 dbvars = dbvars + 1
392 end if
393
394 end if
395
396 ! Specific heat ratio function
397 if (gamma_wrt &
398 .or. &
399 (model_eqns == 1 .and. (cons_vars_wrt .or. prim_vars_wrt))) &
400 then
401 dbvars = dbvars + 1
402 end if
403
404 ! Specific heat ratio
405 if (heat_ratio_wrt) dbvars = dbvars + 1
406
407 ! Liquid stiffness function
408 if (pi_inf_wrt &
409 .or. &
410 (model_eqns == 1 .and. (cons_vars_wrt .or. prim_vars_wrt))) &
411 then
412 dbvars = dbvars + 1
413 end if
414
415 ! Liquid stiffness
416 if (pres_inf_wrt) dbvars = dbvars + 1
417
418 ! Speed of sound
419 if (c_wrt) dbvars = dbvars + 1
420
421 ! Vorticity
422 if (p > 0) then
423 do i = 1, num_vels
424 if (omega_wrt(i)) dbvars = dbvars + 1
425 end do
426 elseif (n > 0) then
427 do i = 1, num_vels
428 if (omega_wrt(i)) dbvars = dbvars + 1
429 end do
430 end if
431
432 ! Numerical Schlieren function
433 if (schlieren_wrt) dbvars = dbvars + 1
434
435 end if
436
437 ! END: Querying Number of Flow Variable(s) in Binary Output
438
440
441 !> @brief Compute the cell-index bounds for the user-specified partial output domain in each coordinate direction.
442 impure subroutine s_define_output_region
443
444 integer :: i
445 integer :: lower_bound, upper_bound
446
447# 447 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
448
449 if (m == 0) return ! Early return for y or z if simulation is 1D or 2D
450
451 lower_bound = -offset_x%beg
452 upper_bound = m+offset_x%end
453
454 do i = lower_bound, upper_bound
455 if (x_cc(i) > x_output%beg) then
456 x_output_idx%beg = i + offset_x%beg
457 exit
458 end if
459 end do
460
461 do i = upper_bound, lower_bound, -1
462 if (x_cc(i) < x_output%end) then
463 x_output_idx%end = i + offset_x%beg
464 exit
465 end if
466 end do
467
468 ! If no grid points are within the output region
469 if ((x_cc(lower_bound) > x_output%end) .or. (x_cc(upper_bound) < x_output%beg)) then
470 x_output_idx%beg = 0
471 x_output_idx%end = 0
472 end if
473
474# 447 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
475
476 if (n == 0) return ! Early return for y or z if simulation is 1D or 2D
477
478 lower_bound = -offset_y%beg
479 upper_bound = n+offset_y%end
480
481 do i = lower_bound, upper_bound
482 if (y_cc(i) > y_output%beg) then
483 y_output_idx%beg = i + offset_y%beg
484 exit
485 end if
486 end do
487
488 do i = upper_bound, lower_bound, -1
489 if (y_cc(i) < y_output%end) then
490 y_output_idx%end = i + offset_y%beg
491 exit
492 end if
493 end do
494
495 ! If no grid points are within the output region
496 if ((y_cc(lower_bound) > y_output%end) .or. (y_cc(upper_bound) < y_output%beg)) then
497 y_output_idx%beg = 0
498 y_output_idx%end = 0
499 end if
500
501# 447 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
502
503 if (p == 0) return ! Early return for y or z if simulation is 1D or 2D
504
505 lower_bound = -offset_z%beg
506 upper_bound = p+offset_z%end
507
508 do i = lower_bound, upper_bound
509 if (z_cc(i) > z_output%beg) then
510 z_output_idx%beg = i + offset_z%beg
511 exit
512 end if
513 end do
514
515 do i = upper_bound, lower_bound, -1
516 if (z_cc(i) < z_output%end) then
517 z_output_idx%end = i + offset_z%beg
518 exit
519 end if
520 end do
521
522 ! If no grid points are within the output region
523 if ((z_cc(lower_bound) > z_output%end) .or. (z_cc(upper_bound) < z_output%beg)) then
524 z_output_idx%beg = 0
525 z_output_idx%end = 0
526 end if
527
528# 474 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
529
530 end subroutine s_define_output_region
531
532 !> @brief Open (or create) the Silo-HDF5 or Binary formatted database slave and master files for a given time step.
533 impure subroutine s_open_formatted_database_file(t_step)
534 ! Description: This subroutine opens a new formatted database file, or
535 ! replaces an old one, and readies it for the data storage
536 ! of the grid and the flow variable(s) associated with the
537 ! current time-step, t_step. This is performed by all the
538 ! local process(es). The root processor, in addition, must
539 ! also generate a master formatted database file whose job
540 ! will be to link, and thus combine, the data from all of
541 ! the local process(es). Note that for the Binary format,
542 ! this extra task that is assigned to the root process is
543 ! not performed in multidimensions.
544
545 ! Time-step that is currently being post-processed
546 integer, intent(IN) :: t_step
547
548 ! Generic string used to store the location of a particular file
549 character(LEN=len_trim(case_dir) + 3*name_len) :: file_loc
550
551 integer :: ierr !< Generic flag used to identify and report database errors
552
553 ! Silo-HDF5 Database Format
554
555 if (format == 1) then
556
557 ! Generating the relative path to the formatted database slave
558 ! file, that is to be opened for the current time-step, t_step
559 write (file_loc, '(A,I0,A)') '/', t_step, '.silo'
560 file_loc = trim(proc_rank_dir)//trim(file_loc)
561
562 ! Creating formatted database slave file at the above location
563 ! and setting up the structure of the file and its header info
564 ierr = dbcreate(trim(file_loc), len_trim(file_loc), &
565 db_clobber, db_local, 'MFC v3.0', 8, &
566 db_hdf5, dbfile)
567
568 ! Verifying that the creation and setup process of the formatted
569 ! database slave file has been performed without errors. If this
570 ! is not the case, the post-process exits.
571 if (dbfile == -1) then
572 call s_mpi_abort('Unable to create Silo-HDF5 database '// &
573 'slave file '//trim(file_loc)//'. '// &
574 'Exiting.')
575 end if
576
577 ! Next, analogous steps to the ones above are carried out by the
578 ! root process to create and setup the formatted database master
579 ! file.
580 if (proc_rank == 0) then
581
582 write (file_loc, '(A,I0,A)') '/collection_', t_step, '.silo'
583 file_loc = trim(rootdir)//trim(file_loc)
584
585 ierr = dbcreate(trim(file_loc), len_trim(file_loc), &
586 db_clobber, db_local, 'MFC v3.0', 8, &
587 db_hdf5, dbroot)
588
589 if (dbroot == -1) then
590 call s_mpi_abort('Unable to create Silo-HDF5 database '// &
591 'master file '//trim(file_loc)//'. '// &
592 'Exiting.')
593 end if
594
595 end if
596
597 ! Binary Database Format
598
599 else
600
601 ! Generating the relative path to the formatted database slave
602 ! file, that is to be opened for the current time-step, t_step
603 write (file_loc, '(A,I0,A)') '/', t_step, '.dat'
604 file_loc = trim(proc_rank_dir)//trim(file_loc)
605
606 ! Creating the formatted database slave file, at the previously
607 ! precised relative path location, and setting up its structure
608 open (dbfile, iostat=err, file=trim(file_loc), &
609 form='unformatted', status='replace')
610
611 ! Verifying that the creation and setup process of the formatted
612 ! database slave file has been performed without errors. If this
613 ! is not the case, the post-process exits.
614 if (err /= 0) then
615 call s_mpi_abort('Unable to create Binary database slave '// &
616 'file '//trim(file_loc)//'. Exiting.')
617 end if
618
619 ! Further defining the structure of the formatted database slave
620 ! file by describing in it the dimensionality of post-processed
621 ! data as well as the total number of flow variable(s) that will
622 ! eventually be stored in it
623 if (output_partial_domain) then
624 write (dbfile) x_output_idx%end - x_output_idx%beg, &
625 y_output_idx%end - y_output_idx%beg, &
626 z_output_idx%end - z_output_idx%beg, &
627 dbvars
628 else
629 write (dbfile) m, n, p, dbvars
630 end if
631
632 ! Next, analogous steps to the ones above are carried out by the
633 ! root process to create and setup the formatted database master
634 ! file. Note that this is only done in multidimensional cases.
635 if (n == 0 .and. proc_rank == 0) then
636
637 write (file_loc, '(A,I0,A)') '/', t_step, '.dat'
638 file_loc = trim(rootdir)//trim(file_loc)
639
640 open (dbroot, iostat=err, file=trim(file_loc), &
641 form='unformatted', status='replace')
642
643 if (err /= 0) then
644 call s_mpi_abort('Unable to create Binary database '// &
645 'master file '//trim(file_loc)// &
646 '. Exiting.')
647 end if
648
649 if (output_partial_domain) then
650 write (dbroot) x_output_idx%end - x_output_idx%beg, 0, 0, dbvars
651 else
652 write (dbroot) m_root, 0, 0, dbvars
653 end if
654
655 end if
656
657 end if
658
659 end subroutine s_open_formatted_database_file
660
661 !> @brief Open the interface data file for appending extracted interface coordinates.
662 impure subroutine s_open_intf_data_file()
663
664 character(LEN=path_len + 3*name_len) :: file_path !<
665 !! Relative path to a file in the case directory
666
667 write (file_path, '(A)') '/intf_data.dat'
668 file_path = trim(case_dir)//trim(file_path)
669
670 ! Opening the simulation data file
671 open (211, file=trim(file_path), &
672 form='formatted', &
673 position='append', &
674 status='unknown')
675
676 end subroutine s_open_intf_data_file
677
678 !> @brief Open the energy data file for appending volume-integrated energy budget quantities.
679 impure subroutine s_open_energy_data_file()
680
681 character(LEN=path_len + 3*name_len) :: file_path !<
682 !! Relative path to a file in the case directory
683
684 write (file_path, '(A)') '/eng_data.dat'
685 file_path = trim(case_dir)//trim(file_path)
686
687 ! Opening the simulation data file
688 open (251, file=trim(file_path), &
689 form='formatted', &
690 position='append', &
691 status='unknown')
692
693 end subroutine s_open_energy_data_file
694
695 !> @brief Write the computational grid (cell-boundary coordinates) to the formatted database slave and master files.
697 ! Description: The general objective of this subroutine is to write the
698 ! necessary grid data to the formatted database file, for
699 ! the current time-step, t_step. The local processor will
700 ! write the grid data of the domain segment that it is in
701 ! charge of to the formatted database slave file. The root
702 ! process will additionally take care of linking that grid
703 ! data in the formatted database master file. In the Silo-
704 ! HDF5 database format, the spatial extents of each local
705 ! process grid are also written to the master file. In the
706 ! Binary format, note that no master file is maintained in
707 ! multidimensions. Finally, in 1D, no grid data is written
708 ! within this subroutine for the Silo-HDF5 format because
709 ! curve objects rather than quadrilateral meshes are used.
710 ! For curve objects, in contrast to the quadrilateral mesh
711 ! objects, the grid data is included side by side with the
712 ! flow variable data. Then, in this case, we take care of
713 ! writing both the grid and the flow variable data in the
714 ! subroutine s_write_variable_to_formatted_database_file.
715
716 ! Time-step that is currently being post-processed
717 integer, intent(IN) :: t_step
718
719 ! Bookkeeping variables storing the name and type of mesh that is
720 ! handled by the local processor(s). Note that due to an internal
721 ! NAG Fortran compiler problem, these two variables could not be
722 ! allocated dynamically.
723 character(LEN=4*name_len), dimension(num_procs) :: meshnames
724 integer, dimension(num_procs) :: meshtypes
725
726 ! Generic loop iterator
727 integer :: i
728
729 integer :: ierr !< Generic flag used to identify and report database errors
730
731 ! Silo-HDF5 Database Format
732
733 if (format == 1) then
734
735 ! For multidimensional data sets, the spatial extents of all of
736 ! the grid(s) handled by the local processor(s) are recorded so
737 ! that they may be written, by root processor, to the formatted
738 ! database master file.
739 if (num_procs > 1) then
741 elseif (p > 0) then
742 if (grid_geometry == 3) then
743 spatial_extents(:, 0) = (/minval(y_cb), minval(z_cb), &
744 minval(x_cb), maxval(y_cb), &
745 maxval(z_cb), maxval(x_cb)/)
746 else
747 spatial_extents(:, 0) = (/minval(x_cb), minval(y_cb), &
748 minval(z_cb), maxval(x_cb), &
749 maxval(y_cb), maxval(z_cb)/)
750 end if
751 elseif (n > 0) then
752 spatial_extents(:, 0) = (/minval(x_cb), minval(y_cb), &
753 maxval(x_cb), maxval(y_cb)/)
754 else
755 spatial_extents(:, 0) = (/minval(x_cb), maxval(x_cb)/)
756 end if
757
758 ! Next, the root processor proceeds to record all of the spatial
759 ! extents in the formatted database master file. In addition, it
760 ! also records a sub-domain connectivity map so that the entire
761 ! grid may be reassembled by looking at the master file.
762 if (proc_rank == 0) then
763
764 do i = 1, num_procs
765 write (meshnames(i), '(A,I0,A,I0,A)') '../p', i - 1, &
766 '/', t_step, '.silo:rectilinear_grid'
767 end do
768
769 meshtypes = db_quad_rect
770
771 err = dbset2dstrlen(len(meshnames(1)))
772 err = dbmkoptlist(2, optlist)
773 err = dbaddiopt(optlist, dbopt_extents_size, &
774 size(spatial_extents, 1))
775 err = dbadddopt(optlist, dbopt_extents, spatial_extents)
776 err = dbputmmesh(dbroot, 'rectilinear_grid', 16, &
777 num_procs, meshnames, &
778 len_trim(meshnames), &
779 meshtypes, optlist, ierr)
780 err = dbfreeoptlist(optlist)
781
782 end if
783
784 ! Finally, the local quadrilateral mesh, either 2D or 3D, along
785 ! with its offsets that indicate the presence and size of ghost
786 ! zone layer(s), are put in the formatted database slave file.
787
788 if (p > 0) then
789 err = dbmkoptlist(2, optlist)
790 err = dbaddiopt(optlist, dbopt_lo_offset, lo_offset)
791 err = dbaddiopt(optlist, dbopt_hi_offset, hi_offset)
792 if (grid_geometry == 3) then
793 err = dbputqm(dbfile, 'rectilinear_grid', 16, &
794 'x', 1, 'y', 1, 'z', 1, &
795 y_cb, z_cb, x_cb, dims, 3, &
796 db_double, db_collinear, &
797 optlist, ierr)
798 else
799 err = dbputqm(dbfile, 'rectilinear_grid', 16, &
800 'x', 1, 'y', 1, 'z', 1, &
801 x_cb, y_cb, z_cb, dims, 3, &
802 db_double, db_collinear, &
803 optlist, ierr)
804 end if
805 err = dbfreeoptlist(optlist)
806 elseif (n > 0) then
807 err = dbmkoptlist(2, optlist)
808 err = dbaddiopt(optlist, dbopt_lo_offset, lo_offset)
809 err = dbaddiopt(optlist, dbopt_hi_offset, hi_offset)
810 err = dbputqm(dbfile, 'rectilinear_grid', 16, &
811 'x', 1, 'y', 1, 'z', 1, &
812 x_cb, y_cb, db_f77null, dims, 2, &
813 db_double, db_collinear, &
814 optlist, ierr)
815 err = dbfreeoptlist(optlist)
816 else
817 err = dbmkoptlist(2, optlist)
818 err = dbaddiopt(optlist, dbopt_lo_offset, lo_offset)
819 err = dbaddiopt(optlist, dbopt_hi_offset, hi_offset)
820 err = dbputqm(dbfile, 'rectilinear_grid', 16, &
821 'x', 1, 'y', 1, 'z', 1, &
822 x_cb, db_f77null, db_f77null, dims, 1, &
823 db_double, db_collinear, &
824 optlist, ierr)
825 err = dbfreeoptlist(optlist)
826 end if
827 ! END: Silo-HDF5 Database Format
828
829 ! Binary Database Format
830
831 elseif (format == 2) then
832
833 ! Multidimensional local grid data is written to the formatted
834 ! database slave file. Recall that no master file to maintained
835 ! in multidimensions.
836 if (p > 0) then
837 if (precision == 1) then
838 write (dbfile) real(x_cb, sp), &
839 real(y_cb, sp), &
840 real(z_cb, sp)
841 else
842 if (output_partial_domain) then
843 write (dbfile) x_cb(x_output_idx%beg - 1:x_output_idx%end), &
844 y_cb(y_output_idx%beg - 1:y_output_idx%end), &
845 z_cb(z_output_idx%beg - 1:z_output_idx%end)
846 else
847 write (dbfile) x_cb, y_cb, z_cb
848 end if
849 end if
850
851 elseif (n > 0) then
852 if (precision == 1) then
853 write (dbfile) real(x_cb, sp), &
854 real(y_cb, sp)
855 else
856 if (output_partial_domain) then
857 write (dbfile) x_cb(x_output_idx%beg - 1:x_output_idx%end), &
858 y_cb(y_output_idx%beg - 1:y_output_idx%end)
859 else
860 write (dbfile) x_cb, y_cb
861 end if
862 end if
863
864 ! One-dimensional local grid data is written to the formatted
865 ! database slave file. In addition, the local grid data is put
866 ! together by the root process and written to the master file.
867 else
868
869 if (precision == 1) then
870 write (dbfile) real(x_cb, sp)
871 else
872 if (output_partial_domain) then
873 write (dbfile) x_cb(x_output_idx%beg - 1:x_output_idx%end)
874 else
875 write (dbfile) x_cb
876 end if
877 end if
878
879 if (num_procs > 1) then
881 else
882 x_root_cb(:) = x_cb(:)
883 end if
884
885 if (proc_rank == 0) then
886 if (precision == 1) then
887 write (dbroot) real(x_root_cb, wp)
888 else
889 if (output_partial_domain) then
890 write (dbroot) x_root_cb(x_output_idx%beg - 1:x_output_idx%end)
891 else
892 write (dbroot) x_root_cb
893 end if
894 end if
895 end if
896
897 end if
898
899 end if
900
902
903 !> @brief Write a single flow variable field to the formatted database slave and master files for a given time step.
904 impure subroutine s_write_variable_to_formatted_database_file(varname, t_step)
905 ! Description: The goal of this subroutine is to write to the formatted
906 ! database file the flow variable at the current time-step,
907 ! t_step. The local process(es) write the part of the flow
908 ! variable that they handle to the formatted database slave
909 ! file. The root process, on the other hand, will also take
910 ! care of connecting all of the flow variable data in the
911 ! formatted database master file. In the Silo-HDF5 database
912 ! format, the extents of each local process flow variable
913 ! are also written to the master file. Note that in Binary
914 ! format, no master file is maintained in multidimensions.
915 ! Finally note that in 1D, grid data is also written within
916 ! this subroutine for Silo-HDF5 database format since curve
917 ! and not the quadrilateral variable objects are used, see
918 ! description of s_write_grid_to_formatted_database_file
919 ! for more details on this topic.
920
921 ! Name of the flow variable, which will be written to the formatted
922 ! database file at the current time-step, t_step
923 character(LEN=*), intent(IN) :: varname
924
925 ! Time-step that is currently being post-processed
926 integer, intent(IN) :: t_step
927
928 ! Bookkeeping variables storing the name and type of flow variable
929 ! that is about to be handled by the local processor(s). Note that
930 ! due to an internal NAG Fortran compiler problem, these variables
931 ! could not be allocated dynamically.
932 character(LEN=4*name_len), dimension(num_procs) :: varnames
933 integer, dimension(num_procs) :: vartypes
934
935 ! Generic loop iterator
936 integer :: i, j, k
937
938 integer :: ierr !< Generic flag used to identify and report database errors
939
940 ! Silo-HDF5 Database Format
941
942 if (format == 1) then
943
944 ! Determining the extents of the flow variable on each local
945 ! process and gathering all this information on root process
946 if (num_procs > 1) then
948 else
949 data_extents(:, 0) = (/minval(q_sf), maxval(q_sf)/)
950 end if
951
952 ! Next, the root process proceeds to write the gathered flow
953 ! variable data extents to formatted database master file.
954 if (proc_rank == 0) then
955
956 do i = 1, num_procs
957 write (varnames(i), '(A,I0,A,I0,A)') '../p', i - 1, &
958 '/', t_step, '.silo:'//trim(varname)
959 end do
960
961 vartypes = db_quadvar
962
963 err = dbset2dstrlen(len(varnames(1)))
964 err = dbmkoptlist(2, optlist)
965 err = dbaddiopt(optlist, dbopt_extents_size, 2)
966 err = dbadddopt(optlist, dbopt_extents, data_extents)
967 err = dbputmvar(dbroot, trim(varname), &
968 len_trim(varname), num_procs, &
969 varnames, len_trim(varnames), &
970 vartypes, optlist, ierr)
971 err = dbfreeoptlist(optlist)
972
973 end if
974
975 ! Finally, each of the local processor(s) proceeds to write
976 ! the flow variable data that it is responsible for to the
977 ! formatted database slave file.
978 if (wp == dp) then
979 if (precision == 1) then
980 do i = -offset_x%beg, m + offset_x%end
981 do j = -offset_y%beg, n + offset_y%end
982 do k = -offset_z%beg, p + offset_z%end
983 q_sf_s(i, j, k) = real(q_sf(i, j, k), sp)
984 end do
985 end do
986 end do
987 if (grid_geometry == 3) then
988 do i = -offset_x%beg, m + offset_x%end
989 do j = -offset_y%beg, n + offset_y%end
990 do k = -offset_z%beg, p + offset_z%end
991 cyl_q_sf_s(j, k, i) = q_sf_s(i, j, k)
992 end do
993 end do
994 end do
995 end if
996 else
997 if (grid_geometry == 3) then
998 do i = -offset_x%beg, m + offset_x%end
999 do j = -offset_y%beg, n + offset_y%end
1000 do k = -offset_z%beg, p + offset_z%end
1001 cyl_q_sf(j, k, i) = q_sf(i, j, k)
1002 end do
1003 end do
1004 end do
1005 end if
1006 end if
1007 elseif (wp == sp) then
1008 do i = -offset_x%beg, m + offset_x%end
1009 do j = -offset_y%beg, n + offset_y%end
1010 do k = -offset_z%beg, p + offset_z%end
1011 q_sf_s(i, j, k) = q_sf(i, j, k)
1012 end do
1013 end do
1014 end do
1015 if (grid_geometry == 3) then
1016 do i = -offset_x%beg, m + offset_x%end
1017 do j = -offset_y%beg, n + offset_y%end
1018 do k = -offset_z%beg, p + offset_z%end
1019 cyl_q_sf_s(j, k, i) = q_sf_s(i, j, k)
1020 end do
1021 end do
1022 end do
1023 end if
1024 end if
1025
1026# 972 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1027 if (precision == 1) then
1028 if (p > 0) then
1029 if (grid_geometry == 3) then
1030 err = dbputqv1(dbfile, trim(varname), &
1031 len_trim(varname), &
1032 'rectilinear_grid', 16, &
1033 cyl_q_sf_s, dims - 1, 3, db_f77null, &
1034 0, db_float, db_zonecent, &
1035 db_f77null, ierr)
1036 else
1037 err = dbputqv1(dbfile, trim(varname), &
1038 len_trim(varname), &
1039 'rectilinear_grid', 16, &
1040 q_sf_s, dims - 1, 3, db_f77null, &
1041 0, db_float, db_zonecent, &
1042 db_f77null, ierr)
1043 end if
1044 elseif (n > 0) then
1045 err = dbputqv1(dbfile, trim(varname), &
1046 len_trim(varname), &
1047 'rectilinear_grid', 16, &
1048 q_sf_s, dims - 1, 2, db_f77null, &
1049 0, db_float, db_zonecent, &
1050 db_f77null, ierr)
1051 else
1052 err = dbputqv1(dbfile, trim(varname), &
1053 len_trim(varname), &
1054 'rectilinear_grid', 16, &
1055 q_sf_s, dims - 1, 1, db_f77null, &
1056 0, db_float, db_zonecent, &
1057 db_f77null, ierr)
1058
1059 end if
1060 end if
1061# 972 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1062 if (precision == 2) then
1063 if (p > 0) then
1064 if (grid_geometry == 3) then
1065 err = dbputqv1(dbfile, trim(varname), &
1066 len_trim(varname), &
1067 'rectilinear_grid', 16, &
1068 cyl_q_sf, dims - 1, 3, db_f77null, &
1069 0, db_double, db_zonecent, &
1070 db_f77null, ierr)
1071 else
1072 err = dbputqv1(dbfile, trim(varname), &
1073 len_trim(varname), &
1074 'rectilinear_grid', 16, &
1075 q_sf, dims - 1, 3, db_f77null, &
1076 0, db_double, db_zonecent, &
1077 db_f77null, ierr)
1078 end if
1079 elseif (n > 0) then
1080 err = dbputqv1(dbfile, trim(varname), &
1081 len_trim(varname), &
1082 'rectilinear_grid', 16, &
1083 q_sf, dims - 1, 2, db_f77null, &
1084 0, db_double, db_zonecent, &
1085 db_f77null, ierr)
1086 else
1087 err = dbputqv1(dbfile, trim(varname), &
1088 len_trim(varname), &
1089 'rectilinear_grid', 16, &
1090 q_sf, dims - 1, 1, db_f77null, &
1091 0, db_double, db_zonecent, &
1092 db_f77null, ierr)
1093
1094 end if
1095 end if
1096# 1007 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1097
1098 ! END: Silo-HDF5 Database Format
1099
1100 ! Binary Database Format
1101
1102 else
1103
1104 ! Writing the name of the flow variable and its data, associated
1105 ! with the local processor, to the formatted database slave file
1106 if (precision == 1) then
1107 write (dbfile) varname, real(q_sf, wp)
1108 else
1109 write (dbfile) varname, q_sf
1110 end if
1111
1112 ! In 1D, the root process also takes care of gathering the flow
1113 ! variable data from all of the local processor(s) and writes it
1114 ! to the formatted database master file.
1115 if (n == 0) then
1116
1117 if (num_procs > 1) then
1119 else
1120 q_root_sf(:, :, :) = q_sf(:, :, :)
1121 end if
1122
1123 if (proc_rank == 0) then
1124 if (precision == 1) then
1125 write (dbroot) varname, real(q_root_sf, wp)
1126 else
1127 write (dbroot) varname, q_root_sf
1128 end if
1129 end if
1130
1131 end if
1132
1133 end if
1134
1136
1137 !> Subroutine that writes the post processed results in the folder 'lag_bubbles_data'
1138 !! @param t_step Current time step
1139 impure subroutine s_write_lag_bubbles_results_to_text(t_step)
1140
1141 integer, intent(in) :: t_step
1142
1143 character(len=len_trim(case_dir) + 3*name_len) :: file_loc
1144
1145 integer :: id
1146
1147#ifdef MFC_MPI
1148 real(wp), dimension(20) :: inputvals
1149 real(wp) :: time_real
1150 integer, dimension(MPI_STATUS_SIZE) :: status
1151 integer(KIND=MPI_OFFSET_KIND) :: disp
1152 integer :: view
1153
1154 logical :: lg_bub_file, file_exist
1155
1156 integer, dimension(2) :: gsizes, lsizes, start_idx_part
1157 integer :: ifile
1158 integer :: ierr !< Generic flag used to identify and report MPI errors
1159 real(wp) :: file_time, file_dt
1160 integer :: file_num_procs, file_tot_part, tot_part
1161 integer :: i
1162
1163 integer, dimension(:), allocatable :: proc_bubble_counts
1164 real(wp), dimension(1:1, 1:lag_io_vars) :: lag_io_null
1165 lag_io_null = 0._wp
1166
1167 ! Construct file path
1168 write (file_loc, '(A,I0,A)') 'lag_bubbles_', t_step, '.dat'
1169 file_loc = trim(case_dir)//'/restart_data'//trim(mpiiofs)//trim(file_loc)
1170
1171 ! Check if file exists
1172 inquire (file=trim(file_loc), exist=file_exist)
1173 if (.not. file_exist) then
1174 call s_mpi_abort('Restart file '//trim(file_loc)//' does not exist!')
1175 end if
1176
1177 if (.not. parallel_io) return
1178
1179 if (proc_rank == 0) then
1180 call mpi_file_open(mpi_comm_self, file_loc, mpi_mode_rdonly, &
1181 mpi_info_int, ifile, ierr)
1182
1183 call mpi_file_read(ifile, file_tot_part, 1, mpi_integer, status, ierr)
1184 call mpi_file_read(ifile, file_time, 1, mpi_p, status, ierr)
1185 call mpi_file_read(ifile, file_dt, 1, mpi_p, status, ierr)
1186 call mpi_file_read(ifile, file_num_procs, 1, mpi_integer, status, ierr)
1187
1188 call mpi_file_close(ifile, ierr)
1189 end if
1190
1191 call mpi_bcast(file_tot_part, 1, mpi_integer, 0, mpi_comm_world, ierr)
1192 call mpi_bcast(file_time, 1, mpi_p, 0, mpi_comm_world, ierr)
1193 call mpi_bcast(file_dt, 1, mpi_p, 0, mpi_comm_world, ierr)
1194 call mpi_bcast(file_num_procs, 1, mpi_integer, 0, mpi_comm_world, ierr)
1195
1196 allocate (proc_bubble_counts(file_num_procs))
1197
1198 if (proc_rank == 0) then
1199 call mpi_file_open(mpi_comm_self, file_loc, mpi_mode_rdonly, &
1200 mpi_info_int, ifile, ierr)
1201
1202 ! Skip to processor counts position
1203 disp = int(sizeof(file_tot_part) + 2*sizeof(file_time) + sizeof(file_num_procs), &
1204 mpi_offset_kind)
1205 call mpi_file_seek(ifile, disp, mpi_seek_set, ierr)
1206 call mpi_file_read(ifile, proc_bubble_counts, file_num_procs, mpi_integer, status, ierr)
1207
1208 call mpi_file_close(ifile, ierr)
1209 end if
1210
1211 call mpi_bcast(proc_bubble_counts, file_num_procs, mpi_integer, 0, mpi_comm_world, ierr)
1212
1213 gsizes(1) = file_tot_part
1214 gsizes(2) = lag_io_vars
1215 lsizes(1) = file_tot_part
1216 lsizes(2) = lag_io_vars
1217 start_idx_part(1) = 0
1218 start_idx_part(2) = 0
1219
1220 call mpi_type_create_subarray(2, gsizes, lsizes, start_idx_part, &
1221 mpi_order_fortran, mpi_p, view, ierr)
1222 call mpi_type_commit(view, ierr)
1223
1224 call mpi_file_open(mpi_comm_world, file_loc, mpi_mode_rdonly, &
1225 mpi_info_int, ifile, ierr)
1226
1227 disp = int(sizeof(file_tot_part) + 2*sizeof(file_time) + sizeof(file_num_procs) + &
1228 file_num_procs*sizeof(proc_bubble_counts(1)), mpi_offset_kind)
1229 call mpi_file_set_view(ifile, disp, mpi_p, view, &
1230 'native', mpi_info_null, ierr)
1231
1232 allocate (mpi_io_data_lg_bubbles(file_tot_part, 1:lag_io_vars))
1233
1234 call mpi_file_read_all(ifile, mpi_io_data_lg_bubbles, lag_io_vars*file_tot_part, &
1235 mpi_p, status, ierr)
1236
1237 write (file_loc, '(A,I0,A)') 'lag_bubbles_post_process_', t_step, '.dat'
1238 file_loc = trim(case_dir)//'/lag_bubbles_post_process/'//trim(file_loc)
1239
1240 if (proc_rank == 0) then
1241 open (unit=29, file=file_loc, form='formatted', position='rewind')
1242
1243 if (lag_header) then
1244 write (29, '(A)', advance='no')
1245 if (lag_id_wrt) write (29, '(A8)', advance='no') 'id, '
1246 if (lag_pos_wrt) write (29, '(3(A17))', advance='no') 'px, ', 'py, ', 'pz, '
1247 if (lag_pos_prev_wrt) write (29, '(3(A17))', advance='no') 'pvx, ', 'pvy, ', 'pvz, '
1248 if (lag_vel_wrt) write (29, '(3(A17))', advance='no') 'vx, ', 'vy, ', 'vz, '
1249 if (lag_rad_wrt) write (29, '(A17)', advance='no') 'radius, '
1250 if (lag_rvel_wrt) write (29, '(A17)', advance='no') 'rvel, '
1251 if (lag_r0_wrt) write (29, '(A17)', advance='no') 'r0, '
1252 if (lag_rmax_wrt) write (29, '(A17)', advance='no') 'rmax, '
1253 if (lag_rmin_wrt) write (29, '(A17)', advance='no') 'rmin, '
1254 if (lag_dphidt_wrt) write (29, '(A17)', advance='no') 'dphidt, '
1255 if (lag_pres_wrt) write (29, '(A17)', advance='no') 'pressure, '
1256 if (lag_mv_wrt) write (29, '(A17)', advance='no') 'mv, '
1257 if (lag_mg_wrt) write (29, '(A17)', advance='no') 'mg, '
1258 if (lag_betat_wrt) write (29, '(A17)', advance='no') 'betaT, '
1259 if (lag_betac_wrt) write (29, '(A17)', advance='no') 'betaC, '
1260 write (29, '(A15)') 'time'
1261 end if
1262
1263 do i = 1, file_tot_part
1264 id = int(mpi_io_data_lg_bubbles(i, 1))
1265 inputvals(1:20) = mpi_io_data_lg_bubbles(i, 2:21)
1266 if (id > 0) then
1267 write (29, '(100(A))', advance='no') ''
1268 if (lag_id_wrt) write (29, '(I6, A)', advance='no') id, ', '
1269 if (lag_pos_wrt) write (29, '(3(E15.7, A))', advance='no') inputvals(1), ', ', inputvals(2), ', ', inputvals(3), ', '
1270 if (lag_pos_prev_wrt) write (29, '(3(E15.7, A))', advance='no') inputvals(4), ', ', inputvals(5), ', ', inputvals(6), ', '
1271 if (lag_vel_wrt) write (29, '(3(E15.7, A))', advance='no') inputvals(7), ', ', inputvals(8), ', ', inputvals(9), ', '
1272 if (lag_rad_wrt) write (29, '(E15.7, A)', advance='no') inputvals(10), ', '
1273 if (lag_rvel_wrt) write (29, '(E15.7, A)', advance='no') inputvals(11), ', '
1274 if (lag_r0_wrt) write (29, '(E15.7, A)', advance='no') inputvals(12), ', '
1275 if (lag_rmax_wrt) write (29, '(E15.7, A)', advance='no') inputvals(13), ', '
1276 if (lag_rmin_wrt) write (29, '(E15.7, A)', advance='no') inputvals(14), ', '
1277 if (lag_dphidt_wrt) write (29, '(E15.7, A)', advance='no') inputvals(15), ', '
1278 if (lag_pres_wrt) write (29, '(E15.7, A)', advance='no') inputvals(16), ', '
1279 if (lag_mv_wrt) write (29, '(E15.7, A)', advance='no') inputvals(17), ', '
1280 if (lag_mg_wrt) write (29, '(E15.7, A)', advance='no') inputvals(18), ', '
1281 if (lag_betat_wrt) write (29, '(E15.7, A)', advance='no') inputvals(19), ', '
1282 if (lag_betac_wrt) write (29, '(E15.7, A)', advance='no') inputvals(20), ', '
1283 write (29, '(E15.7)') time_real
1284 end if
1285 end do
1286 close (29)
1287 end if
1288
1289 deallocate (mpi_io_data_lg_bubbles)
1290
1291 call s_mpi_barrier()
1292
1293 call mpi_file_close(ifile, ierr)
1294#endif
1295
1297
1298 !> @brief Read Lagrangian bubble restart data and write bubble positions and scalar fields to the Silo database.
1300
1301 integer, intent(in) :: t_step
1302
1303 character(len=len_trim(case_dir) + 3*name_len) :: file_loc
1304
1305 integer :: id
1306
1307#ifdef MFC_MPI
1308 real(wp), dimension(20) :: inputvals
1309 real(wp) :: time_real
1310 integer, dimension(MPI_STATUS_SIZE) :: status
1311 integer(KIND=MPI_OFFSET_KIND) :: disp
1312 integer :: view
1313
1314 logical :: lg_bub_file, file_exist
1315
1316 integer, dimension(2) :: gsizes, lsizes, start_idx_part
1317 integer :: ifile, ierr, tot_data, valid_data, nbub
1318 real(wp) :: file_time, file_dt
1319 integer :: file_num_procs, file_tot_part
1320 integer, dimension(:), allocatable :: proc_bubble_counts
1321 real(wp), dimension(1:1, 1:lag_io_vars) :: dummy
1322 character(LEN=4*name_len), dimension(num_procs) :: meshnames
1323 integer, dimension(num_procs) :: meshtypes
1324 real(wp) :: dummy_data
1325
1326 integer :: i, j
1327
1328 real(wp), dimension(:), allocatable :: bub_id
1329 real(wp), dimension(:), allocatable :: px, py, pz, ppx, ppy, ppz, vx, vy, vz
1330 real(wp), dimension(:), allocatable :: radius, rvel, rnot, rmax, rmin, dphidt
1331 real(wp), dimension(:), allocatable :: pressure, mv, mg, betat, betac
1332
1333 dummy = 0._wp
1334 dummy_data = 0._wp
1335
1336 ! Construct file path
1337 write (file_loc, '(A,I0,A)') 'lag_bubbles_', t_step, '.dat'
1338 file_loc = trim(case_dir)//'/restart_data'//trim(mpiiofs)//trim(file_loc)
1339
1340 ! Check if file exists
1341 inquire (file=trim(file_loc), exist=file_exist)
1342 if (.not. file_exist) then
1343 call s_mpi_abort('Restart file '//trim(file_loc)//' does not exist!')
1344 end if
1345
1346 if (.not. parallel_io) return
1347
1348 if (proc_rank == 0) then
1349 call mpi_file_open(mpi_comm_self, file_loc, mpi_mode_rdonly, &
1350 mpi_info_int, ifile, ierr)
1351
1352 call mpi_file_read(ifile, file_tot_part, 1, mpi_integer, status, ierr)
1353 call mpi_file_read(ifile, file_time, 1, mpi_p, status, ierr)
1354 call mpi_file_read(ifile, file_dt, 1, mpi_p, status, ierr)
1355 call mpi_file_read(ifile, file_num_procs, 1, mpi_integer, status, ierr)
1356
1357 call mpi_file_close(ifile, ierr)
1358 end if
1359
1360 call mpi_bcast(file_tot_part, 1, mpi_integer, 0, mpi_comm_world, ierr)
1361 call mpi_bcast(file_time, 1, mpi_p, 0, mpi_comm_world, ierr)
1362 call mpi_bcast(file_dt, 1, mpi_p, 0, mpi_comm_world, ierr)
1363 call mpi_bcast(file_num_procs, 1, mpi_integer, 0, mpi_comm_world, ierr)
1364
1365 allocate (proc_bubble_counts(file_num_procs))
1366
1367 if (proc_rank == 0) then
1368 call mpi_file_open(mpi_comm_self, file_loc, mpi_mode_rdonly, &
1369 mpi_info_int, ifile, ierr)
1370
1371 ! Skip to processor counts position
1372 disp = int(sizeof(file_tot_part) + 2*sizeof(file_time) + sizeof(file_num_procs), &
1373 mpi_offset_kind)
1374 call mpi_file_seek(ifile, disp, mpi_seek_set, ierr)
1375 call mpi_file_read(ifile, proc_bubble_counts, file_num_procs, mpi_integer, status, ierr)
1376
1377 call mpi_file_close(ifile, ierr)
1378 end if
1379
1380 call mpi_bcast(proc_bubble_counts, file_num_procs, mpi_integer, 0, mpi_comm_world, ierr)
1381
1382 ! Set time variables from file
1383
1384 nbub = proc_bubble_counts(proc_rank + 1)
1385
1386 start_idx_part(1) = 0
1387 do i = 1, proc_rank
1388 start_idx_part(1) = start_idx_part(1) + proc_bubble_counts(i)
1389 end do
1390
1391 start_idx_part(2) = 0
1392 lsizes(1) = nbub
1393 lsizes(2) = lag_io_vars
1394
1395 gsizes(1) = file_tot_part
1396 gsizes(2) = lag_io_vars
1397
1398 if (nbub > 0) then
1399
1400# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1401 allocate (bub_id(nbub))
1402# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1403 allocate (px(nbub))
1404# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1405 allocate (py(nbub))
1406# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1407 allocate (pz(nbub))
1408# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1409 allocate (ppx(nbub))
1410# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1411 allocate (ppy(nbub))
1412# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1413 allocate (ppz(nbub))
1414# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1415 allocate (vx(nbub))
1416# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1417 allocate (vy(nbub))
1418# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1419 allocate (vz(nbub))
1420# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1421 allocate (radius(nbub))
1422# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1423 allocate (rvel(nbub))
1424# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1425 allocate (rnot(nbub))
1426# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1427 allocate (rmax(nbub))
1428# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1429 allocate (rmin(nbub))
1430# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1431 allocate (dphidt(nbub))
1432# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1433 allocate (pressure(nbub))
1434# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1435 allocate (mv(nbub))
1436# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1437 allocate (mg(nbub))
1438# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1439 allocate (betat(nbub))
1440# 1313 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1441 allocate (betac(nbub))
1442# 1315 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1443 allocate (mpi_io_data_lg_bubbles(nbub, 1:lag_io_vars))
1444
1445 call mpi_type_create_subarray(2, gsizes, lsizes, start_idx_part, &
1446 mpi_order_fortran, mpi_p, view, ierr)
1447 call mpi_type_commit(view, ierr)
1448
1449 call mpi_file_open(mpi_comm_world, file_loc, mpi_mode_rdonly, &
1450 mpi_info_int, ifile, ierr)
1451
1452 ! Skip extended header
1453 disp = int(sizeof(file_tot_part) + 2*sizeof(file_time) + sizeof(file_num_procs) + &
1454 file_num_procs*sizeof(proc_bubble_counts(1)), mpi_offset_kind)
1455 call mpi_file_set_view(ifile, disp, mpi_p, view, 'native', mpi_info_int, ierr)
1456
1457 call mpi_file_read_all(ifile, mpi_io_data_lg_bubbles, &
1458 lag_io_vars*nbub, mpi_p, status, ierr)
1459
1460 call mpi_file_close(ifile, ierr)
1461 call mpi_type_free(view, ierr)
1462
1463 ! Extract data from MPI_IO_DATA_lg_bubbles array
1464 ! Adjust these indices based on your actual data layout
1465# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1466 bub_id(:) = mpi_io_data_lg_bubbles(:, 1)
1467# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1468 px(:) = mpi_io_data_lg_bubbles(:, 2)
1469# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1470 py(:) = mpi_io_data_lg_bubbles(:, 3)
1471# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1472 pz(:) = mpi_io_data_lg_bubbles(:, 4)
1473# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1474 ppx(:) = mpi_io_data_lg_bubbles(:, 5)
1475# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1476 ppy(:) = mpi_io_data_lg_bubbles(:, 6)
1477# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1478 ppz(:) = mpi_io_data_lg_bubbles(:, 7)
1479# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1480 vx(:) = mpi_io_data_lg_bubbles(:, 8)
1481# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1482 vy(:) = mpi_io_data_lg_bubbles(:, 9)
1483# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1484 vz(:) = mpi_io_data_lg_bubbles(:, 10)
1485# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1486 radius(:) = mpi_io_data_lg_bubbles(:, 11)
1487# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1488 rvel(:) = mpi_io_data_lg_bubbles(:, 12)
1489# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1490 rnot(:) = mpi_io_data_lg_bubbles(:, 13)
1491# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1492 rmax(:) = mpi_io_data_lg_bubbles(:, 14)
1493# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1494 rmin(:) = mpi_io_data_lg_bubbles(:, 15)
1495# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1496 dphidt(:) = mpi_io_data_lg_bubbles(:, 16)
1497# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1498 pressure(:) = mpi_io_data_lg_bubbles(:, 17)
1499# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1500 mv(:) = mpi_io_data_lg_bubbles(:, 18)
1501# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1502 mg(:) = mpi_io_data_lg_bubbles(:, 19)
1503# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1504 betat(:) = mpi_io_data_lg_bubbles(:, 20)
1505# 1341 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1506 betac(:) = mpi_io_data_lg_bubbles(:, 21)
1507# 1343 "/home/runner/work/MFC/MFC/src/post_process/m_data_output.fpp"
1508
1509 ! Next, the root processor proceeds to record all of the spatial
1510 ! extents in the formatted database master file. In addition, it
1511 ! also records a sub-domain connectivity map so that the entire
1512 ! grid may be reassembled by looking at the master file.
1513 if (proc_rank == 0) then
1514
1515 do i = 1, num_procs
1516 write (meshnames(i), '(A,I0,A,I0,A)') '../p', i - 1, &
1517 '/', t_step, '.silo:lag_bubbles'
1518 meshtypes(i) = db_pointmesh
1519 end do
1520 err = dbset2dstrlen(len(meshnames(1)))
1521 err = dbputmmesh(dbroot, 'lag_bubbles', 16, &
1522 num_procs, meshnames, &
1523 len_trim(meshnames), &
1524 meshtypes, db_f77null, ierr)
1525 end if
1526
1527 err = dbputpm(dbfile, 'lag_bubbles', 11, 3, &
1528 px, py, pz, nbub, &
1529 db_double, db_f77null, ierr)
1530
1531 if (lag_id_wrt) call s_write_lag_variable_to_formatted_database_file('part_id', t_step, bub_id, nbub)
1532 if (lag_vel_wrt) then
1533 call s_write_lag_variable_to_formatted_database_file('part_vel1', t_step, vx, nbub)
1534 call s_write_lag_variable_to_formatted_database_file('part_vel2', t_step, vy, nbub)
1535 if (p > 0) call s_write_lag_variable_to_formatted_database_file('part_vel3', t_step, vz, nbub)
1536 end if
1537 if (lag_rad_wrt) call s_write_lag_variable_to_formatted_database_file('part_radius', t_step, radius, nbub)
1538 if (lag_rvel_wrt) call s_write_lag_variable_to_formatted_database_file('part_rdot', t_step, rvel, nbub)
1539 if (lag_r0_wrt) call s_write_lag_variable_to_formatted_database_file('part_r0', t_step, rnot, nbub)
1540 if (lag_rmax_wrt) call s_write_lag_variable_to_formatted_database_file('part_rmax', t_step, rmax, nbub)
1541 if (lag_rmin_wrt) call s_write_lag_variable_to_formatted_database_file('part_rmin', t_step, rmin, nbub)
1542 if (lag_dphidt_wrt) call s_write_lag_variable_to_formatted_database_file('part_dphidt', t_step, dphidt, nbub)
1543 if (lag_pres_wrt) call s_write_lag_variable_to_formatted_database_file('part_pressure', t_step, pressure, nbub)
1544 if (lag_mv_wrt) call s_write_lag_variable_to_formatted_database_file('part_mv', t_step, mv, nbub)
1545 if (lag_mg_wrt) call s_write_lag_variable_to_formatted_database_file('part_mg', t_step, mg, nbub)
1546 if (lag_betat_wrt) call s_write_lag_variable_to_formatted_database_file('part_betaT', t_step, betat, nbub)
1547 if (lag_betac_wrt) call s_write_lag_variable_to_formatted_database_file('part_betaC', t_step, betac, nbub)
1548
1549 deallocate (bub_id, px, py, pz, ppx, ppy, ppz, vx, vy, vz, radius, &
1550 rvel, rnot, rmax, rmin, dphidt, pressure, mv, mg, &
1551 betat, betac)
1552 deallocate (mpi_io_data_lg_bubbles)
1553 else
1554 call mpi_type_contiguous(0, mpi_p, view, ierr)
1555 call mpi_type_commit(view, ierr)
1556
1557 call mpi_file_open(mpi_comm_world, file_loc, mpi_mode_rdonly, &
1558 mpi_info_int, ifile, ierr)
1559
1560 ! Skip extended header
1561 disp = int(sizeof(file_tot_part) + 2*sizeof(file_time) + sizeof(file_num_procs) + &
1562 file_num_procs*sizeof(proc_bubble_counts(1)), mpi_offset_kind)
1563 call mpi_file_set_view(ifile, disp, mpi_p, view, 'native', mpi_info_int, ierr)
1564
1565 call mpi_file_read_all(ifile, dummy, 0, mpi_p, status, ierr)
1566
1567 call mpi_file_close(ifile, ierr)
1568 call mpi_type_free(view, ierr)
1569
1570 if (proc_rank == 0) then
1571
1572 do i = 1, num_procs
1573 write (meshnames(i), '(A,I0,A,I0,A)') '../p', i - 1, &
1574 '/', t_step, '.silo:lag_bubbles'
1575 meshtypes(i) = db_pointmesh
1576 end do
1577 err = dbset2dstrlen(len(meshnames(1)))
1578 err = dbputmmesh(dbroot, 'lag_bubbles', 16, &
1579 num_procs, meshnames, &
1580 len_trim(meshnames), &
1581 meshtypes, db_f77null, ierr)
1582 end if
1583
1584 err = dbsetemptyok(1)
1585 err = dbputpm(dbfile, 'lag_bubbles', 11, 3, &
1586 dummy_data, dummy_data, dummy_data, 0, &
1587 db_double, db_f77null, ierr)
1588
1590 if (lag_vel_wrt) then
1591 call s_write_lag_variable_to_formatted_database_file('part_vel1', t_step)
1592 call s_write_lag_variable_to_formatted_database_file('part_vel2', t_step)
1593 if (p > 0) call s_write_lag_variable_to_formatted_database_file('part_vel3', t_step)
1594 end if
1595 if (lag_rad_wrt) call s_write_lag_variable_to_formatted_database_file('part_radius', t_step)
1601 if (lag_pres_wrt) call s_write_lag_variable_to_formatted_database_file('part_pressure', t_step)
1606 end if
1607
1608#endif
1609
1611
1612 !> @brief Write a single Lagrangian bubble point-variable to the Silo database slave and master files.
1613 subroutine s_write_lag_variable_to_formatted_database_file(varname, t_step, data, nBubs)
1614
1615 character(len=*), intent(in) :: varname
1616 integer, intent(in) :: t_step
1617 real(wp), dimension(1:), intent(in), optional :: data
1618 integer, intent(in), optional :: nBubs
1619
1620 character(len=64), dimension(num_procs) :: var_names
1621 integer, dimension(num_procs) :: var_types
1622 real(wp) :: dummy_data
1623
1624 integer :: ierr !< Generic flag used to identify and report database errors
1625 integer :: i
1626
1627 dummy_data = 0._wp
1628
1629 if (present(nbubs) .and. present(data)) then
1630 if (proc_rank == 0) then
1631 do i = 1, num_procs
1632 write (var_names(i), '(A,I0,A,I0,A)') '../p', i - 1, &
1633 '/', t_step, '.silo:'//trim(varname)
1634 var_types(i) = db_pointvar
1635 end do
1636 err = dbset2dstrlen(len(var_names(1)))
1637 err = dbputmvar(dbroot, trim(varname), len_trim(varname), &
1638 num_procs, var_names, &
1639 len_trim(var_names), &
1640 var_types, db_f77null, ierr)
1641 end if
1642
1643 err = dbputpv1(dbfile, trim(varname), len_trim(varname), &
1644 'lag_bubbles', 11, data, nbubs, db_double, db_f77null, ierr)
1645 else
1646 if (proc_rank == 0) then
1647 do i = 1, num_procs
1648 write (var_names(i), '(A,I0,A,I0,A)') '../p', i - 1, &
1649 '/', t_step, '.silo:'//trim(varname)
1650 var_types(i) = db_pointvar
1651 end do
1652 err = dbset2dstrlen(len(var_names(1)))
1653 err = dbsetemptyok(1)
1654 err = dbputmvar(dbroot, trim(varname), len_trim(varname), &
1655 num_procs, var_names, &
1656 len_trim(var_names), &
1657 var_types, db_f77null, ierr)
1658 end if
1659
1660 err = dbsetemptyok(1)
1661 err = dbputpv1(dbfile, trim(varname), len_trim(varname), &
1662 'lag_bubbles', 11, dummy_data, 0, db_double, db_f77null, ierr)
1663 end if
1664
1666
1667 !> @brief Extract the volume-fraction interface contour from primitive fields and write the coordinates to the interface data file.
1668 impure subroutine s_write_intf_data_file(q_prim_vf)
1669
1670 type(scalar_field), dimension(sys_size), intent(IN) :: q_prim_vf
1671 integer :: i, j, k, l, cent !< Generic loop iterators
1672 integer :: counter, root !< number of data points extracted to fit shape to SH perturbations
1673 real(wp), allocatable :: x_td(:), y_td(:), x_d1(:), y_d1(:), y_d(:), x_d(:)
1674 real(wp) :: axp, axm, ayp, aym, tgp, euc_d, thres, maxalph_loc, maxalph_glb
1675
1676 allocate (x_d1(m*n))
1677 allocate (y_d1(m*n))
1678 counter = 0
1679 maxalph_loc = 0._wp
1680 do k = 0, p
1681 do j = 0, n
1682 do i = 0, m
1683 if (q_prim_vf(e_idx + 2)%sf(i, j, k) > maxalph_loc) then
1684 maxalph_loc = q_prim_vf(e_idx + 2)%sf(i, j, k)
1685 end if
1686 end do
1687 end do
1688 end do
1689
1690 call s_mpi_allreduce_max(maxalph_loc, maxalph_glb)
1691 if (p > 0) then
1692 do l = 0, p
1693 if (z_cc(l) < dz(l) .and. z_cc(l) > 0) then
1694 cent = l
1695 end if
1696 end do
1697 else
1698 cent = 0
1699 end if
1700
1701 thres = 0.9_wp*maxalph_glb
1702 do k = 0, n
1703 do j = 0, m
1704 axp = q_prim_vf(e_idx + 2)%sf(j + 1, k, cent)
1705 axm = q_prim_vf(e_idx + 2)%sf(j, k, cent)
1706 ayp = q_prim_vf(e_idx + 2)%sf(j, k + 1, cent)
1707 aym = q_prim_vf(e_idx + 2)%sf(j, k, cent)
1708 if ((axp > thres .and. axm < thres) .or. (axp < thres .and. axm > thres) &
1709 .or. (ayp > thres .and. aym < thres) .or. (ayp < thres .and. aym > thres)) then
1710 if (counter == 0) then
1711 counter = counter + 1
1712 x_d1(counter) = x_cc(j)
1713 y_d1(counter) = y_cc(k)
1714 euc_d = sqrt((x_cc(j) - x_d1(i))**2 + (y_cc(k) - y_d1(i))**2)
1715 tgp = sqrt(dx(j)**2 + dy(k)**2)
1716 else
1717 euc_d = sqrt((x_cc(j) - x_d1(i))**2 + (y_cc(k) - y_d1(i))**2)
1718 tgp = sqrt(dx(j)**2 + dy(k)**2)
1719 do i = 1, counter
1720 if (euc_d < tgp) then
1721 cycle
1722 elseif (euc_d > tgp .and. i == counter) then
1723 counter = counter + 1
1724 x_d1(counter) = x_cc(j)
1725 y_d1(counter) = y_cc(k)
1726
1727 end if
1728 end do
1729 end if
1730 end if
1731 end do
1732 end do
1733
1734 allocate (x_d(counter), y_d(counter))
1735
1736 do i = 1, counter
1737 y_d(i) = y_d1(i)
1738 x_d(i) = x_d1(i)
1739 end do
1740 root = 0
1741
1742 call s_mpi_gather_data(x_d, counter, x_td, root)
1743 call s_mpi_gather_data(y_d, counter, y_td, root)
1744 if (proc_rank == 0) then
1745 do i = 1, size(x_td)
1746 if (i == size(x_td)) then
1747 write (211, '(F12.9,1X,F12.9,1X,I4)') &
1748 x_td(i), y_td(i), size(x_td)
1749 else
1750 write (211, '(F12.9,1X,F12.9,1X,F3.1)') &
1751 x_td(i), y_td(i), 0._wp
1752 end if
1753 end do
1754 end if
1755
1756 end subroutine s_write_intf_data_file
1757
1758 !> @brief Compute volume-integrated kinetic, potential, and internal energies and write the energy budget to the energy data file.
1759 impure subroutine s_write_energy_data_file(q_prim_vf, q_cons_vf)
1760 type(scalar_field), dimension(sys_size), intent(IN) :: q_prim_vf, q_cons_vf
1761 real(wp) :: elk, egk, elp, egint, vb, vl, pres_av, et
1762 real(wp) :: rho, pres, dv, tmp, gamma, pi_inf, maxma, maxma_glb, maxvel, c, ma, h, qv
1763 real(wp), dimension(num_vels) :: vel
1764 real(wp), dimension(num_fluids) :: adv
1765 integer :: i, j, k, l, s !looping indices
1766
1767 egk = 0._wp
1768 elp = 0._wp
1769 egint = 0._wp
1770 vb = 0._wp
1771 maxvel = 0._wp
1772 maxma = 0._wp
1773 vl = 0._wp
1774 elk = 0._wp
1775 et = 0._wp
1776 vb = 0._wp
1777 dv = 0._wp
1778 pres_av = 0._wp
1779 pres = 0._wp
1780 c = 0._wp
1781
1782 do k = 0, p
1783 do j = 0, n
1784 do i = 0, m
1785 pres = 0._wp
1786 dv = dx(i)*dy(j)*dz(k)
1787 rho = 0._wp
1788 gamma = 0._wp
1789 pi_inf = 0._wp
1790 qv = 0._wp
1791 pres = q_prim_vf(e_idx)%sf(i, j, k)
1792 egint = egint + q_prim_vf(e_idx + 2)%sf(i, j, k)*(gammas(2)*pres)*dv
1793 do s = 1, num_vels
1794 vel(s) = q_prim_vf(num_fluids + s)%sf(i, j, k)
1795 egk = egk + 0.5_wp*q_prim_vf(e_idx + 2)%sf(i, j, k)*q_prim_vf(2)%sf(i, j, k)*vel(s)*vel(s)*dv
1796 elk = elk + 0.5_wp*q_prim_vf(e_idx + 1)%sf(i, j, k)*q_prim_vf(1)%sf(i, j, k)*vel(s)*vel(s)*dv
1797 if (abs(vel(s)) > maxvel) then
1798 maxvel = abs(vel(s))
1799 end if
1800 end do
1801 do l = 1, adv_idx%end - e_idx
1802 adv(l) = q_prim_vf(e_idx + l)%sf(i, j, k)
1803 gamma = gamma + adv(l)*gammas(l)
1804 pi_inf = pi_inf + adv(l)*pi_infs(l)
1805 rho = rho + adv(l)*q_prim_vf(l)%sf(i, j, k)
1806 qv = qv + adv(l)*q_prim_vf(l)%sf(i, j, k)*qvs(l)
1807 end do
1808
1809 h = ((gamma + 1._wp)*pres + pi_inf + qv)/rho
1810
1811 call s_compute_speed_of_sound(pres, rho, &
1812 gamma, pi_inf, &
1813 h, adv, 0._wp, 0._wp, c, qv)
1814
1815 ma = maxvel/c
1816 if (ma > maxma .and. (adv(1) > (1.0_wp - 1.0e-10_wp))) then
1817 maxma = ma
1818 end if
1819 vl = vl + adv(1)*dv
1820 vb = vb + adv(2)*dv
1821 pres_av = pres_av + adv(1)*pres*dv
1822 et = et + q_cons_vf(e_idx)%sf(i, j, k)*dv
1823 end do
1824 end do
1825 end do
1826
1827 tmp = pres_av
1828 call s_mpi_allreduce_sum(tmp, pres_av)
1829 tmp = vl
1830 call s_mpi_allreduce_sum(tmp, vl)
1831
1832 call s_mpi_allreduce_max(maxma, maxma_glb)
1833 tmp = elk
1834 call s_mpi_allreduce_sum(tmp, elk)
1835 tmp = egint
1836 call s_mpi_allreduce_sum(tmp, egint)
1837 tmp = egk
1838 call s_mpi_allreduce_sum(tmp, egk)
1839 tmp = vb
1840 call s_mpi_allreduce_sum(tmp, vb)
1841 tmp = et
1842 call s_mpi_allreduce_sum(tmp, et)
1843
1844 elp = pres_av/vl*vb
1845 if (proc_rank == 0) then
1846 write (251, '(10X, 8F24.8)') &
1847 elp, &
1848 egint, &
1849 elk, &
1850 egk, &
1851 et, &
1852 vb, &
1853 vl, &
1854 maxma_glb
1855 end if
1856
1857 end subroutine s_write_energy_data_file
1858
1859 !> @brief Close the formatted database slave file and, for the root process, the master file.
1861 ! Description: The purpose of this subroutine is to close any formatted
1862 ! database file(s) that may be opened at the time-step that
1863 ! is currently being post-processed. The root process must
1864 ! typically close two files, one associated with the local
1865 ! sub-domain and the other with the entire domain. The non-
1866 ! root process(es) must close one file, which is associated
1867 ! with the local sub-domain. Note that for the Binary data-
1868 ! base format and multidimensional data, the root process
1869 ! only has to close the file associated with the local sub-
1870 ! domain, because one associated with the entire domain is
1871 ! not generated.
1872
1873 integer :: ierr !< Generic flag used to identify and report database errors
1874
1875 ! Silo-HDF5 database format
1876 if (format == 1) then
1877 ierr = dbclose(dbfile)
1878 if (proc_rank == 0) ierr = dbclose(dbroot)
1879
1880 ! Binary database format
1881 else
1882 close (dbfile)
1883 if (n == 0 .and. proc_rank == 0) close (dbroot)
1884
1885 end if
1886
1887 end subroutine s_close_formatted_database_file
1888
1889 !> @brief Close the interface data file.
1890 impure subroutine s_close_intf_data_file()
1891
1892 close (211)
1893
1894 end subroutine s_close_intf_data_file
1895
1896 !> @brief Close the energy data file.
1897 impure subroutine s_close_energy_data_file()
1898
1899 close (251)
1900
1901 end subroutine s_close_energy_data_file
1902
1903 !> @brief Deallocate module arrays and release all data-output resources.
1905 ! Description: Deallocation procedures for the module
1906
1907 ! Deallocating the generic storage employed for the flow variable(s)
1908 ! that were written to the formatted database file(s). Note that the
1909 ! root variable is only deallocated in the case of a 1D computation.
1910 deallocate (q_sf)
1911 if (n == 0) deallocate (q_root_sf)
1912 if (grid_geometry == 3) then
1913 deallocate (cyl_q_sf)
1914 end if
1915
1916 ! Deallocating spatial and data extents and also the variables for
1917 ! the offsets and the one bookkeeping the number of cell-boundaries
1918 ! in each active coordinate direction. Note that all these variables
1919 ! were only needed by Silo-HDF5 format for multidimensional data.
1920 if (format == 1) then
1921 deallocate (spatial_extents)
1922 deallocate (data_extents)
1923 deallocate (lo_offset)
1924 deallocate (hi_offset)
1925 deallocate (dims)
1926 end if
1927
1928 end subroutine s_finalize_data_output_module
1929
1930end module m_data_output
type(scalar_field), dimension(sys_size), intent(inout) q_cons_vf
integer, intent(in) k
integer, intent(in) j
integer, intent(in) l
Platform-specific file and directory operations: create, delete, inquire, getcwd, and basename.
impure subroutine my_inquire(fileloc, dircheck)
Inquires on the existence of a directory.
impure subroutine s_create_directory(dir_name)
Creates a directory and all its parents if it does not exist.
Writes post-processed grid and flow-variable data to Silo-HDF5 or binary database files.
impure subroutine, public s_write_grid_to_formatted_database_file(t_step)
Write the computational grid (cell-boundary coordinates) to the formatted database slave and master f...
integer, dimension(:), allocatable hi_offset
real(sp), dimension(:, :, :), allocatable cyl_q_sf_s
real(wp), dimension(:, :), allocatable data_extents
impure subroutine, public s_write_variable_to_formatted_database_file(varname, t_step)
Write a single flow variable field to the formatted database slave and master files for a given time ...
impure subroutine, public s_open_energy_data_file()
Open the energy data file for appending volume-integrated energy budget quantities.
impure subroutine, public s_open_intf_data_file()
Open the interface data file for appending extracted interface coordinates.
character(len=path_len+name_len) dbdir
impure subroutine, public s_write_energy_data_file(q_prim_vf, q_cons_vf)
Compute volume-integrated kinetic, potential, and internal energies and write the energy budget to th...
real(sp), dimension(:, :, :), allocatable, public q_sf_s
impure subroutine, public s_write_lag_bubbles_to_formatted_database_file(t_step)
Read Lagrangian bubble restart data and write bubble positions and scalar fields to the Silo database...
integer, dimension(:), allocatable lo_offset
impure subroutine, public s_write_intf_data_file(q_prim_vf)
Extract the volume-fraction interface contour from primitive fields and write the coordinates to the ...
impure subroutine, public s_initialize_data_output_module()
Allocate storage arrays, configure output directories, and count flow variables for formatted databas...
impure subroutine, public s_close_energy_data_file()
Close the energy data file.
impure subroutine, public s_close_formatted_database_file()
Close the formatted database slave file and, for the root process, the master file.
impure subroutine, public s_open_formatted_database_file(t_step)
Open (or create) the Silo-HDF5 or Binary formatted database slave and master files for a given time s...
impure subroutine, public s_close_intf_data_file()
Close the interface data file.
impure subroutine, public s_write_lag_bubbles_results_to_text(t_step)
Subroutine that writes the post processed results in the folder 'lag_bubbles_data'.
real(wp), dimension(:, :, :), allocatable cyl_q_sf
impure subroutine, public s_finalize_data_output_module()
Deallocate module arrays and release all data-output resources.
integer, private err
integer, dimension(:), allocatable dims
impure subroutine, public s_define_output_region
Compute the cell-index bounds for the user-specified partial output domain in each coordinate directi...
real(wp), dimension(:, :), allocatable spatial_extents
character(len=path_len+2 *name_len) proc_rank_dir
real(wp), dimension(:, :, :), allocatable q_root_sf
subroutine s_write_lag_variable_to_formatted_database_file(varname, t_step, data, nbubs)
Write a single Lagrangian bubble point-variable to the Silo database slave and master files.
real(wp), dimension(:, :, :), allocatable, public q_sf
real(sp), dimension(:, :, :), allocatable q_root_sf_s
character(len=path_len+2 *name_len) rootdir
Shared derived types for field data, patch geometry, bubble dynamics, and MPI I/O structures.
Computes derived flow quantities (sound speed, vorticity, Schlieren, etc.) from conservative and prim...
Global parameters for the post-process: domain geometry, equation of state, and output database setti...
logical cont_damage
Continuum damage modeling.
logical hypoelasticity
Turn hypoelasticity on.
type(int_bounds_info) offset_y
type(int_bounds_info) mom_idx
Indexes of first & last momentum eqns.
integer num_fluids
Number of different fluids present in the flow.
logical, dimension(3) flux_wrt
real(wp), dimension(:), allocatable y_cc
integer proc_rank
Rank of the local processor.
logical output_partial_domain
Specify portion of domain to output for post-processing.
real(wp), dimension(:), allocatable adv
Advection variables.
type(int_bounds_info) z_output_idx
Indices of domain to output for post-processing.
logical dummy
AMDFlang workaround: keep a dummy logical to avoid a compiler case-optimization bug when a parameter+...
real(wp), dimension(:), allocatable y_cb
character(len=name_len) mpiiofs
real(wp), dimension(:), allocatable dz
real(wp), dimension(:, :), allocatable, public mpi_io_data_lg_bubbles
logical, dimension(3) mom_wrt
real(wp), dimension(:), allocatable x_root_cb
logical, dimension(num_fluids_max) alpha_wrt
logical, dimension(num_fluids_max) alpha_rho_wrt
integer model_eqns
Multicomponent flow model.
integer precision
Floating point precision of the database file(s).
real(wp), dimension(:), allocatable z_cb
type(bounds_info) z_output
Portion of domain to output for post-processing.
integer num_dims
Number of spatial dimensions.
type(int_bounds_info) x_output_idx
real(wp), dimension(:), allocatable x_cc
integer num_vels
Number of velocity components (different from num_dims for mhd).
real(wp), dimension(:), allocatable x_cb
real(wp), dimension(:), allocatable dy
type(int_bounds_info) offset_x
logical hyper_cleaning
Hyperbolic cleaning for MHD.
real(wp), dimension(:), allocatable z_cc
logical, dimension(3) omega_wrt
integer num_procs
Number of processors.
character(len=path_len) case_dir
Case folder location.
type(int_bounds_info) y_output_idx
type(int_bounds_info) adv_idx
Indexes of first & last advection eqns.
type(int_bounds_info) offset_z
logical mhd
Magnetohydrodynamics.
logical parallel_io
Format of the data files.
integer e_idx
Index of energy equation.
logical, dimension(3) vel_wrt
logical relativity
Relativity for RMHD.
real(wp), dimension(:), allocatable dx
Cell-width distributions in the x-, y- and z-coordinate directions.
Utility routines for bubble model setup, coordinate transforms, array sampling, and special functions...
MPI gather and scatter operations for distributing post-process grid and flow-variable data.
impure subroutine s_mpi_defragment_1d_grid_variable
This subroutine collects the sub-domain cell-boundary or cell-center locations data from all of the p...
impure subroutine s_mpi_defragment_1d_flow_variable(q_sf, q_root_sf)
This subroutine gathers the sub-domain flow variable data from all of the processors and puts it back...
impure subroutine s_mpi_gather_spatial_extents(spatial_extents)
This subroutine gathers the Silo database metadata for the spatial extents in order to boost the perf...
impure subroutine s_mpi_gather_data_extents(q_sf, data_extents)
This subroutine gathers the Silo database metadata for the flow variable's extents as to boost perfor...
Conservative-to-primitive variable conversion, mixture property evaluation, and pressure computation.
real(wp), dimension(:), allocatable, public gammas
subroutine s_compute_speed_of_sound(pres, rho, gamma, pi_inf, h, adv, vel_sum, c_c, c, qv)
Computes the speed of sound from thermodynamic state variables, supporting multiple equation-of-state...
real(wp), dimension(:), allocatable, public qvs
real(wp), dimension(:), allocatable, public pi_infs
Derived type annexing a scalar field (SF).