MPI-AMRVAC  3.0
The MPI - Adaptive Mesh Refinement - Versatile Advection Code
mod_calculate_xw.t
Go to the documentation of this file.
1 !> Handles computations for coordinates and variables in output
3  implicit none
4 
5 contains
6 
7  !> Compute both corner as well as cell-centered values for output
8  subroutine calc_grid(qunit,igrid,xC,xCC,xC_TMP,xCC_TMP,wC_TMP,wCC_TMP,normconv,&
9  ixC^L,ixCC^L,first)
10  ! this subroutine computes both corner as well as cell-centered values
11  ! it handles how we do the center to corner averaging, as well as
12  ! whether we switch to cartesian or want primitive or conservative output,
13  ! handling the addition of B0 in B0+B1 cases, ...
14  !
15  ! the normconv is passed on to usr_aux_output for extending with
16  ! possible normalization values for the nw+1:nw+nwauxio entries
17 
20  use mod_limiter
22 
23  integer, intent(in) :: qunit, igrid
24  double precision, intent(in), dimension(ixMlo^D-1:ixMhi^D,ndim) :: xC
25  double precision, intent(in), dimension(ixMlo^D:ixMhi^D,ndim) :: xCC
26  integer :: ixC^L,ixCC^L
27  logical, intent(in) :: first
28 
29  double precision, dimension(ixMlo^D-1:ixMhi^D,ndim) :: xC_TMP
30  double precision, dimension(ixMlo^D:ixMhi^D,ndim) :: xCC_TMP
31  double precision, dimension(ixMlo^D-1:ixMhi^D,nw+nwauxio) :: wC_TMP
32  double precision, dimension(ixMlo^D:ixMhi^D,nw+nwauxio) :: wCC_TMP
33  double precision,dimension(0:nw+nwauxio),intent(out) :: normconv
34 
35  double precision :: ldw(ixG^T), dwC(ixG^T)
36  double precision, dimension(ixMlo^D-1:ixMhi^D,nw+nwauxio) :: wC
37  double precision, dimension(ixMlo^D:ixMhi^D,nw+nwauxio) :: wCC
38  double precision, dimension(ixG^T,1:nw+nwauxio) :: w
39  integer :: nxCC^D,idims,jxC^L,iwe
40  integer :: nx^D, nxC^D, ix^D, ix, iw, level, idir
41  logical, save :: subfirst=.true.
42 
43  ! initialize w
44  w=0.d0
45 
46  ixcmin^d=ixmlo^d-1; ixcmax^d=ixmhi^d; ! Corner indices
47  ixccmin^d=ixmlo^d; ixccmax^d=ixmhi^d; ! Center indices
48 
49  nx^d=ixmhi^d-ixmlo^d+1;
50  level=node(plevel_,igrid)
51 
52  normconv(0) = length_convert_factor
53  normconv(1:nw) = w_convert_factor
54  block=>ps(igrid)
55  w(ixg^t,1:nw)=ps(igrid)%w(ixg^t,1:nw)
56 
57  if (nwextra>0) then
58  ! here we actually fill the ghost layers for the nwextra variables using
59  ! continuous extrapolation (as these values do not exist normally in ghost cells)
60  do idims=1,ndim
61  select case(idims)
62  {case(^d)
63  jxcmin^dd=ixghi^d+1-nghostcells^d%jxCmin^dd=ixglo^dd;
64  jxcmax^dd=ixghi^dd;
65  do ix^d=jxcmin^d,jxcmax^d
66  w(ix^d^d%jxC^s,nw-nwextra+1:nw) = w(jxcmin^d-1^d%jxC^s,nw-nwextra+1:nw)
67  end do
68  jxcmin^dd=ixglo^dd;
69  jxcmax^dd=ixglo^d-1+nghostcells^d%jxCmax^dd=ixghi^dd;
70  do ix^d=jxcmin^d,jxcmax^d
71  w(ix^d^d%jxC^s,nw-nwextra+1:nw) = w(jxcmax^d+1^d%jxC^s,nw-nwextra+1:nw)
72  end do \}
73  end select
74  end do
75  end if
76 
77  ! next lines needed when usr_aux_output uses gradients
78  ! and later on when dwlimiter2 is used
79  ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
80  if(nwauxio>0)then
81  ! auxiliary io variables can be computed and added by user
82  ! next few lines ensure correct usage of routines like divvector etc
83  ! default (no) normalization for auxiliary variables
84  normconv(nw+1:nw+nwauxio)=one
85 
86  if (.not. associated(usr_aux_output)) then
87  call mpistop("usr_aux_output not defined")
88  else
89  call usr_aux_output(ixg^ll,ixm^ll^ladd1,w,ps(igrid)%x,normconv)
90  end if
91  endif
92 
93  ! In case primitives to be saved: use primitive subroutine
94  ! extra layer around mesh only needed when storing corner values and averaging
95  if(saveprim.and.first) call phys_to_primitive(ixg^ll,ixm^ll^ladd1,w(ixg^t,1:nw),ps(igrid)%x)
96 
97  if(b0field) then
98  ! B0+B1 split handled here
99  if(.not.saveprim.and.phys_energy) then
100  w(ixg^t,iw_e)=w(ixg^t,iw_e)+0.5d0*sum(ps(igrid)%B0(ixg^t,:,0)**2,dim=ndim+1) &
101  + sum(w(ixg^t,iw_mag(:))*ps(igrid)%B0(ixg^t,:,0),dim=ndim+1)
102  end if
103  w(ixg^t,iw_mag(:))=w(ixg^t,iw_mag(:))+ps(igrid)%B0(ixg^t,:,0)
104  end if
105  ! compute the cell-center values for w first
106  ! cell center values obtained from mere copy
107  wcc(ixcc^s,:)=w(ixcc^s,:)
108 
109  ! compute the corner values for w now by averaging
110 
111  if(slab_uniform) then
112  ! for slab symmetry: no geometrical info required
113  do iw=1,nw+nwauxio
114  {do ix^db=ixcmin^db,ixcmax^db\}
115  wc(ix^d,iw)=sum(w(ix^d:ix^d+1,iw))/dble(2**ndim)
116  {end do\}
117  end do
118  else
119  do iw=1,nw+nwauxio
120  {do ix^db=ixcmin^db,ixcmax^db\}
121  wc(ix^d,iw)=sum(w(ix^d:ix^d+1,iw)*ps(igrid)%dvolume(ix^d:ix^d+1)) &
122  /sum(ps(igrid)%dvolume(ix^d:ix^d+1))
123  {end do\}
124  end do
125  endif
126 
127  if(nocartesian) then
128  ! keep the coordinate and vector components
129  xc_tmp(ixc^s,1:ndim) = xc(ixc^s,1:ndim)
130  wc_tmp(ixc^s,1:nw+nwauxio) = wc(ixc^s,1:nw+nwauxio)
131  xcc_tmp(ixcc^s,1:ndim) = xcc(ixcc^s,1:ndim)
132  wcc_tmp(ixcc^s,1:nw+nwauxio) = wcc(ixcc^s,1:nw+nwauxio)
133  else
134  ! do all conversions to cartesian coordinates and vector components
135  ! start for the corner values
136  call to_cartesian(xc_tmp,wc_tmp,ixc^l,xc,wc)
137  ! then cell center values
138  call to_cartesian(xcc_tmp,wcc_tmp,ixcc^l,xcc,wcc)
139  endif
140 
141  ! Warning: differentiate between idl/idlCC/tecplot/tecplotCC/vtu(B)/vtu(B)CC
142  if(nwaux>0 .and. mype==0 .and. first.and.subfirst) then
143  ! when corner values are computed and auxiliaries present: warn!
144  if(convert_type=='idl'.or.convert_type=='tecplot' &
145  .or.convert_type=='vtu'.or.convert_type=='vtuB') &
146  write(*,*) 'Warning: also averaged auxiliaries within calc_grid'
147  subfirst=.false.
148  endif
149 
150  end subroutine calc_grid
151 
152  !> convert to cartesian coordinates and vector components
153  subroutine to_cartesian(x_TMP,w_TMP,ix^L,xC,wC)
154  ! conversion of coordinate and vector components from cylindrical/spherical
155  ! to cartesian coordinates and components done here
156  ! Also: nullifying values lower than smalldouble
158  use mod_geometry
159 
160  integer :: ix^L, ix^D, idim, iw, ivector, iw0
161  integer, dimension(nw) :: vectoriw
162  double precision :: x_TEC(ndim), w_TEC(nw+nwauxio)
163  double precision, dimension(ndim,ndim) :: normal
164 
165  double precision, dimension(ix^S,ndim) :: xC
166  double precision, dimension(ix^S,nw+nwauxio) :: wC
167 
168  double precision, dimension(ix^S,ndim) :: x_TMP
169  double precision, dimension(ix^S,nw+nwauxio) :: w_TMP
170 
171  iw0=0
172  vectoriw=-1
173  if(nvector>0) then
174  do ivector=1,nvector
175  do idim=1,ndim
176  vectoriw(iw_vector(ivector)+idim)=iw_vector(ivector)
177  end do
178  end do
179  endif
180  x_tec=0.d0
181  {do ix^db=ixmin^db,ixmax^db\}
182  select case (coordinate)
184  x_tec(1:ndim)=xc(ix^d,1:ndim)
185  w_tec(1:nw+nwauxio)=wc(ix^d,1:nw+nwauxio)
186  case (cylindrical)
187  {^ifoned
188  x_tec(1)=xc(ix^d,1)}
189  {^iftwod
190  select case (phi_)
191  case (2)
192  x_tec(1)=xc(ix^d,1)*cos(xc(ix^d,2))
193  x_tec(2)=xc(ix^d,1)*sin(xc(ix^d,2))
194  case default
195  x_tec(1)=xc(ix^d,1)
196  x_tec(2)=xc(ix^d,2)
197  end select}
198  {^ifthreed
199  x_tec(1)=xc(ix^d,1)*cos(xc(ix^d,phi_))
200  x_tec(2)=xc(ix^d,1)*sin(xc(ix^d,phi_))
201  x_tec(3)=xc(ix^d,z_)}
202 
203  if (nvector>0) then
204  {^ifoned normal(1,1)=one}
205 
206  {^iftwod
207  select case (phi_)
208  case (2)
209  normal(1,1)=cos(xc(ix^d,2))
210  normal(1,2)=-sin(xc(ix^d,2))
211  normal(2,1)=sin(xc(ix^d,2))
212  normal(2,2)=cos(xc(ix^d,2))
213  case default
214  normal(1,1)=one
215  normal(1,2)=zero
216  normal(2,1)=zero
217  normal(2,2)=one
218  end select}
219 
220  {^ifthreed
221  normal(1,1)=cos(xc(ix^d,phi_))
222  normal(1,phi_)=-sin(xc(ix^d,phi_))
223  normal(1,z_)=zero
224 
225  normal(2,1)=sin(xc(ix^d,phi_))
226  normal(2,phi_)=cos(xc(ix^d,phi_))
227  normal(2,z_)=zero
228 
229  normal(3,1)=zero
230  normal(3,phi_)=zero
231  normal(3,z_)=one}
232  end if
233  do iw=1,nw+nwauxio
234  if (iw<=nw) iw0=vectoriw(iw)
235  if (iw0>=0.and.iw<=iw0+ndim.and.iw<=nw) then
236  idim=iw-iw0
237  w_tec(iw0+idim)={^d&wc(ix^dd,iw0+^d)*normal(idim,^d)+}
238  else
239  w_tec(iw)=wc(ix^d,iw)
240  end if
241  end do
242  case (spherical)
243  x_tec(1)=xc(ix^d,1){^nooned*sin(xc(ix^d,2))}{^ifthreed*cos(xc(ix^d,3))}
244  {^iftwod
245  x_tec(2)=xc(ix^d,1)*cos(xc(ix^d,2))}
246  {^ifthreed
247  x_tec(2)=xc(ix^d,1)*sin(xc(ix^d,2))*sin(xc(ix^d,3))
248  x_tec(3)=xc(ix^d,1)*cos(xc(ix^d,2))}
249 
250  if (nvector>0) then
251  {^ifoned normal(1,1)=one}
252  {^nooned
253  normal(1,1)=sin(xc(ix^d,2)){^ifthreed*cos(xc(ix^d,3))}
254  normal(1,2)=cos(xc(ix^d,2)){^ifthreed*cos(xc(ix^d,3))
255  normal(1,3)=-sin(xc(ix^d,3))}}
256 
257  {^iftwod
258  normal(2,1)=cos(xc(ix^d,2))
259  normal(2,2)=-sin(xc(ix^d,2))}
260  {^ifthreed
261  normal(2,1)=sin(xc(ix^d,2))*sin(xc(ix^d,3))
262  normal(2,2)=cos(xc(ix^d,2))*sin(xc(ix^d,3))
263  normal(2,3)=cos(xc(ix^d,3))
264 
265  normal(3,1)=cos(xc(ix^d,2))
266  normal(3,2)=-sin(xc(ix^d,2))
267  normal(3,3)=zero}
268  end if
269  do iw=1,nw+nwauxio
270  if (iw<=nw) iw0=vectoriw(iw)
271  if (iw0>=0.and.iw<=iw0+ndim.and.iw<=nw) then
272  idim=iw-iw0
273  w_tec(iw0+idim)={^d&wc(ix^dd,iw0+^d)*normal(idim,^d)+}
274  else
275  w_tec(iw)=wc(ix^d,iw)
276  end if
277  end do
278  case default
279  write(*,*) "No converter for coordinate=",coordinate
280  end select
281  x_tmp(ix^d,1:ndim)=x_tec(1:ndim)
282  w_tmp(ix^d,1:nw+nwauxio)=w_tec(1:nw+nwauxio)
283  ! Be aware that small values are nullified here!!!
284  where(dabs(w_tmp(ix^d,1:nw+nwauxio))<smalldouble)
285  w_tmp(ix^d,1:nw+nwauxio)=zero
286  endwhere
287  {end do\}
288 
289  end subroutine to_cartesian
290 
291  !> get all variables names
292  subroutine getheadernames(wnamei,xandwnamei,outfilehead)
293  ! this collects all variables names in the wnamei character array, getting the info from
294  ! the prim_wnames/cons_wnames strings (depending on saveprim). It combines this info with names
295  ! for the dimensional directions in the xandwnamei array. In the outfilehead, it collects
296  ! the dimensional names, and only those names from the nw variables for output (through w_write)
297  ! together with the added names for nwauxio variables
300  use mod_geometry
301 
302  character(len=name_len) :: wnamei(1:nw+nwauxio),xandwnamei(1:ndim+nw+nwauxio)
303  character(len=1024) :: outfilehead
304 
305  integer:: space_position,iw,ind
306  character(len=name_len):: wname
307  character(len=std_len):: aux_variable_names
308  character(len=std_len):: scanstring
309 
310  logical, save:: first=.true.
311 
312  ! in case additional variables are computed and stored for output
313  if (nwauxio>0) then
314  if (.not. associated(usr_add_aux_names)) then
315  call mpistop("usr_add_aux_names not defined")
316  else
317  call usr_add_aux_names(aux_variable_names)
318  end if
319  end if
320 
321  ! --- part to provide variable names from prim_wnames/cons_wnames strings
322  if(saveprim) then
323  scanstring=trim(aux_variable_names)
324  wnamei(1:nw)=prim_wnames(1:nw)
325  else
326  scanstring=trim(aux_variable_names)
327  wnamei(1:nw)=cons_wnames(1:nw)
328  endif
329 
330  space_position=index(scanstring,' ')
331  do iw=nw+1,nw+nwauxio
332  do while (space_position==1)
333  scanstring=scanstring(2:)
334  space_position=index(scanstring,' ')
335  enddo
336  wname=scanstring(:space_position-1)
337  scanstring=scanstring(space_position+1:)
338  space_position=index(scanstring,' ')
339 
340  ! fill all names, even those that we will not write away from the first nw
341  wnamei(iw)=trim(wname)
342  enddo
343  ! --- end of part to provide variable names
344 
345  select case (coordinate)
346  case( spherical )
347  xandwnamei(1)="r";{^nooned xandwnamei(2)="Theta"};{^ifthreed xandwnamei(3)="Phi"}
348  case( cylindrical )
349  xandwnamei(1)="R";
350  {^nooned
351  if( phi_ == 2 )then
352  xandwnamei(2)="Phi"
353  else
354  xandwnamei(2)="Z"
355  endif}
356  {^ifthreed
357  if( phi_ == 2 )then
358  xandwnamei(3)="Z"
359  else
360  xandwnamei(3)="Phi"
361  endif}
362  case default
363  xandwnamei(1)="X";{^nooned xandwnamei(2)="Y"};{^ifthreed xandwnamei(3)="Z"}
364  end select
365 
366  xandwnamei(ndim+1:ndim+nw+nwauxio)=wnamei(1:nw+nwauxio)
367 
368  ! in outfilehead, collect the dimensional names, and all output variable names
369  ! first all dimensions
370  write(outfilehead,'(a)') trim(xandwnamei(1))
371  {^nooned
372  do iw=2,ndim
373  wname=xandwnamei(iw)
374  write(outfilehead,'(a)')outfilehead(1:len_trim(outfilehead))//" "//trim(wname)
375  enddo
376  }
377  ! then all nw variables, with w_write control for inclusion
378  do iw=ndim+1,ndim+nw
379  wname=xandwnamei(iw)
380  if(w_write(iw-ndim)) then
381  write(outfilehead,'(a)')outfilehead(1:len_trim(outfilehead))//" "//trim(wname)
382  endif
383  enddo
384  ! then all nwauxio variables
385  if(nwauxio>0) then
386  do iw=ndim+nw+1,ndim+nw+nwauxio
387  wname=xandwnamei(iw)
388  write(outfilehead,'(a)')outfilehead(1:len_trim(outfilehead))//" "//trim(wname)
389  enddo
390  endif
391 
392  if(first.and.mype==0)then
393  print*,'-------------------------------------------------------------------------------'
394  write(unitterm,*)'Saving visual data. Coordinate directions and variable names are:'
395  ind=0
396  do iw=1,ndim
397  ind=ind+1
398  print *,ind,xandwnamei(iw)
399  enddo
400  do iw=1+ndim,nw+ndim
401  if(w_write(iw-ndim)) then
402  ind=ind+1
403  write(*,*) ind,wnamei(iw-ndim)
404  end if
405  end do
406  do iw=ndim+nw+1,ndim+nw+nwauxio
407  ind=ind+1
408  print *,ind,wnamei(iw-ndim)
409  enddo
410  write(unitterm,*)'time =', global_time
411  print*,'-------------------------------------------------------------------------------'
412  first=.false.
413  endif
414 
415  end subroutine getheadernames
416 
417  !> computes cell corner (xC) and cell center (xCC) coordinates
418  subroutine calc_x(igrid,xC,xCC)
420 
421  integer, intent(in) :: igrid
422  double precision, intent(out) :: xC(ixMlo^D-1:ixMhi^D,ndim)
423  double precision, intent(out) :: xCC(ixMlo^D:ixMhi^D,ndim)
424 
425  integer :: ixC^L, idims, level, ix
426 
427  level=node(plevel_,igrid)
428 
429  ! coordinates of cell centers
430  xcc(ixm^t,:)=ps(igrid)%x(ixm^t,:)
431 
432  ! coordinates of cell corners
433  ixcmin^d=ixmlo^d-1; ixcmax^d=ixmhi^d;
434  if(slab_uniform)then
435  do idims=1,ndim
436  xc(ixc^s,idims)=ps(igrid)%x(ixc^s,idims)+0.5d0*dx(idims,level)
437  end do
438  else
439  ! for any non-cartesian or stretched coordinate (allow multiple stretched directions)
440  {do ix=ixcmin^d,ixcmax^d
441  xc(ix^d%ixC^s,^d)=ps(igrid)%x(ix^d%ixC^s,^d)+0.5d0*ps(igrid)%dx(ix^d%ixC^s,^d)
442  end do\}
443  endif
444 
445  end subroutine calc_x
446 
447 end module mod_calculate_xw
subroutine mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: comm_lib.t:194
Handles computations for coordinates and variables in output.
subroutine calc_grid(qunit, igrid, xC, xCC, xC_TMP, xCC_TMP, wC_TMP, wCC_TMP, normconv, ixCL, ixCCL, first)
Compute both corner as well as cell-centered values for output.
subroutine getheadernames(wnamei, xandwnamei, outfilehead)
get all variables names
subroutine calc_x(igrid, xC, xCC)
computes cell corner (xC) and cell center (xCC) coordinates
subroutine to_cartesian(x_TMP, w_TMP, ixL, xC, wC)
convert to cartesian coordinates and vector components
Module with geometry-related routines (e.g., divergence, curl)
Definition: mod_geometry.t:2
integer coordinate
Definition: mod_geometry.t:6
integer, parameter spherical
Definition: mod_geometry.t:10
integer, parameter cartesian
Definition: mod_geometry.t:7
integer, parameter cylindrical
Definition: mod_geometry.t:9
integer, parameter cartesian_expansion
Definition: mod_geometry.t:11
integer, parameter cartesian_stretched
Definition: mod_geometry.t:8
This module contains definitions of global parameters and variables and some generic functions/subrou...
double precision, dimension(:), allocatable w_convert_factor
Conversion factors the primitive variables.
type(state), pointer block
Block pointer for using one block and its previous state.
integer ixghi
Upper index of grid block arrays.
double precision global_time
The global simulation time.
logical saveprim
If true, convert from conservative to primitive variables in output.
integer, parameter ndim
Number of spatial dimensions for grid variables.
integer mype
The rank of the current MPI task.
integer, parameter plevel_
double precision length_convert_factor
integer ixm
the mesh range (within a block with ghost cells)
integer nwauxio
Number of auxiliary variables that are only included in output.
integer, parameter unitterm
Unit for standard output.
logical, dimension(:), allocatable w_write
logical b0field
split magnetic field as background B0 field
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
double precision, dimension(:,:), allocatable dx
integer nghostcells
Number of ghost cells surrounding a grid.
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
integer, dimension(:,:), allocatable node
double precision, dimension(ndim) dxlevel
integer, parameter ixglo
Lower index of grid block arrays (always 1)
Module with slope/flux limiters.
Definition: mod_limiter.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_convert), pointer phys_to_primitive
Definition: mod_physics.t:59
character(len=name_len) physics_type
String describing the physics type of the simulation.
Definition: mod_physics.t:19
logical phys_energy
Solve energy equation or not.
Definition: mod_physics.t:30
Module with all the methods that users can customize in AMRVAC.
procedure(aux_output), pointer usr_aux_output
procedure(add_aux_names), pointer usr_add_aux_names