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 use mod_eos, only: eos
9 use mod_comm_lib, only: mpistop
10
11 implicit none
12 public
13
14 integer, parameter :: dp = real64
15 integer :: idirmin0, idirmin
16
17 complex(dp), parameter :: ic = (0.0d0, 1.0d0)
18
19 integer :: ef_gridpts
20 real(dp) :: k2, k3
21 integer :: mhd_bool
22 real(dp), allocatable :: ef_grid(:)
23 complex(dp), allocatable :: rho(:)
24 complex(dp), allocatable :: v1(:)
25 complex(dp), allocatable :: v2(:)
26 complex(dp), allocatable :: v3(:)
27 complex(dp), allocatable :: p(:)
28 complex(dp), allocatable :: b1(:)
29 complex(dp), allocatable :: b2(:)
30 complex(dp), allocatable :: b3(:)
31
32 integer :: rho_idx, p_idx
33 integer, allocatable :: mom_idx(:), mag_idx(:)
34
35contains
36
37 subroutine read_legolas_data(legolas_file, file_id)
38 character(len=100), intent(in) :: legolas_file
39 integer, intent(in) :: file_id
40
41 open( &
42 unit=file_id+mype, &
43 file=legolas_file, &
44 form='unformatted' &
45 )
46
47 ! need to read physics_type because mod_physics not yet loaded at this point
48 read(file_id+mype) mhd_bool
49 read(file_id+mype) ef_gridpts
50 read(file_id+mype) k2, k3
51
53 read(file_id+mype) ef_grid
54 read(file_id+mype) rho
55 read(file_id+mype) v1
56 read(file_id+mype) v2
57 read(file_id+mype) v3
58 read(file_id+mype) p
59 if (mhd_bool == 1) then
60 read(file_id+mype) b1
61 read(file_id+mype) b2
62 read(file_id+mype) b3
63 end if
64
65 if (mhd_bool == 1) then
68 else
71 end if
72
73 close(file_id+mype)
74 end subroutine read_legolas_data
75
76 subroutine allocate_arrays(gridpts)
77 integer, intent(in) :: gridpts
78
79 allocate(ef_grid(gridpts))
80 allocate(rho(gridpts))
81 allocate(v1, v2, p, mold=rho)
82 if (ndim >= 3) allocate(v3, mold=rho)
83 if (mhd_bool == 1) then
84 allocate(b1, b2, mold=rho)
85 if (ndim >= 3) allocate(b3, mold=rho)
86 end if
87 end subroutine allocate_arrays
88
89 subroutine add_perturbation_to_w_array(ixI^L, ixO^L, w, w_index, x)
90 integer, intent(in) :: ixI^L, ixO^L
91 real(dp), intent(inout) :: w(ixI^S, nw)
92 integer, intent(in) :: w_index
93 real(dp), intent(in) :: x(ixI^S, ndim)
94 complex(dp) :: amplitude, exp_factor(ixI^S), quantity, values(ef_gridpts)
95 integer :: idx^D
96 real(dp) :: k1 = 0.0d0
97
98 call w_index_to_array(w_index, values)
99 exp_factor = {exp(ic * k^d * x(ixi^s, ^d))|*}
100
101 {do idx^d = iximin^d, iximax^d|\}
102 call ef_amplitude(x(idx^d, 1), ef_grid, values, amplitude)
103 quantity = amplitude * exp_factor(idx^d)
104 w(idx^d, w_index) = w(idx^d, w_index) + quantity%re
105 {end do|\}
106 end subroutine add_perturbation_to_w_array
107
109 if (mhd_bool == 1) then
110 rho_idx = rho_mhd
111 p_idx = p_mhd
112
113 if (.not. allocated(mom_idx)) allocate(mom_idx(size(mom_mhd)))
114 mom_idx = mom_mhd
115
116 if (.not. allocated(mag_idx)) allocate(mag_idx(size(mag_mhd)))
117 mag_idx = mag_mhd
118 else
119 rho_idx = rho_hd
120 p_idx = p_hd
121
122 if (.not. allocated(mom_idx)) allocate(mom_idx(size(mom_hd)))
123 mom_idx = mom_hd
124
125 end if
126 end subroutine init_gimli_indices
127
128 subroutine w_index_to_array(w_index, array)
129 integer, intent(in) :: w_index
130 complex(dp), intent(inout) :: array(ef_gridpts)
131
132 call init_gimli_indices()
133
134 if (w_index == rho_idx) then
135 array = rho
136 else if (w_index == mom_idx(1)) then
137 array = v1
138 else if (w_index == mom_idx(2)) then
139 array = v2
140 end if
141
142 if (ndim >= 3) then
143 if (w_index == mom_idx(3)) then
144 array = v3
145 end if
146 end if
147 if (w_index == p_idx) then
148 array = p
149 end if
150 if (mhd_bool == 1) then
151 if (w_index == mag_idx(1)) then
152 array = b1
153 else if (w_index == mag_idx(2)) then
154 array = b2
155 end if
156 if (ndim >= 3) then
157 if (w_index == mag_idx(3)) then
158 array = b3
159 end if
160 end if
161 end if
162 end subroutine w_index_to_array
163
164 subroutine ef_amplitude(x, grid, array, amplitude)
166 real(dp), intent(in) :: x, grid(ef_gridpts)
167 complex(dp), intent(in) :: array(ef_gridpts)
168 complex(dp), intent(out) :: amplitude
169 integer :: idl, idu
170 real(dp) :: alpha
171
172 if (x <= grid(1) .and. xprobmin1 <= x) then
173 amplitude = array(1)
174
175 if (coordinate==cylindrical .and. grid(1) > 0) then
176 if (k2 .ne. 0.0d0) then
177 alpha = abs(k2)
178 else
179 alpha = 2.0d0
180 end if
181 amplitude = array(1) * (x / grid(1))**alpha
182 end if
183 else if (x >= grid(size(grid)) .and. x <= xprobmax1) then
184 amplitude = array(size(grid))
185 else if (x < xprobmin1 .or. x > xprobmax1) then
186 amplitude = 0.d0
187 else
188 idl = maxloc(grid, mask=(grid < x), dim=1)
189 idu = minloc(grid, mask=(grid > x), dim=1)
190 amplitude = array(idl) + (x - grid(idl)) * &
191 (array(idu) - array(idl)) / (grid(idu) - grid(idl))
192 end if
193 end subroutine ef_amplitude
194
195 ! subroutine custom analytics log file
196 ! called in "usr_print_log => analytics_log" in mod_usr.t
197 subroutine analytics_log
200
201 integer, parameter :: n_modes = 2
202 integer, parameter :: my_unit = 123
203 character(len=80) :: fmt_string = '(9(es12.4))', filename
204 logical, save :: alive, visited=.false.
205 double precision :: volume, magn_avg
206 double precision :: Tmax, Tmin, vmax, B1max, B2max, B3max
207
208 ! First output the standard log file:
210
211 ! Now make the custom _c.log file:
212 call get_minmax_temperature(tmax,tmin)
213 call get_max_velocity(vmax)
214 if (mhd_bool == 1) then
215 call get_max_b(b1max, b2max, b3max)
216 call get_volume_average_func(magnetic, magn_avg, volume)
217 end if
218
219 filename = trim(base_filename) // "_c.log"
220
221 if (mype == 0 .and. .not. visited) then
222 ! Delete the log when not doing a restart run
223 if (restart_from_file == undefined .or. reset_time) then
224 open(unit=my_unit,file=trim(filename),form='formatted',status='replace')
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 visited = .true.
232 end if
233
234 if (mype == 0) then
235 write(filename,"(a)") filename
236 inquire(file=filename,exist=alive)
237 if(alive) then
238 open(unit=my_unit,file=filename,form='formatted',status='old',access='append')
239 else
240 open(unit=my_unit,file=filename,form='formatted',status='new')
241 endif
242
243 ! if number of output doubles is increase, don't forget to change the fmt_string above
244 if (mhd_bool == 1) then
245 write(my_unit, fmt_string) global_time, tmax, tmin, vmax, b1max, b2max, b3max, magn_avg
246 else
247 write(my_unit, fmt_string) global_time, tmax, tmin, vmax
248 end if
249 close(my_unit)
250 end if
251 end subroutine analytics_log
252
253 pure function magnetic(w_vec, w_size) result(magn_energy)
255 integer, intent(in) :: w_size
256 double precision, intent(in) :: w_vec(w_size)
257 double precision :: magn_energy
258
259 magn_energy = 0.5d0 * sum(w_vec(mag_mhd(:))**2,dim=ndir+1)
260 end function magnetic
261
262 ! Calculate both min and max of temperature on grid in one go.
263 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 eos%get_thermal_pressure(wlocal,xlocal,ixg^ll,ixg^ll,pth)
283 call eos%get_rho(wlocal,xlocal,ixg^ll,ixm^ll,rho)
284 call eos%get_Rfactor(wlocal,xlocal,ixg^ll,ixg^ll,rfactor)
285 te(ixm^t) = pth(ixm^t)/(rho(ixm^t)*rfactor(ixm^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
377 subroutine symm(ixI^L,ixO^L,w,x,w_index,boundary)
378 !> Symmetric boundary condition
379 integer, intent(in) :: ixI^L, ixO^L, w_index
380 double precision, intent(in) :: x(ixI^S, 1:ndim)
381 double precision, intent(inout) :: w(ixI^S, 1:nw)
382 character(len=*), intent(in) :: boundary
383
384 select case (boundary)
385 case ('outer')
386 w(ixo^s, w_index) = w(ixomin1-1:ixomin1-nghostcells:-1^%1ixo^s, w_index)
387 case ('inner')
388 w(ixo^s, w_index) = w(ixomax1+nghostcells:ixomax1+1:-1^%1ixo^s, w_index)
389 case default
390 call mpistop('Unknown boundary side: ' // trim(boundary))
391 end select
392
393 end subroutine symm
394
395 subroutine split_symm(ixI^L,ixO^L,w,x,w_index,equi_w,boundary)
396 !> Symmetric boundary condition applied to the perturbation only
397 integer, intent(in) :: ixI^L, ixO^L, w_index
398 double precision, intent(in) :: x(ixI^S, 1:ndim)
399 double precision, intent(inout) :: w(ixI^S, 1:nw)
400 double precision, intent(in) :: equi_w(ixI^S)
401 character(len=*), intent(in) :: boundary
402
403 select case (boundary)
404 case ('outer')
405 w(ixo^s, w_index) = equi_w(ixo^s) &
406 + (w(ixomin1-1:ixomin1-nghostcells:-1^%1ixo^s, w_index) - equi_w(ixomin1-1:ixomin1-nghostcells:-1^%1ixo^s))
407 case ('inner')
408 w(ixo^s, w_index) = equi_w(ixo^s) &
409 + (w(ixomax1+nghostcells:ixomax1+1:-1^%1ixo^s, w_index) - equi_w(ixomax1+nghostcells:ixomax1+1:-1^%1ixo^s))
410 case default
411 call mpistop('Unknown boundary side: ' // trim(boundary))
412 end select
413
414 end subroutine split_symm
415
416 subroutine extrapolate(ixI^L,ixO^L,w,x,w_index,boundary)
417 !> Extrapolate boundary condition
418 integer, intent(in) :: ixI^L, ixO^L, w_index
419 double precision, intent(in) :: x(ixI^S, 1:ndim)
420 double precision, intent(inout) :: w(ixI^S, 1:nw)
421 character(len=*), intent(in) :: boundary
422 integer :: ix1
423
424 select case (boundary)
425 case ('outer')
426 do ix1 = ixomin1, ixomax1
427 w(ix1^%1ixo^s, w_index) = 2.0d0 * w(ix1-1^%1ixo^s, w_index) &
428 - w(ix1-2^%1ixo^s, w_index)
429 end do
430 case ('inner')
431 do ix1 = ixomax1, ixomin1, -1
432 w(ix1^%1ixo^s, w_index) = 2.0d0 * w(ix1+1^%1ixo^s, w_index) &
433 - w(ix1+2^%1ixo^s, w_index)
434 end do
435 case default
436 call mpistop('Unknown boundary side: ' // trim(boundary))
437 end select
438
439 end subroutine extrapolate
440
441 subroutine split_extrapolate(ixI^L,ixO^L,w,x,w_index,equi_w,boundary)
442 !> Extrapolate boundary condition applied to the perturbation only
443 integer, intent(in) :: ixI^L, ixO^L, w_index
444 double precision, intent(in) :: x(ixI^S, 1:ndim)
445 double precision, intent(inout) :: w(ixI^S, 1:nw)
446 double precision, intent(in) :: equi_w(ixI^S)
447 character(len=*), intent(in) :: boundary
448 integer :: ix1
449
450 select case (boundary)
451 case ('outer')
452 do ix1 = ixomin1, ixomax1
453 w(ix1^%1ixo^s, w_index) = equi_w(ix1^%1ixo^s) &
454 + 2.0d0 * (w(ix1-1^%1ixo^s, w_index) - equi_w(ix1-1^%1ixo^s)) &
455 - (w(ix1-2^%1ixo^s, w_index) - equi_w(ix1-2^%1ixo^s))
456 end do
457 case ('inner')
458 do ix1 = ixomax1, ixomin1, -1
459 w(ix1^%1ixo^s, w_index) = equi_w(ix1^%1ixo^s) &
460 + 2.0d0 * (w(ix1+1^%1ixo^s, w_index) - equi_w(ix1+1^%1ixo^s)) &
461 - (w(ix1+2^%1ixo^s, w_index) - equi_w(ix1+2^%1ixo^s))
462 end do
463 case default
464 call mpistop('Unknown boundary side: ' // trim(boundary))
465 end select
466
467 end subroutine split_extrapolate
468
469end module mod_gimli
470!
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Equation of state for AMRVAC, handled through a single eos_container object.
Definition mod_eos.t:30
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:21
integer, parameter dp
Definition mod_gimli.t:14
integer, dimension(:), allocatable mom_idx
Definition mod_gimli.t:33
complex(dp), dimension(:), allocatable b2
Definition mod_gimli.t:29
real(dp), dimension(:), allocatable ef_grid
Definition mod_gimli.t:22
integer, dimension(:), allocatable mag_idx
Definition mod_gimli.t:33
integer ef_gridpts
Definition mod_gimli.t:19
subroutine get_minmax_temperature(tmax, tmin)
Definition mod_gimli.t:264
subroutine analytics_log
Definition mod_gimli.t:198
complex(dp), dimension(:), allocatable p
Definition mod_gimli.t:27
subroutine read_legolas_data(legolas_file, file_id)
Definition mod_gimli.t:38
complex(dp), dimension(:), allocatable v1
Definition mod_gimli.t:24
subroutine symm(ixil, ixol, w, x, w_index, boundary)
Definition mod_gimli.t:378
integer idirmin
Definition mod_gimli.t:15
integer p_idx
Definition mod_gimli.t:32
subroutine split_symm(ixil, ixol, w, x, w_index, equi_w, boundary)
Definition mod_gimli.t:396
real(dp) k3
Definition mod_gimli.t:20
subroutine add_perturbation_to_w_array(ixil, ixol, w, w_index, x)
Definition mod_gimli.t:90
integer idirmin0
Definition mod_gimli.t:15
subroutine ef_amplitude(x, grid, array, amplitude)
Definition mod_gimli.t:165
subroutine get_max_b(b1max, b2max, b3max)
Definition mod_gimli.t:336
complex(dp), parameter ic
Definition mod_gimli.t:17
subroutine extrapolate(ixil, ixol, w, x, w_index, boundary)
Definition mod_gimli.t:417
real(dp) k2
Definition mod_gimli.t:20
complex(dp), dimension(:), allocatable v3
Definition mod_gimli.t:26
subroutine get_max_velocity(vmax)
Definition mod_gimli.t:304
subroutine init_gimli_indices()
Definition mod_gimli.t:109
subroutine split_extrapolate(ixil, ixol, w, x, w_index, equi_w, boundary)
Definition mod_gimli.t:442
complex(dp), dimension(:), allocatable b1
Definition mod_gimli.t:28
integer rho_idx
Definition mod_gimli.t:32
subroutine allocate_arrays(gridpts)
Definition mod_gimli.t:77
subroutine w_index_to_array(w_index, array)
Definition mod_gimli.t:129
complex(dp), dimension(:), allocatable b3
Definition mod_gimli.t:30
complex(dp), dimension(:), allocatable rho
Definition mod_gimli.t:23
complex(dp), dimension(:), allocatable v2
Definition mod_gimli.t:25
pure double precision function magnetic(w_vec, w_size)
Definition mod_gimli.t:254
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:67
integer, public, protected rho_
Whether plasma is partially ionized.
Definition mod_hd_phys.t:64
integer, public, protected p_
Index of the gas pressure (-1 if not present) should equal e_.
Definition mod_hd_phys.t:79
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_v), pointer phys_get_v
Definition mod_physics.t:69