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 real(dp) :: alpha
169
170 if (x <= grid(1) .and. xprobmin1 <= x) then
171 amplitude = array(1)
172
173 if (coordinate==cylindrical .and. grid(1) > 0) then
174 if (k2 .ne. 0.0d0) then
175 alpha = abs(k2)
176 else
177 alpha = 2.0d0
178 end if
179 amplitude = array(1) * (x / grid(1))**alpha
180 end if
181 else if (x >= grid(size(grid)) .and. x <= xprobmax1) then
182 amplitude = array(size(grid))
183 else if (x < xprobmin1 .or. x > xprobmax1) then
184 amplitude = 0.d0
185 else
186 idl = maxloc(grid, mask=(grid < x), dim=1)
187 idu = minloc(grid, mask=(grid > x), dim=1)
188 amplitude = array(idl) + (x - grid(idl)) * &
189 (array(idu) - array(idl)) / (grid(idu) - grid(idl))
190 end if
191 end subroutine ef_amplitude
192
193 ! subroutine custom analytics log file
194 ! called in "usr_print_log => analytics_log" in mod_usr.t
195 subroutine analytics_log
198
199 integer, parameter :: n_modes = 2
200 integer, parameter :: my_unit = 123
201 character(len=80) :: fmt_string = '(9(es12.4))', filename
202 logical, save :: alive, visited=.false.
203 double precision :: volume, magn_avg
204 double precision :: Tmax, Tmin, vmax, B1max, B2max, B3max
205
206 ! First output the standard log file:
208
209 ! Now make the custom _c.log file:
210 call get_minmax_temperature(tmax,tmin)
211 call get_max_velocity(vmax)
212 if (mhd_bool == 1) then
213 call get_max_b(b1max, b2max, b3max)
214 call get_volume_average_func(magnetic, magn_avg, volume)
215 end if
216
217 filename = trim(base_filename) // "_c.log"
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 if (mhd_bool == 1) then
224 write(my_unit,'(a)') 'global_time Tmax Tmin vmax B1max B2max B3max mag_avg'
225 else
226 write(my_unit,'(a)') 'global_time Tmax Tmin vmax'
227 end if
228 end if
229 visited = .true.
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 endif
240
241 ! if number of output doubles is increase, don't forget to change the fmt_string above
242 if (mhd_bool == 1) then
243 write(my_unit, fmt_string) global_time, tmax, tmin, vmax, b1max, b2max, b3max, magn_avg
244 else
245 write(my_unit, fmt_string) global_time, tmax, tmin, vmax
246 end if
247 close(my_unit)
248 end if
249 end subroutine analytics_log
250
251 pure function magnetic(w_vec, w_size) result(magn_energy)
253 integer, intent(in) :: w_size
254 double precision, intent(in) :: w_vec(w_size)
255 double precision :: magn_energy
256
257 magn_energy = 0.5d0 * sum(w_vec(mag_mhd(:))**2,dim=ndir+1)
258 end function magnetic
259
260 ! Calculate both min and max of temperature on grid in one go.
261 subroutine get_minmax_temperature(Tmax, Tmin)
264
265 double precision, intent(out) :: Tmax, Tmin
266
267 integer :: iigrid, igrid
268 double precision :: Tmax_mype, Tmax_recv, Tmin_mype, Tmin_recv
269 double precision :: wlocal(ixG^T,1:nw), xlocal(ixG^T,1:ndim)
270 double precision :: Te(ixG^T), pth(ixG^T), rho(ixG^T), Rfactor(ixG^T)
271
272 tmax_mype = -bigdouble
273 tmin_mype = bigdouble
274
275 !Loop over all the grids
276 do iigrid = 1, igridstail
277 igrid = igrids(iigrid)
278
279 wlocal(ixg^t,1:nw) = ps(igrid)%w(ixg^t,1:nw)
280 xlocal(ixg^t,1:ndim) = ps(igrid)%x(ixg^t,1:ndim)
281 call phys_get_pthermal(wlocal,xlocal,ixg^ll,ixg^ll,pth)
282 call phys_get_rho(wlocal,xlocal,ixg^ll,ixg^ll,rho)
283 call phys_get_rfactor(wlocal,xlocal,ixg^ll,ixg^ll,rfactor)
284 te(ixg^t) = pth(ixg^t)/(rho(ixg^t)*rfactor(ixg^t))
285
286 ! Compare values on current grid to temporary max/min
287 tmax_mype = max(tmax_mype,maxval(te(ixm^t)))
288 tmin_mype = min(tmin_mype,minval(te(ixm^t)))
289 end do
290
291 ! Make the information available on all tasks
292 call mpi_allreduce(tmax_mype, tmax_recv, 1, mpi_double_precision, &
293 mpi_max, icomm, ierrmpi)
294 call mpi_allreduce(tmin_mype, tmin_recv, 1, mpi_double_precision, &
295 mpi_min, icomm, ierrmpi)
296
297 tmax = tmax_recv
298 tmin = tmin_recv
299
300 end subroutine get_minmax_temperature
301
302 subroutine get_max_velocity(vmax)
304 use mod_physics, only: phys_get_v
305
306 double precision, intent(out) :: vmax
307
308 integer :: iigrid, igrid
309 double precision :: vmax_mype,vmax_recv
310 double precision :: v_vec(ixG^T,1:ndir), v(ixG^T)
311
312 vmax_mype = -bigdouble
313
314 !Loop over all the grids
315 do iigrid = 1, igridstail
316 igrid = igrids(iigrid)
317
318 call phys_get_v(ps(igrid)%w, ps(igrid)%x, ixg^ll, ixg^ll, v_vec)
319
320 v(ixm^t) = sqrt(sum(v_vec(ixm^t,:)**2,dim=ndir+1))
321
322 vmax_mype =max(vmax_mype ,maxval(v(ixm^t)))
323
324 end do
325
326 ! Make the information available on all tasks
327 call mpi_allreduce(vmax_mype, vmax_recv, 1, mpi_double_precision, &
328 mpi_max, icomm, ierrmpi)
329
330 vmax = vmax_recv
331
332 end subroutine get_max_velocity
333
334 subroutine get_max_b(B1max, B2max, B3max)
336
337 double precision, intent(out) :: B1max, B2max, B3max
338
339 integer :: iigrid, igrid
340 double precision :: B1max_mype, B1max_recv
341 double precision :: B2max_mype, B2max_recv
342 double precision :: B3max_mype, B3max_recv
343
344 b1max_mype = -bigdouble
345 b2max_mype = -bigdouble
346 b3max_mype = -bigdouble
347
348 !Loop over all the grids
349 do iigrid = 1, igridstail
350 igrid = igrids(iigrid)
351
352 b1max_mype = max(b1max_mype, maxval(ps(igrid)%w(ixg^t, mag_mhd(1))))
353 b2max_mype = max(b2max_mype, maxval(ps(igrid)%w(ixg^t, mag_mhd(2))))
354 if (ndir >= 3) then
355 b3max_mype = max(b3max_mype, maxval(ps(igrid)%w(ixg^t, mag_mhd(3))))
356 end if
357 end do
358
359 ! Make the information available on all tasks
360 call mpi_allreduce(b1max_mype, b1max_recv, 1, mpi_double_precision, &
361 mpi_max, icomm, ierrmpi)
362 call mpi_allreduce(b2max_mype, b2max_recv, 1, mpi_double_precision, &
363 mpi_max, icomm, ierrmpi)
364 call mpi_allreduce(b3max_mype, b3max_recv, 1, mpi_double_precision, &
365 mpi_max, icomm, ierrmpi)
366
367 b1max = b1max_recv
368 b2max = b2max_recv
369 b3max = b3max_recv
370
371 if (b2max == -bigdouble) b2max = 0.d0
372 if (b3max == -bigdouble) b3max = 0.d0
373
374 end subroutine get_max_b
375
376end module mod_gimli
377!
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:262
subroutine analytics_log
Definition mod_gimli.t:196
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:335
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:303
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:252
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:66
integer, public, protected rho_
Whether plasma is partially ionized.
Definition mod_hd_phys.t:63
integer, public, protected p_
Index of the gas pressure (-1 if not present) should equal e_.
Definition mod_hd_phys.t:78
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:77
procedure(sub_get_rfactor), pointer phys_get_rfactor
Definition mod_physics.t:81
procedure(sub_get_rho), pointer phys_get_rho
Definition mod_physics.t:70
procedure(sub_get_v), pointer phys_get_v
Definition mod_physics.t:69