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