MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_gimli.t
Go to the documentation of this file.
1!> Module for reading in Legolas .ldat data as initial condition
3 use, intrinsic :: iso_fortran_env
5 use mod_hd_phys, only: rho_hd=>rho_, mom_hd=>mom, p_hd=>p_
6 use mod_mhd_phys, only: rho_mhd=>rho_, mom_mhd=>mom, p_mhd=>p_
7 use mod_functions_bfield, only: mag_mhd=>mag
8
9 implicit none
10 public
11
12 integer, parameter :: dp = real64
13 integer :: idirmin0, idirmin
14
15 complex(dp), parameter :: ic = (0.0d0, 1.0d0)
16
17 integer :: ef_gridpts
18 real(dp) :: k2, k3
19 integer :: mhd_bool
20 real(dp), allocatable :: ef_grid(:)
21 complex(dp), allocatable :: rho(:)
22 complex(dp), allocatable :: v1(:)
23 complex(dp), allocatable :: v2(:)
24 complex(dp), allocatable :: v3(:)
25 complex(dp), allocatable :: p(:)
26 complex(dp), allocatable :: b1(:)
27 complex(dp), allocatable :: b2(:)
28 complex(dp), allocatable :: b3(:)
29
30 integer :: rho_idx, p_idx
31 integer, allocatable :: mom_idx(:), mag_idx(:)
32
33contains
34
35 subroutine read_legolas_data(legolas_file, file_id)
36 character(len=100), intent(in) :: legolas_file
37 integer, intent(in) :: file_id
38
39 open( &
40 unit=file_id+mype, &
41 file=legolas_file, &
42 form='unformatted' &
43 )
44
45 ! need to read physics_type because mod_physics not yet loaded at this point
46 read(file_id+mype) mhd_bool
47 read(file_id+mype) ef_gridpts
48 read(file_id+mype) k2, k3
49
51 read(file_id+mype) ef_grid
52 read(file_id+mype) rho
53 read(file_id+mype) v1
54 read(file_id+mype) v2
55 read(file_id+mype) v3
56 read(file_id+mype) p
57 if (mhd_bool == 1) then
58 read(file_id+mype) b1
59 read(file_id+mype) b2
60 read(file_id+mype) b3
61 end if
62
63 if (mhd_bool == 1) then
66 else
69 end if
70
71 close(file_id+mype)
72 end subroutine read_legolas_data
73
74 subroutine allocate_arrays(gridpts)
75 integer, intent(in) :: gridpts
76
77 allocate(ef_grid(gridpts))
78 allocate(rho(gridpts))
79 allocate(v1, v2, p, mold=rho)
80 if (ndim >= 3) allocate(v3, mold=rho)
81 if (mhd_bool == 1) then
82 allocate(b1, b2, mold=rho)
83 if (ndim >= 3) allocate(b3, mold=rho)
84 end if
85 end subroutine allocate_arrays
86
87 subroutine add_perturbation_to_w_array(ixI^L, ixO^L, w, w_index, x)
88 integer, intent(in) :: ixI^L, ixO^L
89 real(dp), intent(inout) :: w(ixI^S, nw)
90 integer, intent(in) :: w_index
91 real(dp), intent(in) :: x(ixI^S, ndim)
92 complex(dp) :: amplitude, exp_factor(ixI^S), quantity, values(ef_gridpts)
93 integer :: idx^D
94 real(dp) :: k1 = 0.0d0
95
96 call w_index_to_array(w_index, values)
97 exp_factor = {exp(ic * k^d * x(ixi^s, ^d))|*}
98
99 {do idx^d = iximin^d, iximax^d|\}
100 call ef_amplitude(x(idx^d, 1), ef_grid, values, amplitude)
101 quantity = amplitude * exp_factor(idx^d)
102 w(idx^d, w_index) = w(idx^d, w_index) + quantity%re
103 {end do|\}
104 end subroutine add_perturbation_to_w_array
105
107 if (mhd_bool == 1) then
108 rho_idx = rho_mhd
109 p_idx = p_mhd
110
111 if (.not. allocated(mom_idx)) allocate(mom_idx(size(mom_mhd)))
112 mom_idx = mom_mhd
113
114 if (.not. allocated(mag_idx)) allocate(mag_idx(size(mag_mhd)))
115 mag_idx = mag_mhd
116 else
117 rho_idx = rho_hd
118 p_idx = p_hd
119
120 if (.not. allocated(mom_idx)) allocate(mom_idx(size(mom_hd)))
121 mom_idx = mom_hd
122
123 end if
124 end subroutine init_gimli_indices
125
126 subroutine w_index_to_array(w_index, array)
127 integer, intent(in) :: w_index
128 complex(dp), intent(inout) :: array(ef_gridpts)
129
130 call init_gimli_indices()
131
132 if (w_index == rho_idx) then
133 array = rho
134 else if (w_index == mom_idx(1)) then
135 array = v1
136 else if (w_index == mom_idx(2)) then
137 array = v2
138 end if
139
140 if (ndim >= 3) then
141 if (w_index == mom_idx(3)) then
142 array = v3
143 end if
144 end if
145 if (w_index == p_idx) then
146 array = p
147 end if
148 if (mhd_bool == 1) then
149 if (w_index == mag_idx(1)) then
150 array = b1
151 else if (w_index == mag_idx(2)) then
152 array = b2
153 end if
154 if (ndim >= 3) then
155 if (w_index == mag_idx(3)) then
156 array = b3
157 end if
158 end if
159 end if
160 end subroutine w_index_to_array
161
162 subroutine ef_amplitude(x, grid, array, amplitude)
164 real(dp), intent(in) :: x, grid(ef_gridpts)
165 complex(dp), intent(in) :: array(ef_gridpts)
166 complex(dp), intent(out) :: amplitude
167 integer :: idl, idu
168
169 if (x <= grid(1) .and. xprobmin1 <= x) then
170 amplitude = array(1)
171
172 if (coordinate==cylindrical .and. grid(1) > 0) then
173 if (x >= grid(1)/2) then
174 amplitude = (x - grid(1)/2) * array(1) / grid(1)
175 else
176 amplitude = 0.d0
177 end if
178 end if
179 else if (x >= grid(size(grid)) .and. x <= xprobmax1) then
180 amplitude = array(size(grid))
181 else if (x < xprobmin1 .or. x > xprobmax1) then
182 amplitude = 0.d0
183 else
184 idl = maxloc(grid, mask=(grid < x), dim=1)
185 idu = minloc(grid, mask=(grid > x), dim=1)
186 amplitude = array(idl) + (x - grid(idl)) * &
187 (array(idu) - array(idl)) / (grid(idu) - grid(idl))
188 end if
189 end subroutine ef_amplitude
190
191 ! subroutine custom analytics log file
192 ! called in "usr_print_log => analytics_log" in mod_usr.t
193 subroutine analytics_log
196
197 integer, parameter :: n_modes = 2
198 integer, parameter :: my_unit = 123
199 character(len=80) :: fmt_string = '(9(es12.4))', filename
200 logical, save :: alive, visited=.false.
201 double precision :: volume, magn_avg
202 double precision :: Tmax, Tmin, vmax, B1max, B2max, B3max
203
204 ! First output the standard log file:
206
207 ! Now make the custom _c.log file:
208 call get_minmax_temperature(tmax,tmin)
209 call get_max_velocity(vmax)
210 if (mhd_bool == 1) then
211 call get_max_b(b1max, b2max, b3max)
212 call get_volume_average_func(magnetic, magn_avg, volume)
213 end if
214
215 filename = trim(base_filename) // "_c.log"
216
217 if (mype == 0) then
218
219 if (.not. visited) then
220 ! Delete the log when not doing a restart run
221 if (restart_from_file == undefined .or. reset_time) then
222 open(unit=my_unit,file=trim(filename),form='formatted',status='replace')
223 end if
224 visited = .true.
225 if (mhd_bool == 1) then
226 write(my_unit,'(a)') 'global_time Tmax Tmin vmax B1max B2max B3max mag_avg'
227 else
228 write(my_unit,'(a)') 'global_time Tmax Tmin vmax'
229 end if
230 end if
231
232 if (mype == 0) then
233 write(filename,"(a)") filename
234 inquire(file=filename,exist=alive)
235 if(alive) then
236 open(unit=my_unit,file=filename,form='formatted',status='old',access='append')
237 else
238 open(unit=my_unit,file=filename,form='formatted',status='new')
239 end if
240 end if
241
242 ! if number of output doubles is increase, don't forget to change the fmt_string above
243 if (mhd_bool == 1) then
244 write(my_unit, fmt_string) global_time, tmax, tmin, vmax, b1max, b2max, b3max, magn_avg
245 else
246 write(my_unit, fmt_string) global_time, tmax, tmin, vmax
247 end if
248 close(my_unit)
249 end if
250 end subroutine analytics_log
251
252 pure function magnetic(w_vec, w_size) result(magn_energy)
254 integer, intent(in) :: w_size
255 double precision, intent(in) :: w_vec(w_size)
256 double precision :: magn_energy
257
258 magn_energy = 0.5d0 * sum(w_vec(mag_mhd(:))**2,dim=ndir+1)
259 end function magnetic
260
261 ! Calculate both min and max of temperature on grid in one go.
262 subroutine get_minmax_temperature(Tmax, Tmin)
265
266 double precision, intent(out) :: Tmax, Tmin
267
268 integer :: iigrid, igrid
269 double precision :: Tmax_mype, Tmax_recv, Tmin_mype, Tmin_recv
270 double precision :: wlocal(ixG^T,1:nw), xlocal(ixG^T,1:ndim)
271 double precision :: Te(ixG^T), pth(ixG^T), rho(ixG^T), Rfactor(ixG^T)
272
273 tmax_mype = -bigdouble
274 tmin_mype = bigdouble
275
276 !Loop over all the grids
277 do iigrid = 1, igridstail
278 igrid = igrids(iigrid)
279
280 wlocal(ixg^t,1:nw) = ps(igrid)%w(ixg^t,1:nw)
281 xlocal(ixg^t,1:ndim) = ps(igrid)%x(ixg^t,1:ndim)
282 call phys_get_pthermal(wlocal,xlocal,ixg^ll,ixg^ll,pth)
283 call phys_get_rho(wlocal,xlocal,ixg^ll,ixg^ll,rho)
284 call phys_get_rfactor(wlocal,xlocal,ixg^ll,ixg^ll,rfactor)
285 te(ixg^t) = pth(ixg^t)/(rho(ixg^t)*rfactor(ixg^t))
286
287 ! Compare values on current grid to temporary max/min
288 tmax_mype = max(tmax_mype,maxval(te(ixm^t)))
289 tmin_mype = min(tmin_mype,minval(te(ixm^t)))
290 end do
291
292 ! Make the information available on all tasks
293 call mpi_allreduce(tmax_mype, tmax_recv, 1, mpi_double_precision, &
294 mpi_max, icomm, ierrmpi)
295 call mpi_allreduce(tmin_mype, tmin_recv, 1, mpi_double_precision, &
296 mpi_min, icomm, ierrmpi)
297
298 tmax = tmax_recv
299 tmin = tmin_recv
300
301 end subroutine get_minmax_temperature
302
303 subroutine get_max_velocity(vmax)
305 use mod_physics, only: phys_get_v
306
307 double precision, intent(out) :: vmax
308
309 integer :: iigrid, igrid
310 double precision :: vmax_mype,vmax_recv
311 double precision :: v_vec(ixG^T,1:ndir), v(ixG^T)
312
313 vmax_mype = -bigdouble
314
315 !Loop over all the grids
316 do iigrid = 1, igridstail
317 igrid = igrids(iigrid)
318
319 call phys_get_v(ps(igrid)%w, ps(igrid)%x, ixg^ll, ixg^ll, v_vec)
320
321 v(ixm^t) = sqrt(sum(v_vec(ixm^t,:)**2,dim=ndir+1))
322
323 vmax_mype =max(vmax_mype ,maxval(v(ixm^t)))
324
325 end do
326
327 ! Make the information available on all tasks
328 call mpi_allreduce(vmax_mype, vmax_recv, 1, mpi_double_precision, &
329 mpi_max, icomm, ierrmpi)
330
331 vmax = vmax_recv
332
333 end subroutine get_max_velocity
334
335 subroutine get_max_b(B1max, B2max, B3max)
337
338 double precision, intent(out) :: B1max, B2max, B3max
339
340 integer :: iigrid, igrid
341 double precision :: B1max_mype, B1max_recv
342 double precision :: B2max_mype, B2max_recv
343 double precision :: B3max_mype, B3max_recv
344
345 b1max_mype = -bigdouble
346 b2max_mype = -bigdouble
347 b3max_mype = -bigdouble
348
349 !Loop over all the grids
350 do iigrid = 1, igridstail
351 igrid = igrids(iigrid)
352
353 b1max_mype = max(b1max_mype, maxval(ps(igrid)%w(ixg^t, mag_mhd(1))))
354 b2max_mype = max(b2max_mype, maxval(ps(igrid)%w(ixg^t, mag_mhd(2))))
355 if (ndir >= 3) then
356 b3max_mype = max(b3max_mype, maxval(ps(igrid)%w(ixg^t, mag_mhd(3))))
357 end if
358 end do
359
360 ! Make the information available on all tasks
361 call mpi_allreduce(b1max_mype, b1max_recv, 1, mpi_double_precision, &
362 mpi_max, icomm, ierrmpi)
363 call mpi_allreduce(b2max_mype, b2max_recv, 1, mpi_double_precision, &
364 mpi_max, icomm, ierrmpi)
365 call mpi_allreduce(b3max_mype, b3max_recv, 1, mpi_double_precision, &
366 mpi_max, icomm, ierrmpi)
367
368 b1max = b1max_recv
369 b2max = b2max_recv
370 b3max = b3max_recv
371
372 if (b2max == -bigdouble) b2max = 0.d0
373 if (b3max == -bigdouble) b3max = 0.d0
374
375 end subroutine get_max_b
376
377end module mod_gimli
378!
integer, dimension(:), allocatable, public mag
Indices of the magnetic field.
Module with geometry-related routines (e.g., divergence, curl)
Definition mod_geometry.t:2
integer coordinate
Definition mod_geometry.t:7
integer, parameter cylindrical
Module for reading in Legolas .ldat data as initial condition.
Definition mod_gimli.t:2
integer mhd_bool
Definition mod_gimli.t:19
integer, parameter dp
Definition mod_gimli.t:12
integer, dimension(:), allocatable mom_idx
Definition mod_gimli.t:31
complex(dp), dimension(:), allocatable b2
Definition mod_gimli.t:27
real(dp), dimension(:), allocatable ef_grid
Definition mod_gimli.t:20
integer, dimension(:), allocatable mag_idx
Definition mod_gimli.t:31
integer ef_gridpts
Definition mod_gimli.t:17
subroutine get_minmax_temperature(tmax, tmin)
Definition mod_gimli.t:263
subroutine analytics_log
Definition mod_gimli.t:194
complex(dp), dimension(:), allocatable p
Definition mod_gimli.t:25
subroutine read_legolas_data(legolas_file, file_id)
Definition mod_gimli.t:36
complex(dp), dimension(:), allocatable v1
Definition mod_gimli.t:22
integer idirmin
Definition mod_gimli.t:13
integer p_idx
Definition mod_gimli.t:30
real(dp) k3
Definition mod_gimli.t:18
subroutine add_perturbation_to_w_array(ixil, ixol, w, w_index, x)
Definition mod_gimli.t:88
integer idirmin0
Definition mod_gimli.t:13
subroutine ef_amplitude(x, grid, array, amplitude)
Definition mod_gimli.t:163
subroutine get_max_b(b1max, b2max, b3max)
Definition mod_gimli.t:336
complex(dp), parameter ic
Definition mod_gimli.t:15
real(dp) k2
Definition mod_gimli.t:18
complex(dp), dimension(:), allocatable v3
Definition mod_gimli.t:24
subroutine get_max_velocity(vmax)
Definition mod_gimli.t:304
subroutine init_gimli_indices()
Definition mod_gimli.t:107
complex(dp), dimension(:), allocatable b1
Definition mod_gimli.t:26
integer rho_idx
Definition mod_gimli.t:30
subroutine allocate_arrays(gridpts)
Definition mod_gimli.t:75
subroutine w_index_to_array(w_index, array)
Definition mod_gimli.t:127
complex(dp), dimension(:), allocatable b3
Definition mod_gimli.t:28
complex(dp), dimension(:), allocatable rho
Definition mod_gimli.t:21
complex(dp), dimension(:), allocatable v2
Definition mod_gimli.t:23
pure double precision function magnetic(w_vec, w_size)
Definition mod_gimli.t:253
This module contains definitions of global parameters and variables and some generic functions/subrou...
double precision unit_time
Physical scaling factor for time.
double precision unit_density
Physical scaling factor for density.
double precision global_time
The global simulation time.
double precision unit_numberdensity
Physical scaling factor for number density.
double precision unit_pressure
Physical scaling factor for pressure.
integer, parameter ndim
Number of spatial dimensions for grid variables.
double precision unit_length
Physical scaling factor for length.
integer icomm
The MPI communicator.
logical reset_time
If true, reset iteration count and global_time to original values, and start writing snapshots at ind...
integer mype
The rank of the current MPI task.
integer ndir
Number of spatial dimensions (components) for vector variables.
integer ixm
the mesh range of a physical block without ghost cells
integer ierrmpi
A global MPI error return code.
double precision unit_magneticfield
Physical scaling factor for magnetic field.
double precision unit_velocity
Physical scaling factor for velocity.
character(len=std_len) restart_from_file
If not 'unavailable', resume from snapshot with this base file name.
double precision unit_temperature
Physical scaling factor for temperature.
character(len= *), parameter undefined
character(len=std_len) base_filename
Base file name for simulation output, which will be followed by a number.
Hydrodynamics physics module.
Definition mod_hd_phys.t:2
integer, dimension(:), allocatable, public, protected mom
Indices of the momentum density.
Definition mod_hd_phys.t:59
integer, public, protected rho_
Index of the density (in the w array)
Definition mod_hd_phys.t:56
integer, public, protected p_
Index of the gas pressure (-1 if not present) should equal e_.
Definition mod_hd_phys.t:71
Module for reading input and writing output.
subroutine get_volume_average_func(func, f_avg, volume)
Compute the volume average of func(w) over the leaves of the grid.
subroutine printlog_default
Write volume-averaged values and other information to the log file.
Magneto-hydrodynamics module.
Definition mod_mhd_phys.t:2
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition mod_physics.t:4
procedure(sub_get_pthermal), pointer phys_get_pthermal
Definition mod_physics.t:70
procedure(sub_get_rfactor), pointer phys_get_rfactor
Definition mod_physics.t:73
procedure(sub_get_rho), pointer phys_get_rho
Definition mod_physics.t:63
procedure(sub_get_v), pointer phys_get_v
Definition mod_physics.t:62