MFC
Exascale flow solver
Loading...
Searching...
No Matches
m_grid.f90
Go to the documentation of this file.
1!>
2!! @file
3!! @brief Contains module m_grid
4
5!> @brief Generates uniform or stretched rectilinear grids with hyperbolic-tangent spacing
6module m_grid
7
8 use m_derived_types ! Definitions of the derived types
9 use m_global_parameters ! Global parameters for the code
10 use m_mpi_proxy ! Message passing interface (MPI) module proxy
12#ifdef MFC_MPI
13 use mpi ! Message passing interface (MPI) module
14#endif
15
16 implicit none
17
18 private
20
21 abstract interface
22
23 !> Abstract interface for generating a rectilinear computational grid.
24 impure subroutine s_generate_abstract_grid
25
26 end subroutine s_generate_abstract_grid
27 end interface
28
29 procedure(s_generate_abstract_grid), pointer :: s_generate_grid => null()
30
31contains
32
33 !> Generate a uniform or stretched rectilinear grid in serial from user parameters.
34 impure subroutine s_generate_serial_grid
35
36 ! Generic loop iterator
37 integer :: i, j !< generic loop operators
38 real(wp) :: length !< domain lengths
39 ! Uniform grid: dx = (x_end - x_beg) / (m + 1)
40
41 dx = (x_domain%end - x_domain%beg)/real(m + 1, wp)
42
43 do i = 0, m
44 x_cc(i) = x_domain%beg + 5.e-1_wp*dx*real(2*i + 1, wp)
45 x_cb(i - 1) = x_domain%beg + dx*real(i, wp)
46 end do
47
48 x_cb(m) = x_domain%end
49
50 ! Hyperbolic tangent grid stretching
51 if (stretch_x) then
52 length = abs(x_cb(m) - x_cb(-1))
53 x_cb = x_cb/length
54 x_a = x_a/length
55 x_b = x_b/length
56
57 do j = 1, loops_x
58 do i = -1, m
59 x_cb(i) = x_cb(i)/a_x*(a_x + log(cosh(a_x*(x_cb(i) - x_a))) + log(cosh(a_x*(x_cb(i) - x_b))) &
60 & - 2._wp*log(cosh(a_x*(x_b - x_a)/2._wp)))
61 end do
62 end do
63 x_cb = x_cb*length
64
65 x_cc(0:m) = (x_cb(0:m) + x_cb(-1:m - 1))/2._wp
66
67 dx = minval(x_cb(0:m) - x_cb(-1:m - 1))
68 print *, 'Stretched grid: min/max x grid: ', minval(x_cc(:)), maxval(x_cc(:))
69 if (num_procs > 1) call s_mpi_reduce_min(dx)
70 end if
71
72 ! Grid Generation in the y-direction
73 if (n == 0) return
74
75 ! Axisymmetric cylindrical grid (r, z): half-cell offset at r=0 axis
76 if (grid_geometry == 2 .and. f_approx_equal(y_domain%beg, 0.0_wp)) then
77 dy = (y_domain%end - y_domain%beg)/real(2*n + 1, wp)
78
79 y_cc(0) = y_domain%beg + 5.e-1_wp*dy
80 y_cb(-1) = y_domain%beg
81
82 do i = 1, n
83 y_cc(i) = y_domain%beg + 2._wp*dy*real(i, wp)
84 y_cb(i - 1) = y_domain%beg + dy*real(2*i - 1, wp)
85 end do
86 else
87 dy = (y_domain%end - y_domain%beg)/real(n + 1, wp)
88
89 do i = 0, n
90 y_cc(i) = y_domain%beg + 5.e-1_wp*dy*real(2*i + 1, wp)
91 y_cb(i - 1) = y_domain%beg + dy*real(i, wp)
92 end do
93 end if
94
95 y_cb(n) = y_domain%end
96
97 ! Hyperbolic tangent grid stretching in y-direction
98 if (stretch_y) then
99 length = abs(y_cb(n) - y_cb(-1))
100 y_cb = y_cb/length
101 y_a = y_a/length
102 y_b = y_b/length
103
104 do j = 1, loops_y
105 do i = -1, n
106 y_cb(i) = y_cb(i)/a_y*(a_y + log(cosh(a_y*(y_cb(i) - y_a))) + log(cosh(a_y*(y_cb(i) - y_b))) &
107 & - 2._wp*log(cosh(a_y*(y_b - y_a)/2._wp)))
108 end do
109 end do
110
111 y_cb = y_cb*length
112 y_cc(0:n) = (y_cb(0:n) + y_cb(-1:n - 1))/2._wp
113
114 dy = minval(y_cb(0:n) - y_cb(-1:n - 1))
115
116 if (num_procs > 1) call s_mpi_reduce_min(dy)
117 end if
118
119 ! Grid Generation in the z-direction
120 if (p == 0) return
121
122 dz = (z_domain%end - z_domain%beg)/real(p + 1, wp)
123
124 do i = 0, p
125 z_cc(i) = z_domain%beg + 5.e-1_wp*dz*real(2*i + 1, wp)
126 z_cb(i - 1) = z_domain%beg + dz*real(i, wp)
127 end do
128
129 z_cb(p) = z_domain%end
130
131 ! Hyperbolic tangent grid stretching in z-direction
132 if (stretch_z) then
133 length = abs(z_cb(p) - z_cb(-1))
134 z_cb = z_cb/length
135 z_a = z_a/length
136 z_b = z_b/length
137
138 do j = 1, loops_z
139 do i = -1, p
140 z_cb(i) = z_cb(i)/a_z*(a_z + log(cosh(a_z*(z_cb(i) - z_a))) + log(cosh(a_z*(z_cb(i) - z_b))) &
141 & - 2._wp*log(cosh(a_z*(z_b - z_a)/2._wp)))
142 end do
143 end do
144
145 z_cb = z_cb*length
146 z_cc(0:p) = (z_cb(0:p) + z_cb(-1:p - 1))/2._wp
147
148 dz = minval(z_cb(0:p) - z_cb(-1:p - 1))
149
150 if (num_procs > 1) call s_mpi_reduce_min(dz)
151 end if
152
153 end subroutine s_generate_serial_grid
154
155 !> Generate a uniform or stretched rectilinear grid in parallel from user parameters.
156 impure subroutine s_generate_parallel_grid
157
158#ifdef MFC_MPI
159 real(wp) :: length !< domain lengths
160 ! Locations of cell boundaries
161 real(wp), allocatable, dimension(:) :: x_cb_glb, y_cb_glb, z_cb_glb !< Locations of cell boundaries
162 character(LEN=path_len + name_len) :: file_loc !< Generic string used to store the address of a file
163 integer :: ifile, ierr, data_size
164 integer, dimension(MPI_STATUS_SIZE) :: status
165 integer :: i, j !< Generic loop integers
166
167 allocate (x_cb_glb(-1:m_glb))
168 allocate (y_cb_glb(-1:n_glb))
169 allocate (z_cb_glb(-1:p_glb))
170
171 ! Uniform grid: dx = (x_end - x_beg) / (m_glb + 1)
172 dx = (x_domain%end - x_domain%beg)/real(m_glb + 1, wp)
173 do i = 0, m_glb
174 x_cb_glb(i - 1) = x_domain%beg + dx*real(i, wp)
175 end do
176 x_cb_glb(m_glb) = x_domain%end
177 ! Hyperbolic tangent grid stretching in x-direction (parallel version)
178 if (stretch_x) then
179 length = abs(x_cb_glb(m_glb) - x_cb_glb(-1))
180
181 x_cb_glb = x_cb_glb/length
182
183 x_a = x_a/length
184 x_b = x_b/length
185
186 do j = 1, loops_x
187 do i = -1, m_glb
188 x_cb_glb(i) = x_cb_glb(i)/a_x*(a_x + log(cosh(a_x*(x_cb_glb(i) - x_a))) + log(cosh(a_x*(x_cb_glb(i) - x_b))) &
189 & - 2._wp*log(cosh(a_x*(x_b - x_a)/2._wp)))
190 end do
191 end do
192
193 x_cb_glb = x_cb_glb*length
194 end if
195
196 ! Grid generation in the y-direction
197 if (n_glb > 0) then
198 ! Axisymmetric cylindrical grid (r, z): half-cell offset at r=0 axis
199 if (grid_geometry == 2 .and. f_approx_equal(y_domain%beg, 0.0_wp)) then
200 dy = (y_domain%end - y_domain%beg)/real(2*n_glb + 1, wp)
201 y_cb_glb(-1) = y_domain%beg
202 do i = 1, n_glb
203 y_cb_glb(i - 1) = y_domain%beg + dy*real(2*i - 1, wp)
204 end do
205 else
206 dy = (y_domain%end - y_domain%beg)/real(n_glb + 1, wp)
207 do i = 0, n_glb
208 y_cb_glb(i - 1) = y_domain%beg + dy*real(i, wp)
209 end do
210 end if
211 y_cb_glb(n_glb) = y_domain%end
212 if (stretch_y) then
213 length = abs(y_cb_glb(n_glb) - y_cb_glb(-1))
214
215 y_cb_glb = y_cb_glb/length
216
217 y_a = y_a/length
218 y_b = y_b/length
219
220 do j = 1, loops_y
221 do i = -1, n_glb
222 y_cb_glb(i) = y_cb_glb(i)/a_y*(a_y + log(cosh(a_y*(y_cb_glb(i) - y_a))) + log(cosh(a_y*(y_cb_glb(i) - y_b) &
223 & )) - 2._wp*log(cosh(a_y*(y_b - y_a)/2._wp)))
224 end do
225 end do
226
227 y_cb_glb = y_cb_glb*length
228 end if
229
230 ! Grid generation in the z-direction
231 if (p_glb > 0) then
232 dz = (z_domain%end - z_domain%beg)/real(p_glb + 1, wp)
233 do i = 0, p_glb
234 z_cb_glb(i - 1) = z_domain%beg + dz*real(i, wp)
235 end do
236 z_cb_glb(p_glb) = z_domain%end
237 if (stretch_z) then
238 length = abs(z_cb_glb(p_glb) - z_cb_glb(-1))
239
240 z_cb_glb = z_cb_glb/length
241 z_a = z_a/length
242 z_b = z_b/length
243
244 do j = 1, loops_z
245 do i = -1, p_glb
246 z_cb_glb(i) = z_cb_glb(i)/a_z*(a_z + log(cosh(a_z*(z_cb_glb(i) - z_a))) + log(cosh(a_z*(z_cb_glb(i) &
247 & - z_b))) - 2._wp*log(cosh(a_z*(z_b - z_a)/2._wp)))
248 end do
249 end do
250
251 z_cb_glb = z_cb_glb*length
252 end if
253 end if
254 end if
255
256 ! Write cell boundary locations to grid data files
257 file_loc = trim(case_dir) // '/restart_data' // trim(mpiiofs) // 'x_cb.dat'
258 data_size = m_glb + 2
259 call mpi_file_open(mpi_comm_self, file_loc, ior(mpi_mode_wronly, mpi_mode_create), mpi_info_int, ifile, ierr)
260 call mpi_file_write(ifile, x_cb_glb, data_size, mpi_p, status, ierr)
261 call mpi_file_close(ifile, ierr)
262
263 if (n > 0) then
264 file_loc = trim(case_dir) // '/restart_data' // trim(mpiiofs) // 'y_cb.dat'
265 data_size = n_glb + 2
266 call mpi_file_open(mpi_comm_self, file_loc, ior(mpi_mode_wronly, mpi_mode_create), mpi_info_int, ifile, ierr)
267 call mpi_file_write(ifile, y_cb_glb, data_size, mpi_p, status, ierr)
268 call mpi_file_close(ifile, ierr)
269
270 if (p > 0) then
271 file_loc = trim(case_dir) // '/restart_data' // trim(mpiiofs) // 'z_cb.dat'
272 data_size = p_glb + 2
273 call mpi_file_open(mpi_comm_self, file_loc, ior(mpi_mode_wronly, mpi_mode_create), mpi_info_int, ifile, ierr)
274 call mpi_file_write(ifile, z_cb_glb, data_size, mpi_p, status, ierr)
275 call mpi_file_close(ifile, ierr)
276 end if
277 end if
278
279 deallocate (x_cb_glb, y_cb_glb, z_cb_glb)
280#endif
281
282 end subroutine s_generate_parallel_grid
283
284 !> Computation of parameters, allocation procedures, and/or any other tasks needed to properly setup the module
285 impure subroutine s_initialize_grid_module
286
287 if (parallel_io .neqv. .true.) then
289 else
291 end if
292
293 end subroutine s_initialize_grid_module
294
295 !> Deallocation procedures for the module
296 impure subroutine s_finalize_grid_module
297
298 s_generate_grid => null()
299
300 end subroutine s_finalize_grid_module
301
302end module m_grid
Abstract interface for generating a rectilinear computational grid.
Definition m_grid.f90:24
integer, intent(in) j
Shared derived types for field data, patch geometry, bubble dynamics, and MPI I/O structures.
Defines global parameters for the computational domain, simulation algorithm, and initial conditions.
integer grid_geometry
Cylindrical coordinates (either axisymmetric or full 3D).
integer p_glb
Global number of cells in each direction.
integer mpi_info_int
MPI info for parallel IO with Lustre file systems.
real(wp) dz
Minimum cell-widths in the x-, y- and z-coordinate directions.
real(wp), dimension(:), allocatable y_cc
real(wp), dimension(:), allocatable y_cb
type(bounds_info) z_domain
Locations of the domain bounds in the x-, y- and z-coordinate directions.
character(len=name_len) mpiiofs
real(wp), dimension(:), allocatable z_cb
real(wp), dimension(:), allocatable x_cc
Locations of cell-centers (cc) in x-, y- and z-directions, respectively.
real(wp), dimension(:), allocatable x_cb
Locations of cell-boundaries (cb) in x-, y- and z-directions, respectively.
real(wp), dimension(:), allocatable z_cc
logical stretch_z
Grid stretching flags for the x-, y- and z-coordinate directions.
integer num_procs
Number of processors.
character(len=path_len) case_dir
Case folder location.
logical parallel_io
Format of the data files.
Generates uniform or stretched rectilinear grids with hyperbolic-tangent spacing.
Definition m_grid.f90:6
impure subroutine, public s_generate_serial_grid
Generate a uniform or stretched rectilinear grid in serial from user parameters.
Definition m_grid.f90:35
impure subroutine, public s_initialize_grid_module
Computation of parameters, allocation procedures, and/or any other tasks needed to properly setup the...
Definition m_grid.f90:286
procedure(s_generate_abstract_grid), pointer, public s_generate_grid
Definition m_grid.f90:29
impure subroutine, public s_generate_parallel_grid
Generate a uniform or stretched rectilinear grid in parallel from user parameters.
Definition m_grid.f90:157
impure subroutine, public s_finalize_grid_module
Deallocation procedures for the module.
Definition m_grid.f90:297
Basic floating-point utilities: approximate equality, default detection, and coordinate bounds.
logical elemental function, public f_approx_equal(a, b, tol_input)
Check if two floating point numbers of wp are within tolerance.
Broadcasts user inputs and decomposes the domain across MPI ranks for pre-processing.