MPI-AMRVAC  3.0
The MPI - Adaptive Mesh Refinement - Versatile Advection Code
amr_solution_node.t
Go to the documentation of this file.
1 !> Get first available igrid on processor ipe
2 integer function getnode(ipe)
3  use mod_forest, only: igrid_inuse
5 
6  integer, intent(in) :: ipe
7  integer :: igrid, igrid_available
8 
9  igrid_available=0
10 
11  do igrid=1,max_blocks
12  if (igrid_inuse(igrid,ipe)) cycle
13 
14  igrid_available=igrid
15  exit
16  end do
17 
18  if (igrid_available == 0) then
19  getnode = -1
20  print *, "Current maximum number of grid blocks:", max_blocks
21  call mpistop("Insufficient grid blocks; increase max_blocks in meshlist")
22  else
23  getnode=igrid_available
24  igrid_inuse(igrid,ipe)=.true.
25  end if
26 
27  if (ipe==mype) then
28  ! initialize nodal block
29  node(1:nodehi,getnode) = 0
30  rnode(1:rnodehi,getnode) = zero
31  end if
32 
33 end function getnode
34 
35 ! put igrid on processor ipe to be not in use
36 subroutine putnode(igrid,ipe)
37  use mod_forest
38  implicit none
39 
40  integer, intent(in) :: igrid, ipe
41 
42  igrid_inuse(igrid,ipe)=.false.
43 
44 end subroutine putnode
45 
46 !> allocate arrays on igrid node
47 subroutine alloc_node(igrid)
48  use mod_forest
50  use mod_geometry
53 
54  integer, intent(in) :: igrid
55 
56  integer :: level, ig^D, ign^D, ixCoG^L, ix, i^D
57  integer :: imin, imax, index, igCo^D, ixshift, offset, ifirst
58  integer :: icase, ixGext^L
59  double precision :: dx^D, summeddx, sizeuniformpart^D
60  double precision :: xext(ixGlo^D-1:ixGhi^D+1,1:ndim)
61  double precision :: delx_ext(ixGlo1-1:ixGhi1+1)
62  double precision :: exp_factor_ext(ixGlo1-1:ixGhi1+1),del_exp_factor_ext(ixGlo1-1:ixGhi1+1),exp_factor_primitive_ext(ixGlo1-1:ixGhi1+1)
63  double precision :: xc(ixGlo1:ixGhi1),delxc(ixGlo1:ixGhi1)
64  double precision :: exp_factor_coarse(ixGlo1:ixGhi1),del_exp_factor_coarse(ixGlo1:ixGhi1),exp_factor_primitive_coarse(ixGlo1:ixGhi1)
65 
66  ixcogmin^d=1;
67  ixcogmax^d=(ixghi^d-2*nghostcells)/2+2*nghostcells;
68 
69  icase=mod(nghostcells,2)
70  if(stagger_grid) icase=1
71  select case(icase)
72  case(0)
73  ixgext^l=ixg^ll;
74  case(1)
75  ! for ghost cell related prolongations, we need
76  ! an extra layer with known volumes and dx-intervals
77  ! in case the number of ghost cells is odd
78  ixgext^l=ixg^ll^ladd1;
79  case default
80  call mpistop("no such case")
81  end select
82 
83  ! set level information
84  level=igrid_to_node(igrid,mype)%node%level
85 
86  if(.not. allocated(ps(igrid)%w)) then
87 
88  ! allocate arrays for solution and space
89  call alloc_state(igrid, ps(igrid), ixg^ll, ixgext^l, .true.)
90  ! allocate arrays for one level coarser solution
91  call alloc_state_coarse(igrid, psc(igrid), ixcog^l, ixcog^l)
92  if(.not.convert) then
93  ! allocate arrays for old solution
94  call alloc_state(igrid, pso(igrid), ixg^ll, ixgext^l, .false.)
95  ! allocate arrays for temp solution 1
96  call alloc_state(igrid, ps1(igrid), ixg^ll, ixgext^l, .false.)
97 
98  ! allocate temporary solution space
99  select case (t_integrator)
101  call alloc_state(igrid, ps2(igrid), ixg^ll, ixgext^l, .false.)
102  case(rk3_bt,rk4,ssprk5,imex_cb3a)
103  call alloc_state(igrid, ps2(igrid), ixg^ll, ixgext^l, .false.)
104  call alloc_state(igrid, ps3(igrid), ixg^ll, ixgext^l, .false.)
105  case(imex_ars3,imex_232)
106  call alloc_state(igrid, ps2(igrid), ixg^ll, ixgext^l, .false.)
107  call alloc_state(igrid, ps3(igrid), ixg^ll, ixgext^l, .false.)
108  call alloc_state(igrid, ps4(igrid), ixg^ll, ixgext^l, .false.)
109  end select
110  end if
111 
112  end if
113 
114  ! avoid dividing by zero rho in skipped corner ghostcells when phys_req_diagonal=F
115  ps(igrid)%w(:^d&,1)=1.d0
116  ps(igrid)%level=level
117  psc(igrid)%level=level-1
118  ! avoid dividing by zero rho in skipped corner ghostcells when phys_req_diagonal=F
119  psc(igrid)%w(:^d&,1)=1.d0
120  if(phys_trac) ps(igrid)%special_values=0.d0
121  if(.not.convert) then
122  pso(igrid)%level=level
123  ps1(igrid)%level=level
124  select case (t_integrator)
126  ps2(igrid)%level=level
127  case(rk3_bt,rk4,ssprk5,imex_cb3a)
128  ps2(igrid)%level=level
129  ps3(igrid)%level=level
130  case(imex_ars3,imex_232)
131  ps2(igrid)%level=level
132  ps3(igrid)%level=level
133  ps4(igrid)%level=level
134  end select
135  end if
136 
137  ! block pointer to current block
138  block=>ps(igrid)
139 
140  ig^d=igrid_to_node(igrid,mype)%node%ig^d;
141 
142  node(plevel_,igrid)=level
143  ^d&node(pig^d_,igrid)=ig^d\
144 
145  ! set dx information
146  ^d&rnode(rpdx^d_,igrid)=dx(^d,level)\
147  dxlevel(:)=dx(:,level)
148 
149  ! uniform cartesian case as well as all unstretched coordinates
150  ! determine the minimal and maximal corners
151  ^d&rnode(rpxmin^d_,igrid)=xprobmin^d+dble(ig^d-1)*dg^d(level)\
152  ^d&rnode(rpxmax^d_,igrid)=xprobmin^d+dble(ig^d)*dg^d(level)\
153  {if(rnode(rpxmax^d_,igrid)>xprobmax^d) rnode(rpxmax^d_,igrid)=xprobmax^d\}
154 
155  ^d&dx^d=rnode(rpdx^d_,igrid)\
156  {do ix=ixglo^d,ixmhi^d-nghostcells
157  ps(igrid)%x(ix^d%ixG^t,^d)=rnode(rpxmin^d_,igrid)+(dble(ix-nghostcells)-half)*dx^d
158  end do\}
159  ! update overlap cells of neighboring blocks in the same way to get the same values
160  {do ix=ixmhi^d-nghostcells+1,ixghi^d
161  ps(igrid)%x(ix^d%ixG^t,^d)=rnode(rpxmax^d_,igrid)+(dble(ix-ixmhi^d)-half)*dx^d
162  end do\}
163 
164  ^d&dx^d=2.0d0*rnode(rpdx^d_,igrid)\
165  {do ix=ixcogmin^d,ixcogmax^d
166  psc(igrid)%x(ix^d%ixCoG^s,^d)=rnode(rpxmin^d_,igrid)+(dble(ix-nghostcells)-half)*dx^d
167  end do\}
168 
169  ^d&ps(igrid)%dx(ixgext^s,^d)=rnode(rpdx^d_,igrid);
170  ^d&psc(igrid)%dx(ixcog^s,^d)=2.0d0*rnode(rpdx^d_,igrid);
171  ^d&dx^d=rnode(rpdx^d_,igrid)\
172  {do ix=ixgextmin^d,ixgextmax^d
173  xext(ix^d%ixGext^s,^d)=rnode(rpxmin^d_,igrid)+(dble(ix-nghostcells)-half)*dx^d
174  end do\}
175 
176  if(any(stretched_dim)) then
177  {if(stretch_type(^d) == stretch_uni)then
178  imin=(ig^d-1)*block_nx^d
179  imax=ig^d*block_nx^d
180  rnode(rpxmin^d_,igrid)=xprobmin^d+dxfirst_1mq(level,^d) &
181  *(1.0d0-qstretch(level,^d)**imin)
182  rnode(rpxmax^d_,igrid)=xprobmin^d+dxfirst_1mq(level,^d) &
183  *(1.0d0-qstretch(level,^d)**imax)
184  ! fix possible out of bound due to precision
185  if(rnode(rpxmax^d_,igrid)>xprobmax^d) rnode(rpxmax^d_,igrid)=xprobmax^d
186  ixshift=(ig^d-1)*block_nx^d-nghostcells
187  do ix=ixgextmin^d,ixgextmax^d
188  index=ixshift+ix
189  ps(igrid)%dx(ix^d%ixGext^s,^d)=dxfirst(level,^d)*qstretch(level,^d)**(index-1)
190  enddo
191  igco^d=(ig^d-1)/2
192  ixshift=igco^d*block_nx^d+(1-modulo(ig^d,2))*block_nx^d/2-nghostcells
193  do ix=ixcogmin^d,ixcogmax^d
194  index=ixshift+ix
195  psc(igrid)%dx(ix^d%ixCoG^s,^d)=dxfirst(level-1,^d)*qstretch(level-1,^d)**(index-1)
196  psc(igrid)%x(ix^d%ixCoG^s,^d)=xprobmin^d+dxfirst_1mq(level-1,^d)&
197  *(1.0d0-qstretch(level-1,^d)**(index-1))&
198  + 0.5d0*dxfirst(level-1,^d)*qstretch(level-1,^d)**(index-1)
199  end do
200  ! now that dx and grid boundaries are known: fill cell centers
201  ifirst=nghostcells+1
202  ! first fill the mesh
203  summeddx=0.0d0
204  do ix=ixmlo^d,ixmhi^d
205  ps(igrid)%x(ix^d%ixG^t,^d)=rnode(rpxmin^d_,igrid)+summeddx+0.5d0*ps(igrid)%dx(ix^d%ixG^t,^d)
206  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
207  enddo
208  ! then ghost cells to left
209  summeddx=0.0d0
210  do ix=nghostcells,1,-1
211  ps(igrid)%x(ix^d%ixG^t,^d)=rnode(rpxmin^d_,igrid)-summeddx-0.5d0*ps(igrid)%dx(ix^d%ixG^t,^d)
212  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
213  enddo
214  ! then ghost cells to right
215  summeddx=0.0d0
216  do ix=ixghi^d-nghostcells+1,ixghi^d
217  ps(igrid)%x(ix^d%ixG^t,^d)=rnode(rpxmax^d_,igrid)+summeddx+0.5d0*ps(igrid)%dx(ix^d%ixG^t,^d)
218  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
219  enddo
220  select case(icase)
221  case(0)
222  ! if even number of ghost cells: xext is just copy of local x
223  xext(ixgext^s,^d)=ps(igrid)%x(ixgext^s,^d)
224  case(1)
225  ! if uneven number of ghost cells: extra layer left/right
226  summeddx=0.0d0
227  do ix=ixmlo^d,ixmhi^d
228  xext(ix^d%ixGext^s,^d)=rnode(rpxmin^d_,igrid)+summeddx+0.5d0*ps(igrid)%dx(ix^d%ixGext^s,^d)
229  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
230  enddo
231  ! then ghost cells to left
232  summeddx=0.0d0
233  do ix=nghostcells,ixgextmin^d,-1
234  xext(ix^d%ixGext^s,^d)=rnode(rpxmin^d_,igrid)-summeddx-0.5d0*ps(igrid)%dx(ix^d%ixGext^s,^d)
235  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
236  enddo
237  ! then ghost cells to right
238  summeddx=0.0d0
239  do ix=ixghi^d-nghostcells+1,ixgextmax^d
240  xext(ix^d%ixGext^s,^d)=rnode(rpxmax^d_,igrid)+summeddx+0.5d0*ps(igrid)%dx(ix^d%ixGext^s,^d)
241  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
242  enddo
243  case default
244  call mpistop("no such case")
245  end select
246  endif\}
247  {if(stretch_type(^d) == stretch_symm)then
248  ! here we distinguish three kinds of grid blocks
249  ! depending on their ig-index, set per level
250  ! the first n_stretchedblocks/2 will stretch to the left
251  ! the middle ntotal-n_stretchedblocks will be uniform
252  ! the last n_stretchedblocks/2 will stretch to the right
253  if(ig^d<=nstretchedblocks(level,^d)/2)then
254  ! stretch to the left
255  offset=block_nx^d*nstretchedblocks(level,^d)/2
256  imin=(ig^d-1)*block_nx^d
257  imax=ig^d*block_nx^d
258  rnode(rpxmin^d_,igrid)=xprobmin^d+xstretch^d-dxfirst_1mq(level,^d) &
259  *(1.0d0-qstretch(level,^d)**(offset-imin))
260  rnode(rpxmax^d_,igrid)=xprobmin^d+xstretch^d-dxfirst_1mq(level,^d) &
261  *(1.0d0-qstretch(level,^d)**(offset-imax))
262  ! fix possible out of bound due to precision
263  if(rnode(rpxmin^d_,igrid)<xprobmin^d) rnode(rpxmin^d_,igrid)=xprobmin^d
264  ixshift=(ig^d-1)*block_nx^d-nghostcells
265  do ix=ixgextmin^d,ixgextmax^d
266  index=ixshift+ix
267  ps(igrid)%dx(ix^d%ixGext^s,^d)=dxfirst(level,^d)*qstretch(level,^d)**(offset-index)
268  enddo
269  ixshift=(nstretchedblocks(level,^d)/2-ig^d)*(block_nx^d/2)+block_nx^d/2+nghostcells
270  do ix=ixcogmin^d,ixcogmax^d
271  index=ixshift-ix
272  psc(igrid)%dx(ix^d%ixCoG^s,^d)=dxfirst(level-1,^d)*qstretch(level-1,^d)**index
273  enddo
274  ! last block: to modify ghost cells!!!
275  if(ig^d==nstretchedblocks(level,^d)/2)then
276  if(ng^d(level)==nstretchedblocks(level,^d))then
277  ! if middle blocks do not exist then use symmetry
278  do ix=ixghi^d-nghostcells+1,ixgextmax^d
279  ps(igrid)%dx(ix^d%ixGext^s,^d)= &
280  ps(igrid)%dx(2*(ixghi^d-nghostcells)+1-ix^d%ixGext^s,^d)
281  enddo
282  do ix=ixcogmax^d-nghostcells+1,ixcogmax^d
283  psc(igrid)%dx(ix^d%ixCoG^s,^d)= &
284  psc(igrid)%dx(2*(ixcogmax^d-nghostcells)+1-ix^d%ixCoG^s,^d)
285  enddo
286  else
287  ! if middle blocks exist then use same as middle blocks:
288  do ix=ixghi^d-nghostcells+1,ixgextmax^d
289  ps(igrid)%dx(ix^d%ixGext^s,^d)=dxmid(level,^d)
290  enddo
291  do ix=ixcogmax^d-nghostcells+1,ixcogmax^d
292  psc(igrid)%dx(ix^d%ixCoG^s,^d)=dxmid(level-1,^d)
293  enddo
294  endif
295  endif
296  ! first block: make ghost cells symmetric (to allow periodicity)
297  if(ig^d==1)then
298  do ix=ixgextmin^d,nghostcells
299  ps(igrid)%dx(ix^d%ixGext^s,^d)=ps(igrid)%dx(2*nghostcells+1-ix^d%ixGext^s,^d)
300  enddo
301  do ix=1,nghostcells
302  psc(igrid)%dx(ix^d%ixCoG^s,^d)=psc(igrid)%dx(2*nghostcells+1-ix^d%ixCoG^s,^d)
303  enddo
304  endif
305  else
306  if(ig^d<=ng^d(level)-nstretchedblocks(level,^d)/2) then
307  ! keep uniform
308  ps(igrid)%dx(ixgext^s,^d)=dxmid(level,^d)
309  psc(igrid)%dx(ixcog^s,^d)=dxmid(level-1,^d)
310  rnode(rpxmin^d_,igrid)=xprobmin^d+xstretch^d+(ig^d-nstretchedblocks(level,^d)/2-1)*block_nx^d*dxmid(level,^d)
311  rnode(rpxmax^d_,igrid)=xprobmin^d+xstretch^d+(ig^d-nstretchedblocks(level,^d)/2) *block_nx^d*dxmid(level,^d)
312  ! first and last block: to modify the ghost cells!!!
313  if(ig^d==nstretchedblocks(level,^d)/2+1)then
314  do ix=ixgextmin^d,nghostcells
315  ps(igrid)%dx(ix^d%ixGext^s,^d)=dxfirst(level,^d)*qstretch(level,^d)**(nghostcells-ix)
316  enddo
317  do ix=1,nghostcells
318  psc(igrid)%dx(ix^d%ixCoG^s,^d)=dxfirst(level-1,^d)*qstretch(level-1,^d)**(nghostcells-ix)
319  enddo
320  endif
321  if(ig^d==ng^d(level)-nstretchedblocks(level,^d))then
322  do ix=ixghi^d-nghostcells+1,ixgextmax^d
323  ps(igrid)%dx(ix^d%ixGext^s,^d)=dxfirst(level,^d)*qstretch(level,^d)**(ix-block_nx^d-nghostcells-1)
324  enddo
325  do ix=ixcogmax^d-nghostcells+1,ixcogmax^d
326  psc(igrid)%dx(ix^d%ixCoG^s,^d)=dxfirst(level-1,^d)*qstretch(level-1,^d)**(ix-ixcogmax^d+nghostcells-1)
327  enddo
328  endif
329  else
330  ! stretch to the right
331  offset=block_nx^d*(ng^d(level)-nstretchedblocks(level,^d)/2)
332  sizeuniformpart^d=dxmid(1,^d)*(domain_nx^d-nstretchedblocks_baselevel(^d)*block_nx^d)
333  imin=(ig^d-1)*block_nx^d-offset
334  imax=ig^d*block_nx^d-offset
335  rnode(rpxmin^d_,igrid)=xprobmin^d+xstretch^d+sizeuniformpart^d+dxfirst_1mq(level,^d) &
336  *(1.0d0-qstretch(level,^d)**imin)
337  rnode(rpxmax^d_,igrid)=xprobmin^d+xstretch^d+sizeuniformpart^d+dxfirst_1mq(level,^d) &
338  *(1.0d0-qstretch(level,^d)**imax)
339  ! fix possible out of bound due to precision
340  if(rnode(rpxmax^d_,igrid)>xprobmax^d) rnode(rpxmax^d_,igrid)=xprobmax^d
341  ixshift=(ig^d-1)*block_nx^d-nghostcells-offset
342  do ix=ixgextmin^d,ixgextmax^d
343  index=ixshift+ix
344  ps(igrid)%dx(ix^d%ixGext^s,^d)=dxfirst(level,^d)*qstretch(level,^d)**(index-1)
345  enddo
346  ixshift=(ig^d+nstretchedblocks(level,^d)/2-ng^d(level)-1)*(block_nx^d/2)-nghostcells
347  do ix=ixcogmin^d,ixcogmax^d
348  index=ixshift+ix
349  psc(igrid)%dx(ix^d%ixCoG^s,^d)=dxfirst(level-1,^d)*qstretch(level-1,^d)**(index-1)
350  enddo
351  ! first block: modify ghost cells!!!
352  if(ig^d==ng^d(level)-nstretchedblocks(level,^d)+1)then
353  if(ng^d(level)==nstretchedblocks(level,^d))then
354  ! if middle blocks do not exist then use symmetry
355  do ix=ixgextmin^d,nghostcells
356  ps(igrid)%dx(ix^d%ixGext^s,^d)=ps(igrid)%dx(2*nghostcells+1-ix^d%ixGext^s,^d)
357  enddo
358  do ix=1,nghostcells
359  psc(igrid)%dx(ix^d%ixCoG^s,^d)=psc(igrid)%dx(2*nghostcells+1-ix^d%ixCoG^s,^d)
360  enddo
361  else
362  ! if middle blocks exist then use same as middle blocks:
363  do ix=ixgextmin^d,nghostcells
364  ps(igrid)%dx(ix^d%ixGext^s,^d)=dxmid(level,^d)
365  enddo
366  do ix=1,nghostcells
367  psc(igrid)%dx(ix^d%ixCoG^s,^d)=dxmid(level-1,^d)
368  enddo
369  endif
370  endif
371  ! last block: make ghost cells symmetric (to allow periodicity)
372  if(ig^d==ng^d(level))then
373  do ix=ixghi^d-nghostcells+1,ixgextmax^d
374  ps(igrid)%dx(ix^d%ixGext^s,^d)=ps(igrid)%dx(2*(ixghi^d-nghostcells)+1-ix^d%ixGext^s,^d)
375  enddo
376  do ix=ixcogmax^d-nghostcells+1,ixcogmax^d
377  psc(igrid)%dx(ix^d%ixCoG^s,^d)=psc(igrid)%dx(2*(ixcogmax^d-nghostcells)+1-ix^d%ixCoG^s,^d)
378  enddo
379  endif
380  endif
381  endif
382  ! now that dx and grid boundaries are known: fill cell centers
383  ifirst=nghostcells+1
384  ! first fill the mesh
385  summeddx=0.0d0
386  do ix=ixmlo^d,ixmhi^d
387  ps(igrid)%x(ix^d%ixG^t,^d)=rnode(rpxmin^d_,igrid)+summeddx+0.5d0*ps(igrid)%dx(ix^d%ixG^t,^d)
388  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
389  enddo
390  ! then ghost cells to left
391  summeddx=0.0d0
392  do ix=nghostcells,1,-1
393  ps(igrid)%x(ix^d%ixG^t,^d)=rnode(rpxmin^d_,igrid)-summeddx-0.5d0*ps(igrid)%dx(ix^d%ixG^t,^d)
394  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
395  enddo
396  ! then ghost cells to right
397  summeddx=0.0d0
398  do ix=ixghi^d-nghostcells+1,ixghi^d
399  ps(igrid)%x(ix^d%ixG^t,^d)=rnode(rpxmax^d_,igrid)+summeddx+0.5d0*ps(igrid)%dx(ix^d%ixG^t,^d)
400  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
401  enddo
402  ! and next for the coarse representation
403  ! first fill the mesh
404  summeddx=0.0d0
405  do ix=nghostcells+1,ixcogmax^d-nghostcells
406  psc(igrid)%x(ix^d%ixCoG^s,^d)=rnode(rpxmin^d_,igrid)+summeddx+0.5d0*psc(igrid)%dx(ix^d%ixCoG^s,^d)
407  summeddx=summeddx+psc(igrid)%dx(ix^d%ifirst,^d)
408  enddo
409  ! then ghost cells to left
410  summeddx=0.0d0
411  do ix=nghostcells,1,-1
412  psc(igrid)%x(ix^d%ixCoG^s,^d)=rnode(rpxmin^d_,igrid)-summeddx-0.5d0*psc(igrid)%dx(ix^d%ixCoG^s,^d)
413  summeddx=summeddx+psc(igrid)%dx(ix^d%ifirst,^d)
414  enddo
415  ! then ghost cells to right
416  summeddx=0.0d0
417  do ix=ixcogmax^d-nghostcells+1,ixcogmax^d
418  psc(igrid)%x(ix^d%ixCoG^s,^d)=rnode(rpxmax^d_,igrid)+summeddx+0.5d0*psc(igrid)%dx(ix^d%ixCoG^s,^d)
419  summeddx=summeddx+psc(igrid)%dx(ix^d%ifirst,^d)
420  enddo
421  select case(icase)
422  case(0)
423  ! if even number of ghost cells: xext is just copy of local x
424  xext(ixgext^s,^d)=ps(igrid)%x(ixgext^s,^d)
425  case(1)
426  ! if uneven number of ghost cells: extra layer left/right
427  summeddx=0.0d0
428  do ix=ixmlo^d,ixmhi^d
429  xext(ix^d%ixGext^s,^d)=rnode(rpxmin^d_,igrid)+summeddx+0.5d0*ps(igrid)%dx(ix^d%ixGext^s,^d)
430  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
431  enddo
432  ! then ghost cells to left
433  summeddx=0.0d0
434  do ix=nghostcells,ixgextmin^d,-1
435  xext(ix^d%ixGext^s,^d)=rnode(rpxmin^d_,igrid)-summeddx-0.5d0*ps(igrid)%dx(ix^d%ixGext^s,^d)
436  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
437  enddo
438  ! then ghost cells to right
439  summeddx=0.0d0
440  do ix=ixghi^d-nghostcells+1,ixgextmax^d
441  xext(ix^d%ixGext^s,^d)=rnode(rpxmax^d_,igrid)+summeddx+0.5d0*ps(igrid)%dx(ix^d%ixGext^s,^d)
442  summeddx=summeddx+ps(igrid)%dx(ix^d%ifirst,^d)
443  enddo
444  case default
445  call mpistop("no such case")
446  end select
447  endif\}
448  endif
449 
450  ! calculate area of cell surfaces for standard block
451  call get_surface_area(ps(igrid),ixg^ll)
452  ! calculate area of cell surfaces for coarser representative block
453  call get_surface_area(psc(igrid),ixcog^l)
454  ! calculate volume and distance of cells
455  ps(igrid)%dsC=1.d0
456  select case (coordinate)
457  case (cartesian)
458  ps(igrid)%dvolume(ixgext^s)= {^d&rnode(rpdx^d_,igrid)|*}
459  ps(igrid)%ds(ixgext^s,1:ndim)=ps(igrid)%dx(ixgext^s,1:ndim)
460  ps(igrid)%dsC(ixgext^s,1:ndim)=ps(igrid)%dx(ixgext^s,1:ndim)
461  psc(igrid)%dvolume(ixcog^s)= {^d&2.d0*rnode(rpdx^d_,igrid)|*}
462  psc(igrid)%ds(ixcog^s,1:ndim)=psc(igrid)%dx(ixcog^s,1:ndim)
463  case (cartesian_stretched)
464  ps(igrid)%dvolume(ixgext^s)= {^d&ps(igrid)%dx(ixgext^s,^d)|*}
465  ps(igrid)%ds(ixgext^s,1:ndim)=ps(igrid)%dx(ixgext^s,1:ndim)
466  ps(igrid)%dsC(ixgext^s,1:ndim)=ps(igrid)%dx(ixgext^s,1:ndim)
467  psc(igrid)%dvolume(ixcog^s)= {^d&psc(igrid)%dx(ixcog^s,^d)|*}
468  psc(igrid)%ds(ixcog^s,1:ndim)=psc(igrid)%dx(ixcog^s,1:ndim)
469  case (cartesian_expansion)
470  {^ifoned
471  delx_ext(ixgext^s) = ps(igrid)%dx(ixgext^s,1)
472  if(associated(usr_set_surface)) call usr_set_surface(ixgext^l,xext(ixgext^s,1),delx_ext(ixgext^s),exp_factor_ext(ixgext^s),del_exp_factor_ext(ixgext^s),exp_factor_primitive_ext(ixgext^s))
473  ps(igrid)%dvolume(ixgext^s)= exp_factor_primitive_ext(ixgext^s)
474  ps(igrid)%ds(ixgext^s,1)=ps(igrid)%dx(ixgext^s,1)
475  ps(igrid)%dsC(ixgext^s,1)=ps(igrid)%dx(ixgext^s,1)
476  xc(ixcog^s) = psc(igrid)%x(ixcog^s,1)
477  delxc(ixcog^s) = psc(igrid)%dx(ixcog^s,1)
478  if(associated(usr_set_surface)) call usr_set_surface(ixcog^l,xc(ixcog^s),delxc(ixcog^s),exp_factor_coarse(ixcog^s),del_exp_factor_coarse(ixcog^s),exp_factor_primitive_coarse(ixcog^s))
479  psc(igrid)%dvolume(ixcog^s)= exp_factor_primitive_coarse(ixcog^s)
480  psc(igrid)%ds(ixcog^s,1)=psc(igrid)%dx(ixcog^s,1)
481  }
482  case (spherical)
483  ps(igrid)%dvolume(ixgext^s)=(xext(ixgext^s,1)**2 &
484  +ps(igrid)%dx(ixgext^s,1)**2/12.0d0)*&
485  ps(igrid)%dx(ixgext^s,1){^nooned &
486  *two*dabs(dsin(xext(ixgext^s,2))) &
487  *dsin(half*ps(igrid)%dx(ixgext^s,2))}{^ifthreed*ps(igrid)%dx(ixgext^s,3)}
488  psc(igrid)%dvolume(ixcog^s)=(psc(igrid)%x(ixcog^s,1)**2 &
489  +psc(igrid)%dx(ixcog^s,1)**2/12.0d0)*&
490  psc(igrid)%dx(ixcog^s,1){^nooned &
491  *two*dabs(dsin(psc(igrid)%x(ixcog^s,2))) &
492  *dsin(half*psc(igrid)%dx(ixcog^s,2))}{^ifthreed*psc(igrid)%dx(ixcog^s,3)}
493  ps(igrid)%ds(ixgext^s,1)=ps(igrid)%dx(ixgext^s,1)
494  {^nooned ps(igrid)%ds(ixgext^s,2)=xext(ixgext^s,1)*ps(igrid)%dx(ixgext^s,2)}
495  {^ifthreed ps(igrid)%ds(ixgext^s,3)=xext(ixgext^s,1)*dsin(xext(ixgext^s,2))*&
496  ps(igrid)%dx(ixgext^s,3)}
497  ps(igrid)%dsC(ixgext^s,1)=ps(igrid)%dx(ixgext^s,1)
498  {^nooned ps(igrid)%dsC(ixgext^s,2)=(xext(ixgext^s,1)+half*ps(igrid)%dx(ixgext^s,1))*&
499  ps(igrid)%dx(ixgext^s,2)
500  if(ndir>ndim) then
501  ps(igrid)%dsC(ixgext^s,3)=(xext(ixgext^s,1)+half*ps(igrid)%dx(ixgext^s,1))*&
502  dsin(xext(ixgext^s,2)+half*ps(igrid)%dx(ixgext^s,2))
503  end if
504  }
505  {^ifthreed ps(igrid)%dsC(ixgext^s,3)=(xext(ixgext^s,1)+half*ps(igrid)%dx(ixgext^s,1))*&
506  dsin(xext(ixgext^s,2)+half*ps(igrid)%dx(ixgext^s,2))*&
507  ps(igrid)%dx(ixgext^s,3)}
508  case (cylindrical)
509  ps(igrid)%dvolume(ixgext^s)=dabs(xext(ixgext^s,1)) &
510  *ps(igrid)%dx(ixgext^s,1){^de&*ps(igrid)%dx(ixgext^s,^de) }
511  psc(igrid)%dvolume(ixcog^s)=dabs(psc(igrid)%x(ixcog^s,1)) &
512  *psc(igrid)%dx(ixcog^s,1){^de&*psc(igrid)%dx(ixcog^s,^de) }
513  ps(igrid)%ds(ixgext^s,r_)=ps(igrid)%dx(ixgext^s,r_)
514  ps(igrid)%dsC(ixgext^s,r_)=ps(igrid)%dx(ixgext^s,r_)
515  if(z_>0.and.z_<=ndim) then
516  ps(igrid)%ds(ixgext^s,z_)=ps(igrid)%dx(ixgext^s,z_)
517  ps(igrid)%dsC(ixgext^s,z_)=ps(igrid)%dx(ixgext^s,z_)
518  if(phi_>z_.and.ndir>ndim) then
519  ps(igrid)%dsC(ixgext^s,phi_)=xext(ixgext^s,1)+half*ps(igrid)%dx(ixgext^s,1)
520  end if
521  end if
522  if(phi_>0.and.phi_<=ndim) then
523  ps(igrid)%ds(ixgext^s,phi_)=xext(ixgext^s,1)*ps(igrid)%dx(ixgext^s,phi_)
524  ps(igrid)%dsC(ixgext^s,phi_)=(xext(ixgext^s,1)+&
525  half*ps(igrid)%dx(ixgext^s,1))*ps(igrid)%dx(ixgext^s,phi_)
526  if(z_>phi_.and.ndir>ndim) ps(igrid)%dsC(ixgext^s,z_)=1.d0
527  end if
528  case default
529  call mpistop("Sorry, coordinate unknown")
530  end select
531 
532  ! initialize background non-evolving solution
533  if (b0field) call set_b0_grid(igrid)
534  if (number_equi_vars>0) call phys_set_equi_vars(igrid)
535 
536  ! find the blocks on the boundaries
537  ps(igrid)%is_physical_boundary=.false.
538  {
539  do i^d=-1,1
540  if(i^d==0) cycle
541  ign^d=ig^d+i^d
542  ! blocks at periodic boundary have neighbors in the physical domain
543  ! thus threated at internal blocks with no physical boundary
544  if (periodb(^d)) ign^d=1+modulo(ign^d-1,ng^d(level))
545  if (ign^d > ng^d(level)) then
546  if(phi_ > 0 .and. poleb(2,^d)) then
547  ! if at a pole, the boundary is not physical boundary
548  ps(igrid)%is_physical_boundary(2*^d)=.false.
549  else
550  ps(igrid)%is_physical_boundary(2*^d)=.true.
551  end if
552  else if (ign^d < 1) then
553  if(phi_ > 0 .and. poleb(1,^d)) then
554  ! if at a pole, the boundary is not physical boundary
555  ps(igrid)%is_physical_boundary(2*^d-1)=.false.
556  else
557  ps(igrid)%is_physical_boundary(2*^d-1)=.true.
558  end if
559  end if
560  end do
561  \}
562  if(any(ps(igrid)%is_physical_boundary)) then
563  phyboundblock(igrid)=.true.
564  else
565  phyboundblock(igrid)=.false.
566  end if
567 
568 end subroutine alloc_node
569 
570 !> allocate memory to physical state of igrid node
571 subroutine alloc_state(igrid, s, ixG^L, ixGext^L, alloc_once_for_ps)
573  type(state) :: s
574  integer, intent(in) :: igrid, ixG^L, ixGext^L
575  logical, intent(in) :: alloc_once_for_ps
576  integer :: ixGs^L
577 
578  allocate(s%w(ixg^s,1:nw))
579  s%igrid=igrid
580  s%w=0.d0
581  s%ixG^l=ixg^l;
582  {^d& ixgsmin^d = ixgmin^d-1; ixgsmax^d = ixgmax^d|;}
583  if(stagger_grid) then
584  allocate(s%ws(ixgs^s,1:nws))
585  s%ws=0.d0
586  if(record_electric_field) then
587  allocate(s%we(ixgs^s,1:nws))
588  s%we=0.d0
589  end if
590  s%ixGs^l=ixgs^l;
591  end if
592  if(alloc_once_for_ps) then
593  ! allocate extra variables for ps state
594  if(nw_extra>0) allocate(s%wextra(ixg^s,1:nw_extra))
595  ! allocate coordinates
596  allocate(s%x(ixg^s,1:ndim))
597  allocate(s%dx(ixgext^s,1:ndim), &
598  s%ds(ixgext^s,1:ndim),s%dsC(ixgext^s,1:3))
599  allocate(s%dvolume(ixgext^s))
600  allocate(s%surfaceC(ixgs^s,1:ndim), &
601  s%surface(ixg^s,1:ndim))
602  ! allocate physical boundary flag
603  allocate(s%is_physical_boundary(2*ndim))
604  if(b0field) then
605  allocate(s%B0(ixg^s,1:ndir,0:ndim))
606  allocate(s%J0(ixg^s,7-2*ndir:3))
607  end if
608  if(number_equi_vars > 0) then
609  allocate(s%equi_vars(ixg^s,1:number_equi_vars,0:ndim))
610  endif
611 
612  ! allocate space for special values for each block state
613  if(phys_trac) then
614  ! special_values(1) Tcoff local
615  ! special_values(2) Tmax local
616  ! special_values(3:2+ndim) Bdir local
617  allocate(s%special_values(ndim+2))
618  end if
619  else
620  ! share common info from ps states to save memory
621  if(nw_extra>0) s%wextra=>ps(igrid)%wextra
622  s%x=>ps(igrid)%x
623  s%dx=>ps(igrid)%dx
624  s%ds=>ps(igrid)%ds
625  s%dsC=>ps(igrid)%dsC
626  s%dvolume=>ps(igrid)%dvolume
627  s%surfaceC=>ps(igrid)%surfaceC
628  s%surface=>ps(igrid)%surface
629  s%is_physical_boundary=>ps(igrid)%is_physical_boundary
630  if(b0field) then
631  s%B0=>ps(igrid)%B0
632  s%J0=>ps(igrid)%J0
633  end if
634  if(number_equi_vars > 0) then
635  s%equi_vars=>ps(igrid)%equi_vars
636  endif
637  if(phys_trac) s%special_values=>ps(igrid)%special_values
638  end if
639 end subroutine alloc_state
640 
641 !> allocate memory to one-level coarser physical state of igrid node
642 subroutine alloc_state_coarse(igrid, s, ixG^L, ixGext^L)
645  type(state) :: s
646  integer, intent(in) :: igrid, ixG^L, ixGext^L
647  integer :: ixGs^L
648 
649  allocate(s%w(ixg^s,1:nw))
650  s%igrid=igrid
651  s%w=0.d0
652  s%ixG^l=ixg^l;
653  {^d& ixgsmin^d = ixgmin^d-1; ixgsmax^d = ixgmax^d|;}
654  if(stagger_grid) then
655  allocate(s%ws(ixgs^s,1:nws))
656  s%ws=0.d0
657  s%ixGs^l=ixgs^l;
658  end if
659  if(b0field.and.mhd_semirelativistic) then
660  allocate(s%B0(ixg^s,1:ndir,0:ndim))
661  end if
662  ! allocate coordinates
663  allocate(s%x(ixg^s,1:ndim))
664  allocate(s%dx(ixgext^s,1:ndim), &
665  s%ds(ixgext^s,1:ndim),s%dsC(ixgext^s,1:3))
666  allocate(s%dvolume(ixgext^s))
667  allocate(s%surfaceC(ixgs^s,1:ndim), &
668  s%surface(ixg^s,1:ndim))
669  ! allocate physical boundary flag
670  allocate(s%is_physical_boundary(2*ndim))
671 end subroutine alloc_state_coarse
672 
673 subroutine dealloc_state(igrid, s,dealloc_x)
675  integer, intent(in) :: igrid
676  type(state) :: s
677  logical, intent(in) :: dealloc_x
678 
679  deallocate(s%w)
680  if(stagger_grid) then
681  deallocate(s%ws)
682  end if
683  if(dealloc_x) then
684  if(nw_extra>0) deallocate(s%wextra)
685  ! deallocate coordinates
686  deallocate(s%x)
687  deallocate(s%dx,s%ds,s%dsC)
688  deallocate(s%dvolume)
689  deallocate(s%surfaceC,s%surface)
690  deallocate(s%is_physical_boundary)
691  if(b0field) then
692  deallocate(s%B0)
693  deallocate(s%J0)
694  end if
695  if(number_equi_vars > 0) then
696  deallocate(s%equi_vars)
697  end if
698  else
699  nullify(s%x,s%dx,s%ds,s%dsC,s%dvolume,s%surfaceC,s%surface)
700  nullify(s%is_physical_boundary)
701  if(b0field) nullify(s%B0,s%J0)
702  if(number_equi_vars > 0) then
703  nullify(s%equi_vars)
704  end if
705  if(nw_extra>0) nullify(s%wextra)
706  end if
707 end subroutine dealloc_state
708 
709 subroutine dealloc_state_coarse(igrid, s)
712  integer, intent(in) :: igrid
713  type(state) :: s
714 
715  deallocate(s%w)
716  if(stagger_grid) then
717  deallocate(s%ws)
718  end if
719  if(b0field.and.mhd_semirelativistic) then
720  deallocate(s%B0)
721  end if
722  ! deallocate coordinates
723  deallocate(s%x)
724  deallocate(s%dx,s%ds,s%dsC)
725  deallocate(s%dvolume)
726  deallocate(s%surfaceC,s%surface)
727  deallocate(s%is_physical_boundary)
728 end subroutine dealloc_state_coarse
729 
730 subroutine dealloc_node(igrid)
732 
733  integer, intent(in) :: igrid
734 
735  if (igrid==0) then
736  call mpistop("trying to delete a non-existing grid in dealloc_node")
737  end if
738 
739  call dealloc_state(igrid, ps(igrid),.true.)
740  call dealloc_state_coarse(igrid, psc(igrid))
741  if(.not.convert) then
742  call dealloc_state(igrid, ps1(igrid),.false.)
743  call dealloc_state(igrid, pso(igrid),.false.)
744  ! deallocate temporary solution space
745  select case (t_integrator)
747  call dealloc_state(igrid, ps2(igrid),.false.)
748  case(rk3_bt,rk4,ssprk5,imex_cb3a)
749  call dealloc_state(igrid, ps2(igrid),.false.)
750  call dealloc_state(igrid, ps3(igrid),.false.)
751  case(imex_ars3,imex_232)
752  call dealloc_state(igrid, ps2(igrid),.false.)
753  call dealloc_state(igrid, ps3(igrid),.false.)
754  call dealloc_state(igrid, ps4(igrid),.false.)
755  end select
756  end if
757 
758 end subroutine dealloc_node
subroutine alloc_node(igrid)
allocate arrays on igrid node
subroutine dealloc_node(igrid)
integer function getnode(ipe)
Get first available igrid on processor ipe.
subroutine dealloc_state_coarse(igrid, s)
subroutine putnode(igrid, ipe)
subroutine dealloc_state(igrid, s, dealloc_x)
subroutine alloc_state_coarse(igrid, s, ixGL, ixGextL)
allocate memory to one-level coarser physical state of igrid node
subroutine alloc_state(igrid, s, ixGL, ixGextL, alloc_once_for_ps)
allocate memory to physical state of igrid node
subroutine mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: comm_lib.t:194
Module with basic grid data structures.
Definition: mod_forest.t:2
logical, dimension(:,:), allocatable, save igrid_inuse
Definition: mod_forest.t:70
type(tree_node_ptr), dimension(:,:), allocatable, save igrid_to_node
Array to go from an [igrid, ipe] index to a node pointer.
Definition: mod_forest.t:32
Module with geometry-related routines (e.g., divergence, curl)
Definition: mod_geometry.t:2
This module contains definitions of global parameters and variables and some generic functions/subrou...
type(state), pointer block
Block pointer for using one block and its previous state.
integer, parameter imex_232
double precision, dimension(:), allocatable dg
extent of grid blocks in domain per dimension, in array over levels
integer, parameter ndim
Number of spatial dimensions for grid variables.
logical stagger_grid
True for using stagger grid.
integer, parameter imex_ars3
integer, parameter imex_trapezoidal
integer mype
The rank of the current MPI task.
integer, parameter plevel_
integer, dimension(:), allocatable, parameter d
integer, parameter nodehi
grid hierarchy info (level and grid indices)
integer ndir
Number of spatial dimensions (components) for vector variables.
logical b0field
split magnetic field as background B0 field
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
integer nghostcells
Number of ghost cells surrounding a grid.
logical phys_trac
Use TRAC (Johnston 2019 ApJL, 873, L22) for MHD or 1D HD.
logical convert
If true and restart_from_file is given, convert snapshots to other file formats.
integer, parameter rnodehi
grid location info (corner coordinates and grid spacing)
integer max_blocks
The maximum number of grid blocks in a processor.
integer, parameter imex_cb3a
logical record_electric_field
True for record electric field.
integer, parameter imex_222
integer t_integrator
time integrator method
integer, dimension(:,:), allocatable node
double precision, dimension(ndim) dxlevel
integer, parameter imex_midpoint
Magneto-hydrodynamics module.
Definition: mod_mhd_phys.t:2
logical, public, protected mhd_semirelativistic
Whether semirelativistic MHD equations (Gombosi 2002 JCP) are solved.
Definition: mod_mhd_phys.t:90
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition: mod_physics.t:4
procedure(sub_set_equi_vars), pointer phys_set_equi_vars
Definition: mod_physics.t:89
Module with all the methods that users can customize in AMRVAC.
procedure(set_surface), pointer usr_set_surface
subroutine set_b0_grid(igrid)
Definition: set_B0.t:2