MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_trac.t
Go to the documentation of this file.
1module mod_trac
4 use mod_eos
5 use mod_comm_lib, only: mpistop
6 implicit none
7 private
8 ! common
9 integer :: numFL,numLP
10 double precision :: dL,Tmax,trac_delta,T_bott
11 double precision, allocatable :: xFi(:,:)
12 ! TRACB
13 integer :: numxT^D
14 double precision :: dxT^D
15 double precision :: xTmin(ndim),xTmax(ndim)
16 double precision, allocatable :: xT(:^D&,:)
17 ! TRACL mask
18 integer, allocatable :: trac_grid(:),ground_grid(:)
19 integer :: ngrid_trac,ngrid_ground
20 logical, allocatable :: trac_pe(:)
22contains
23
24 subroutine init_trac_line(mask)
25 logical, intent(in) :: mask
26 integer :: refine_factor,ix^D,ix(ndim),j,iFL,numL(ndim),finegrid
27 double precision :: lengthFL
28 double precision :: xprobmin(ndim),xprobmax(ndim),domain_nx(ndim)
29 integer :: memxFi
30
31 trac_delta=0.25d0
32 !----------------- init magnetic field -------------------!
33 refine_factor=2**(refine_max_level-1)
34 ^d&xprobmin(^d)=xprobmin^d\
35 ^d&xprobmax(^d)=xprobmax^d\
36 ^d&domain_nx(^d)=domain_nx^d\
37 dl=(xprobmax(ndim)-xprobmin(ndim))/(domain_nx(ndim)*refine_factor)
38 ! max length of a field line
39 if (.not. mask) phys_trac_mask=xprobmax^nd
40 {^iftwod
41 lengthfl=(phys_trac_mask-xprobmin(2))*3.d0
42 }
43 {^ifthreed
44 lengthfl=(phys_trac_mask-xprobmin(3))*3.d0
45 }
46
47 numlp=floor(lengthfl/dl)
48 numl=1
49 numfl=1
50 do j=1,ndim-1
51 ! number of field lines, every 4 finest grid, every direction
52 finegrid=phys_trac_finegrid
53 numl(j)=floor((xprobmax(j)-xprobmin(j))/dl/finegrid)
54 numfl=numfl*numl(j)
55 end do
56 allocate(xfi(numfl,ndim))
57 xfi(:,ndim)=xprobmin(ndim)+dl/50.d0
58 {do ix^db=1,numl(^db)\}
59 ^d&ix(^d)=ix^d\
60 ifl=0
61 do j=ndim-1,1,-1
62 ifl=ifl+(ix(j)-(ndim-1-j))*(numl(j))**(ndim-1-j)
63 end do
64 xfi(ifl,1:ndim-1)=xprobmin(1:ndim-1)+finegrid*dl*ix(1:ndim-1)-finegrid*dl/2.d0
65 {end do\}
66 {^iftwod
67 if(mype .eq. 0) write(*,*) 'NOTE: 2D TRAC method take the y-dir == grav-dir'
68 }
69 {^ifthreed
70 if(mype .eq. 0) write(*,*) 'NOTE: 3D TRAC method take the z-dir == grav-dir'
71 }
72
73 memxfi=floor(8*numfl*numlp*ndim/1e6)
74 if (mype==0) write(*,*) 'Memory requirement for each processor in TRAC:'
75 if (mype==0) write(*,*) memxfi,' MB'
76
77 allocate(trac_pe(0:npe-1),trac_grid(max_blocks),ground_grid(max_blocks))
78
79 end subroutine init_trac_line
80
81 subroutine init_trac_block(mask)
82 logical, intent(in) :: mask
83 integer :: refine_factor,finegrid,iFL,j
84 integer :: ix^D,ixT^L
85 integer :: numL(ndim),ix(ndim)
86 double precision :: lengthFL
87 double precision :: ration,a0
88 double precision :: xprobmin(ndim),xprobmax(ndim),dxT(ndim)
89
90 refine_factor=2**(refine_max_level-1)
91 ^d&xprobmin(^d)=xprobmin^d\
92 ^d&xprobmax(^d)=xprobmax^d\
93 ^d&dxt^d=(xprobmax^d-xprobmin^d)/(domain_nx^d*refine_factor/block_nx^d)\
94 ^d&dxt(ndim)=dxt^d\
95 finegrid=phys_trac_finegrid
96 {^ifoned
97 dl=dxt1/finegrid
98 }
99 {^nooned
100 dl=min(dxt^d)/finegrid
101 }
102 ! table for interpolation
103 ^d&xtmin(^d)=xprobmin^d\
104 ^d&xtmax(^d)=xprobmax^d\
105 if(mask) xtmax(ndim)=phys_trac_mask
106 ! max length of a field line
107 if(mask) then
108 lengthfl=maxval(xtmax-xprobmin)*3.d0
109 else
110 lengthfl=maxval(xprobmax-xprobmin)*3.d0
111 end if
112 numlp=floor(lengthfl/dl)
113 ^d&numxt^d=ceiling((xtmax(^d)-xtmin(^d)-smalldouble)/dxt^d)\
114 allocate(xt(numxt^d,ndim))
115 ixtmin^d=1\
116 ixtmax^d=numxt^d\
117 {do j=1,numxt^d
118 xt(j^d%ixT^s,^d)=(j-0.5d0)*dxt^d+xtmin(^d)
119 end do\}
120 if(mask) xtmax(ndim)=maxval(xt(:^d&,ndim))+half*dxt(ndim)
121 numl=1
122 numfl=1
123 do j=1,ndim-1
124 ! number of field lines, every 4 finest grid, every direction
125 numl(j)=floor((xprobmax(j)-xprobmin(j))/dl)
126 numfl=numfl*numl(j)
127 end do
128 allocate(xfi(numfl,ndim))
129 xfi(:,ndim)=xprobmin(ndim)+dl/50.d0
130 {do ix^db=1,numl(^db)\}
131 ^d&ix(^d)=ix^d\
132 ifl=0
133 do j=ndim-1,1,-1
134 ifl=ifl+(ix(j)-(ndim-1-j))*(numl(j))**(ndim-1-j)
135 end do
136 xfi(ifl,1:ndim-1)=xprobmin(1:ndim-1)+dl*ix(1:ndim-1)-dl/2.d0
137 {end do\}
138 {^iftwod
139 if(mype .eq. 0) write(*,*) 'NOTE: 2D TRAC method take the y-dir == grav-dir'
140 }
141 {^ifthreed
142 if(mype .eq. 0) write(*,*) 'NOTE: 3D TRAC method take the z-dir == grav-dir'
143 }
144 end subroutine init_trac_block
145
146 subroutine trac_simple(tco_global,trac_alfa,T_peak)
147 double precision, intent(in) :: tco_global, trac_alfa,T_peak
148 integer :: iigrid, igrid
149
150 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
151 {^ifoned
152 ps(igrid)%special_values(1)=tco_global
153 }
154 if(ps(igrid)%special_values(1)<trac_alfa*ps(igrid)%special_values(2)) then
155 ps(igrid)%special_values(1)=trac_alfa*ps(igrid)%special_values(2)
156 end if
157 if(ps(igrid)%special_values(1) .lt. t_bott) then
158 ps(igrid)%special_values(1)=t_bott
159 else if(ps(igrid)%special_values(1) .gt. 0.2d0*t_peak) then
160 ps(igrid)%special_values(1)=0.2d0*t_peak
161 end if
162 ps(igrid)%wextra(ixg^t,iw_tcoff)=ps(igrid)%special_values(1)
163 !> special values(2) to save old tcutoff
164 ps(igrid)%special_values(2)=ps(igrid)%special_values(1)
165 end do
166 end subroutine trac_simple
167
168 subroutine ltrac(T_peak)
169 double precision, intent(in) :: T_peak
170 integer :: iigrid, igrid
171 integer :: ixO^L,trac_tcoff
172
173 ixo^l=ixm^ll^ladd1;
174 trac_tcoff=iw_tcoff
175 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
176 where(ps(igrid)%wextra(ixo^s,trac_tcoff) .lt. t_bott)
177 ps(igrid)%wextra(ixo^s,trac_tcoff)=t_bott
178 else where(ps(igrid)%wextra(ixo^s,trac_tcoff) .gt. 0.2d0*t_peak)
179 ps(igrid)%wextra(ixo^s,trac_tcoff)=0.2d0*t_peak
180 end where
181 end do
182 end subroutine ltrac
183
184 subroutine tracl(mask,T_peak)
185 logical, intent(in) :: mask
186 double precision, intent(in) :: T_peak
187 integer :: ix^D,j
188 integer :: iigrid, igrid
189 double precision :: xF(numFL,numLP,ndim)
190 integer :: numR(numFL),ix^L
191 double precision :: Tlcoff(numFL)
192 integer :: ipel(numFL,numLP),igridl(numFL,numLP)
193 logical :: forwardl(numFL)
194
195 tmax=t_peak
196 xf=zero
197
198 do j=1,ndim
199 xf(:,1,j)=xfi(:,j)
200 end do
201
202 call mpi_barrier(icomm,ierrmpi)
203 ! record pe and grid for mask region
204 call update_pegrid()
205 ! get temperature for the calculation of Te gradient,
206 ! which will be stored in wextra(ixI^S,iw_Tcoff) temporarily
207 call get_te_grid()
208 ! find out direction for tracing B field
209 call get_btracing_dir(ipel,igridl,forwardl)
210 ! trace Bfield and get Tcoff for each field line
211 call get_tcoff_line(xf,numr,tlcoff,ipel,igridl,forwardl,mask)
212 ! init vairable Tcoff_ and Tweight_
213 call init_trac_tcoff()
214 ! get cell Tcoff via interpolation
215 call interp_tcoff(xf,ipel,igridl,numr,tlcoff)
216 ! convert primitive data back to conserved data
217 call mpi_barrier(icomm,ierrmpi)
218
219
220 end subroutine tracl
221
222 subroutine tracb(mask,T_peak)
223 logical, intent(in) :: mask
224 double precision, intent(in) :: T_peak
225 integer :: peArr(numxT^D),gdArr(numxT^D),numR(numFL)
226 double precision :: Tcoff(numxT^D),Tcmax(numxT^D),Bdir(numxT^D,ndim)
227 double precision :: xF(numFL,numLP,ndim),Tcoff_line(numFL)
228 integer :: xpe(numFL,numLP,2**ndim)
229 integer :: xgd(numFL,numLP,2**ndim)
230
231 tmax=t_peak
232 tcoff=zero
233 tcmax=zero
234 bdir=zero
235 pearr=-1
236 gdarr=-1
237 call block_estable(mask,tcoff,tcmax,bdir,pearr,gdarr)
238 xf=zero
239 numr=0
240 tcoff_line=zero
241 call block_trace_mfl(mask,tcoff,tcoff_line,tcmax,bdir,pearr,gdarr,xf,numr,xpe,xgd)
242 call block_interp_grid(mask,xf,numr,xpe,xgd,tcoff_line)
243 end subroutine tracb
244
245 subroutine block_estable(mask,Tcoff,Tcmax,Bdir,peArr,gdArr)
246 logical :: mask
247 double precision :: Tcoff(numxT^D),Tcoff_recv(numxT^D)
248 double precision :: Tcmax(numxT^D),Tcmax_recv(numxT^D)
249 double precision :: Bdir(numxT^D,ndim),Bdir_recv(numxT^D,ndim)
250 integer :: peArr(numxT^D),peArr_recv(numxT^D)
251 integer :: gdArr(numxT^D),gdArr_recv(numxT^D)
252 integer :: xc^L,xd^L,ix^D
253 integer :: iigrid,igrid,numxT,intab
254 double precision :: xb^L
255
256 tcoff_recv=zero
257 tcmax_recv=zero
258 bdir_recv=zero
259 pearr_recv=-1
260 gdarr_recv=-1
261 !> combine table from different processors
262 xcmin^d=nghostcells+1\
263 xcmax^d=block_nx^d+nghostcells\
264 do iigrid=1,igridstail; igrid=igrids(iigrid);
265 ps(igrid)%wextra(:^d&,iw_tweight)=zero
266 ps(igrid)%wextra(:^d&,iw_tcoff)=zero
267 ^d&xbmin^d=rnode(rpxmin^d_,igrid)-xtmin(^d)\
268 ^d&xbmax^d=rnode(rpxmax^d_,igrid)-xtmin(^d)\
269 xdmin^d=nint(xbmin^d/dxt^d)+1\
270 xdmax^d=ceiling((xbmax^d-smalldouble)/dxt^d)\
271 {do ix^d=xdmin^d,xdmax^d \}
272 intab=0
273 {if (ix^d .le. numxt^d) intab=intab+1 \}
274 if(intab .eq. ndim) then
275 !> in principle, no overlap will happen here
276 tcoff(ix^d)=max(tcoff(ix^d),ps(igrid)%special_values(1))
277 tcmax(ix^d)=ps(igrid)%special_values(2)
278 !> abs(Bdir) <= 1, so that Bdir+2 should always be positive
279 bdir(ix^d,1:ndim)=ps(igrid)%special_values(3:3+ndim-1)+2.d0
280 pearr(ix^d)=mype
281 gdarr(ix^d)=igrid
282 end if
283 {end do\}
284 end do
285 call mpi_barrier(icomm,ierrmpi)
286 numxt={numxt^d*}
287 call mpi_allreduce(pearr,pearr_recv,numxt,mpi_integer,&
288 mpi_max,icomm,ierrmpi)
289 call mpi_allreduce(gdarr,gdarr_recv,numxt,mpi_integer,&
290 mpi_max,icomm,ierrmpi)
291 call mpi_allreduce(tcoff,tcoff_recv,numxt,mpi_double_precision,&
292 mpi_max,icomm,ierrmpi)
293 call mpi_allreduce(bdir,bdir_recv,numxt*ndim,mpi_double_precision,&
294 mpi_max,icomm,ierrmpi)
295 if(.not. mask) then
296 call mpi_allreduce(tcmax,tcmax_recv,numxt,mpi_double_precision,&
297 mpi_max,icomm,ierrmpi)
298 end if
299 pearr=pearr_recv
300 gdarr=gdarr_recv
301 tcoff=tcoff_recv
302 bdir=bdir_recv-2.d0
303 if(.not. mask) tcmax=tcmax_recv
304 end subroutine block_estable
305
306 subroutine block_trace_mfl(mask,Tcoff,Tcoff_line,Tcmax,Bdir,peArr,gdArr,xF,numR,xpe,xgd)
307 integer :: i,j,k,k^D,ix_next^D
308 logical :: mask,flag,first
309 double precision :: Tcoff(numxT^D),Tcoff_line(numFL)
310 double precision :: Tcmax(numxT^D),Tcmax_line(numFL)
311 double precision :: xF(numFL,numLP,ndim)
312 integer :: ix_mod(ndim,2),numR(numFL)
313 double precision :: alfa_mod(ndim,2)
314 double precision :: nowpoint(ndim),nowgridc(ndim)
315 double precision :: Bdir(numxT^D,ndim)
316 double precision :: init_dir,now_dir1(ndim),now_dir2(ndim)
317 integer :: peArr(numxT^D),xpe(numFL,numLP,2**ndim)
318 integer :: gdArr(numxT^D),xgd(numFL,numLP,2**ndim)
319
320 do i=1,numfl
321 flag=.true.
322 ^d&k^d=ceiling((xfi(i,^d)-xtmin(^d)-smalldouble)/dxt^d)\
323 tcoff_line(i)=tcoff(k^d)
324 if(.not. mask) tcmax_line(i)=tcmax(k^d)
325 ix_next^d=k^d\
326 j=1
327 xf(i,j,:)=xfi(i,:)
328 do while(flag)
329 nowpoint(:)=xf(i,j,:)
330 nowgridc(:)=xt(ix_next^d,:)
331 first=.true.
332 if(j .eq. 1) then
333 call rk_bdir(nowgridc,nowpoint,ix_next^d,now_dir1,bdir,&
334 ix_mod,first,init_dir)
335 else
336 call rk_bdir(nowgridc,nowpoint,ix_next^d,now_dir1,bdir,&
337 ix_mod,first)
338 end if
339 {^iftwod
340 xgd(i,j,1)=gdarr(ix_mod(1,1),ix_mod(2,1))
341 xgd(i,j,2)=gdarr(ix_mod(1,2),ix_mod(2,1))
342 xgd(i,j,3)=gdarr(ix_mod(1,1),ix_mod(2,2))
343 xgd(i,j,4)=gdarr(ix_mod(1,2),ix_mod(2,2))
344 xpe(i,j,1)=pearr(ix_mod(1,1),ix_mod(2,1))
345 xpe(i,j,2)=pearr(ix_mod(1,2),ix_mod(2,1))
346 xpe(i,j,3)=pearr(ix_mod(1,1),ix_mod(2,2))
347 xpe(i,j,4)=pearr(ix_mod(1,2),ix_mod(2,2))
348 }
349 {^ifthreed
350 xgd(i,j,1)=gdarr(ix_mod(1,1),ix_mod(2,1),ix_mod(3,1))
351 xgd(i,j,2)=gdarr(ix_mod(1,2),ix_mod(2,1),ix_mod(3,1))
352 xgd(i,j,3)=gdarr(ix_mod(1,1),ix_mod(2,2),ix_mod(3,1))
353 xgd(i,j,4)=gdarr(ix_mod(1,2),ix_mod(2,2),ix_mod(3,1))
354 xgd(i,j,5)=gdarr(ix_mod(1,1),ix_mod(2,1),ix_mod(3,2))
355 xgd(i,j,6)=gdarr(ix_mod(1,2),ix_mod(2,1),ix_mod(3,2))
356 xgd(i,j,7)=gdarr(ix_mod(1,1),ix_mod(2,2),ix_mod(3,2))
357 xgd(i,j,8)=gdarr(ix_mod(1,2),ix_mod(2,2),ix_mod(3,2))
358 xpe(i,j,1)=pearr(ix_mod(1,1),ix_mod(2,1),ix_mod(3,1))
359 xpe(i,j,2)=pearr(ix_mod(1,2),ix_mod(2,1),ix_mod(3,1))
360 xpe(i,j,3)=pearr(ix_mod(1,1),ix_mod(2,2),ix_mod(3,1))
361 xpe(i,j,4)=pearr(ix_mod(1,2),ix_mod(2,2),ix_mod(3,1))
362 xpe(i,j,5)=pearr(ix_mod(1,1),ix_mod(2,1),ix_mod(3,2))
363 xpe(i,j,6)=pearr(ix_mod(1,2),ix_mod(2,1),ix_mod(3,2))
364 xpe(i,j,7)=pearr(ix_mod(1,1),ix_mod(2,2),ix_mod(3,2))
365 xpe(i,j,8)=pearr(ix_mod(1,2),ix_mod(2,2),ix_mod(3,2))
366 }
367 nowpoint(:)=nowpoint(:)+init_dir*now_dir1*dl
368 {if(nowpoint(^d) .gt. xtmax(^d) .or. nowpoint(^d) .lt. xtmin(^d)) then
369 flag=.false.
370 end if\}
371 if(mask .and. nowpoint(ndim) .gt. phys_trac_mask) then
372 flag=.false.
373 end if
374 if(flag) then
375 first=.false.
376 ^d&ix_next^d=ceiling((nowpoint(^d)-xtmin(^d)-smalldouble)/dxt^d)\
377 nowgridc(:)=xt(ix_next^d,:)
378 call rk_bdir(nowgridc,nowpoint,ix_next^d,now_dir2,bdir,&
379 ix_mod,first)
380 xf(i,j+1,:)=xf(i,j,:)+init_dir*dl*half*(now_dir1+now_dir2)
381 {if(xf(i,j+1,^d) .gt. xtmax(^d) .or. xf(i,j+1,^d) .lt. xtmin(^d)) then
382 flag=.false.
383 end if\}
384 if(mask .and. xf(i,j+1,ndim) .gt. phys_trac_mask) then
385 flag=.false.
386 end if
387 if(flag) then
388 ^d&ix_next^d=ceiling((xf(i,j+1,^d)-xtmin(^d)-smalldouble)/dxt^d)\
389 j=j+1
390 tcoff_line(i)=max(tcoff_line(i),tcoff(ix_next^d))
391 if(.not.mask) tcmax_line(i)=max(tcmax_line(i),tcmax(ix_next^d))
392 end if
393 end if
394 end do
395 numr(i)=j
396 if(mask) then
397 if(tcoff_line(i) .gt. tmax*0.2d0) then
398 tcoff_line(i)=tmax*0.2d0
399 end if
400 else
401 if(tcoff_line(i) .gt. tcmax_line(i)*0.2d0) then
402 tcoff_line(i)=tcmax_line(i)*0.2d0
403 end if
404 end if
405 end do
406 end subroutine block_trace_mfl
407
408 subroutine rk_bdir(nowgridc,nowpoint,ix_next^D,now_dir,Bdir,ix_mod,first,init_dir)
409 double precision :: nowpoint(ndim),nowgridc(ndim)
410 integer :: ix_mod(ndim,2)
411 double precision :: alfa_mod(ndim,2)
412 integer :: ix_next^D,k^D
413 double precision :: now_dir(ndim)
414 double precision :: Bdir(numxT^D,ndim)
415 logical :: first
416 double precision, optional :: init_dir
417
418 {if(nowpoint(^d) .gt. xtmin(^d)+half*dxt^d .and. nowpoint(^d) .lt. xtmax(^d)-half*dxt^d) then
419 if(nowpoint(^d) .le. nowgridc(^d)) then
420 ix_mod(^d,1)=ix_next^d-1
421 ix_mod(^d,2)=ix_next^d
422 alfa_mod(^d,1)=abs(nowgridc(^d)-nowpoint(^d))/dxt^d
423 alfa_mod(^d,2)=one-alfa_mod(^d,1)
424 else
425 ix_mod(^d,1)=ix_next^d
426 ix_mod(^d,2)=ix_next^d+1
427 alfa_mod(^d,2)=abs(nowgridc(^d)-nowpoint(^d))/dxt^d
428 alfa_mod(^d,1)=one-alfa_mod(^d,2)
429 end if
430 else
431 ix_mod(^d,:)=ix_next^d
432 alfa_mod(^d,:)=half
433 end if\}
434 now_dir=zero
435 {^iftwod
436 do k1=1,2
437 do k2=1,2
438 now_dir=now_dir + bdir(ix_mod(1,k1),ix_mod(2,k2),:)*alfa_mod(1,k1)*alfa_mod(2,k2)
439 end do
440 end do
441 }
442 {^ifthreed
443 do k1=1,2
444 do k2=1,2
445 do k3=1,2
446 now_dir=now_dir + bdir(ix_mod(1,k1),ix_mod(2,k2),ix_mod(3,k3),:)&
447 *alfa_mod(1,k1)*alfa_mod(2,k2)*alfa_mod(3,k3)
448 end do
449 end do
450 end do
451 }
452 if(present(init_dir)) then
453 init_dir=sign(one,now_dir(ndim))
454 end if
455 end subroutine rk_bdir
456
457 subroutine block_interp_grid(mask,xF,numR,xpe,xgd,Tcoff_line)
458 logical :: mask
459 double precision :: xF(numFL,numLP,ndim)
460 integer :: numR(numFL)
461 integer :: xpe(numFL,numLP,2**ndim)
462 integer :: xgd(numFL,numLP,2**ndim)
463 double precision :: Tcoff_line(numFL)
464 double precision :: weightIndex,weight,ds
465 integer :: i,j,k,igrid,iigrid,ixO^L,ixc^L,ixc^D
466 double precision :: dxMax^D,dxb^D
467
468 !> interpolate lines into grid cells
469 weightindex=2.d0
470 dxmax^d=2.d0*dl;
471 ixo^l=ixm^ll;
472 do i=1,numfl
473 do j=1,numr(i)
474 do k=1,2**ndim
475 if(mype .eq. xpe(i,j,k)) then
476 igrid=xgd(i,j,k)
477 if(igrid .le. igrids(igridstail)) then
478 ^d&dxb^d=rnode(rpdx^d_,igrid)\
479 ^d&ixcmin^d=floor((xf(i,j,^d)-dxmax^d-ps(igrid)%x(ixomin^dd,^d))/dxb^d)+ixomin^d\
480 ^d&ixcmax^d=floor((xf(i,j,^d)+dxmax^d-ps(igrid)%x(ixomin^dd,^d))/dxb^d)+ixomin^d\
481 {if (ixcmin^d<ixomin^d) ixcmin^d=ixomin^d\}
482 {if (ixcmax^d>ixomax^d) ixcmax^d=ixomax^d\}
483 {do ixc^d=ixcmin^d,ixcmax^d\}
484 ds=0.d0
485 {ds=ds+(xf(i,j,^d)-ps(igrid)%x(ixc^dd,^d))**2\}
486 ds=sqrt(ds)
487 if(ds .le. 0.099d0*dl) then
488 weight=(1/(0.099d0*dl))**weightindex
489 else
490 weight=(1/ds)**weightindex
491 endif
492 ps(igrid)%wextra(ixc^d,iw_tweight)=ps(igrid)%wextra(ixc^d,iw_tweight)+weight
493 ps(igrid)%wextra(ixc^d,iw_tcoff)=ps(igrid)%wextra(ixc^d,iw_tcoff)+weight*tcoff_line(i)
494 {enddo\}
495 else
496 call mpistop("we need to check here 366Line in mod_trac.t")
497 end if
498 end if
499 end do
500 end do
501 end do
502 ! finish interpolation
503 do iigrid=1,igridstail; igrid=igrids(iigrid);
504 where (ps(igrid)%wextra(ixo^s,iw_tweight)>0.d0)
505 ps(igrid)%wextra(ixo^s,iw_tcoff)=ps(igrid)%wextra(ixo^s,iw_tcoff)/ps(igrid)%wextra(ixo^s,iw_tweight)
506 elsewhere
507 ps(igrid)%wextra(ixo^s,iw_tcoff)=0.2d0*tmax
508 endwhere
509 enddo
510 end subroutine block_interp_grid
511
512 ! TODO remove, not used?
513! subroutine get_Tmax_grid(x,w,ixI^L,ixO^L,Tmax_grid)
514! integer, intent(in) :: ixI^L,ixO^L
515! double precision, intent(in) :: x(ixI^S,1:ndim)
516! double precision, intent(out) :: w(ixI^S,1:nw)
517! double precision :: Tmax_grid
518! double precision :: pth(ixI^S),Te(ixI^S)
519!
520! call mhd_get_pthermal(w,x,ixI^L,ixO^L,pth)
521! Te(ixO^S)=pth(ixO^S)/w(ixO^S,rho_)
522! Tmax_grid=maxval(Te(ixO^S))
523! end subroutine get_Tmax_grid
524
525 subroutine init_trac_tcoff()
526 integer :: ixI^L,ixO^L,igrid,iigrid
527
528 ixi^l=ixg^ll;
529 ixo^l=ixm^ll;
530
531 do iigrid=1,igridstail; igrid=igrids(iigrid);
532 ps(igrid)%wextra(ixi^s,iw_tcoff)=0.d0
533 ps(igrid)%wextra(ixi^s,iw_tweight)=0.d0
534 end do
535 end subroutine init_trac_tcoff
536
537 subroutine update_pegrid()
538
539 ngrid_trac=0
540 ngrid_ground=0
541 trac_pe(:)=.false.
542 trac_grid(:)=0
543 ground_grid(:)=0
544
545 ! traverse gridtable to information of grid inside mask region
546 call traverse_gridtable()
547
548 end subroutine update_pegrid
549
550 subroutine traverse_gridtable()
552
553 double precision :: dxb^D,xb^L
554 integer :: iigrid,igrid,j
555 logical, allocatable :: trac_pe_recv(:)
556 double precision :: hcmax_bt
557
558 allocate(trac_pe_recv(npe))
559
560 hcmax_bt=xprobmin^nd+(xprobmax^nd-xprobmin^nd)/(domain_nx^nd*2**(refine_max_level-1))
561
562 do iigrid=1,igridstail; igrid=igrids(iigrid);
563 xbmin^nd=rnode(rpxmin^nd_,igrid)
564 if (xbmin^nd<phys_trac_mask) then
565 trac_pe(mype)=.true.
566 ngrid_trac=ngrid_trac+1
567 trac_grid(ngrid_trac)=igrid
568 if (xbmin^nd<hcmax_bt) then
569 ngrid_ground=ngrid_ground+1
570 ground_grid(ngrid_ground)=igrid
571 endif
572 endif
573 enddo
574
575 call mpi_allreduce(trac_pe,trac_pe_recv,npe,mpi_logical,mpi_lor,icomm,ierrmpi)
576 trac_pe=trac_pe_recv
577
578 deallocate(trac_pe_recv)
579 end subroutine traverse_gridtable
580
581 subroutine get_te_grid()
582 integer :: ixI^L,ixO^L,igrid,iigrid,j
583 double precision :: rho(ixM^T)
584
585 ixi^l=ixg^ll;
586 ixo^l=ixm^ll;
587 do j=1,ngrid_trac
588 igrid=trac_grid(j)
589 ! EoS-aware temperature (correct for LTE; equals p/rho for FI).
590 call eos%get_Te(ps(igrid)%w,ps(igrid)%x,ixi^l,ixi^l,ps(igrid)%wextra(ixi^s,iw_tcoff))
591 enddo
592 end subroutine get_te_grid
593
594 subroutine get_btracing_dir(ipel,igridl,forwardl)
595 integer :: ipel(numFL,numLP),igridl(numFL,numLP)
596 logical :: forwardl(numFL)
597 integer :: igrid,ixO^L,iFL,j,ix^D,idir,ixb^D,ixbb^D
598 double precision :: xb^L,dxb^D,xd^D,factor,Bh
599 integer :: numL(ndim),ixmin(ndim),ixmax(ndim),ix(ndim)
600 logical :: forwardRC(numFL)
601
602 ipel=-1
603 igridl=0
604 forwardl=.true.
605 ^d&ixomin^d=ixmlo^d;
606 ^d&ixomax^d=ixmhi^d;
607
608 do j=1,ngrid_ground
609 igrid=ground_grid(j)
610 ^d&dxb^d=rnode(rpdx^d_,igrid);
611 ^d&xbmin^d=rnode(rpxmin^d_,igrid);
612 ^d&xbmax^d=rnode(rpxmax^d_,igrid);
613 ^d&ixmin(^d)=floor((xbmin^d-xprobmin^d)/(phys_trac_finegrid*dl))+1;
614 ^d&ixmax(^d)=floor((xbmax^d-xprobmin^d)/(phys_trac_finegrid*dl));
615 ^d&numl(^d)=floor((xprobmax^d-xprobmin^d)/(phys_trac_finegrid*dl));
616 ixmin(^nd)=1
617 ixmax(^nd)=1
618 numl(^nd)=1
619 {do ix^db=ixmin(^db),ixmax(^db)\}
620 ^d&ix(^d)=ix^d;
621 ifl=0
622 do idir=ndim-1,1,-1
623 ifl=ifl+(ix(idir)-(ndim-1-idir))*(numl(idir))**(ndim-1-idir)
624 enddo
625 ipel(ifl,1)=mype
626 igridl(ifl,1)=igrid
627 ^d&ixb^d=floor((xfi(ifl,^d)-ps(igrid)%x(ixomin^dd,^d))/dxb^d)+ixomin^d;
628 ^d&xd^d=(xfi(ifl,^d)-ps(igrid)%x(ixb^dd,^d))/dxb^d;
629 bh=0.d0
630 {do ixbb^d=0,1\}
631 factor={abs(1-ix^d-xd^d)*}
632 if (b0field) then
633 if(allocated(iw_mag)) then
634 bh=bh+factor*(ps(igrid)%w(ixb^d+ixbb^d,iw_mag(^nd))+ps(igrid)%B0(ixb^d+ixbb^d,^nd,0))
635 else
636 bh=bh+factor*(ps(igrid)%B0(ixb^d+ixbb^d,^nd,0))
637 endif
638 else
639 bh=bh+factor*ps(igrid)%w(ixb^d+ixbb^d,iw_mag(^nd))
640 endif
641 {enddo\}
642 if (bh>0) then
643 forwardl(ifl)=.true.
644 else
645 forwardl(ifl)=.false.
646 endif
647 {enddo\}
648 enddo
649 call mpi_allreduce(forwardl,forwardrc,numfl,mpi_logical,&
650 mpi_land,icomm,ierrmpi)
651 forwardl=forwardrc
652 end subroutine get_btracing_dir
653
654 subroutine get_tcoff_line(xFL,numR,TcoffFL,ipeFL,igridFL,forwardFL,mask)
656 double precision :: xFL(numFL,numLP,ndim)
657 integer :: numR(numFL)
658 double precision :: TcoffFL(numFL),TmaxFL(numFL)
659 integer :: ipeFL(numFL,numLP),igridFL(numFL,numLP)
660 logical :: forwardFL(numFL)
661 logical, intent(in) :: mask
662 integer :: nwP,nwL,iFL,iLP
663 double precision :: wPm(numFL,numLP,2),wLm(numFL,1+2)
664 character(len=std_len) :: ftype,tcondi
665
666 nwp=2
667 nwl=2
668 ftype='Bfield'
669 tcondi='TRAC'
670 call trace_field_multi(xfl,wpm,wlm,dl,numfl,numlp,nwp,nwl,forwardfl,ftype,tcondi)
671 do ifl=1,numfl
672 numr(ifl)=int(wlm(ifl,1))
673 tcofffl(ifl)=wlm(ifl,2)
674 tmaxfl(ifl)=wlm(ifl,3)
675 if(mask) then
676 if(tcofffl(ifl)>0.2d0*tmax) tcofffl(ifl)=0.2d0*tmax
677 else
678 tmaxfl(ifl)=wlm(ifl,3)
679 if(tcofffl(ifl)>0.2d0*tmaxfl(ifl)) tcofffl(ifl)=0.2d0*tmaxfl(ifl)
680 end if
681
682 if(tcofffl(ifl)<t_bott) tcofffl(ifl)=t_bott
683 enddo
684
685 do ifl=1,numfl
686 if (numr(ifl)>0) then
687 do ilp=1,numr(ifl)
688 ipefl(ifl,ilp)=int(wpm(ifl,ilp,1))
689 igridfl(ifl,ilp)=int(wpm(ifl,ilp,2))
690 enddo
691 endif
692 enddo
693 end subroutine get_tcoff_line
694
695 subroutine interp_tcoff(xF,ipel,igridl,numR,Tlcoff)
696 double precision :: xF(numFL,numLP,ndim)
697 integer :: numR(numFL),ipel(numFL,numLP),igridl(numFL,numLP)
698 double precision :: Tlcoff(numFL)
699 integer :: iFL,iLP,ixO^L,ixI^L,ixc^L,ixb^L,ixc^D
700 integer :: igrid,j,ipmin,ipmax,igrid_nb
701 double precision :: dxb^D,dxMax^D,xb^L,Tcnow
702 double precision :: xFnow(ndim),xc(ndim)
703 integer :: weightIndex,idn^D,ixmax^ND
704 double precision :: ds,weight
705
706 weightindex=2
707
708 ^d&iximin^d=ixglo^d;
709 ^d&iximax^d=ixghi^d;
710 ^d&ixomin^d=ixmlo^d;
711 ^d&ixomax^d=ixmhi^d;
712
713 do ifl=1,numfl
714 ilp=1
715 tcnow=tlcoff(ifl)
716 do while (ilp<=numr(ifl))
717 ! find points in the same grid
718 ipmin=ilp
719 do while (ipel(ifl,ipmin)/=mype .and. ipmin<=numr(ifl))
720 ipmin=ipmin+1
721 enddo
722 igrid=igridl(ifl,ipmin)
723 ipmax=ipmin
724 do while (ipel(ifl,ipmax)==mype .and. igridl(ifl,ipmax+1)==igrid .and. ipmax<numr(ifl))
725 ipmax=ipmax+1
726 enddo
727
728 ! parameters for the grid
729 ^d&dxb^d=rnode(rpdx^d_,igrid);
730 ^d&dxmax^d=4*dxb^d;
731
732 do ilp=ipmin,ipmax
733 xfnow(:)=xf(ifl,ilp,:)
734 ^d&ixbmin^d=floor((xfnow(^d)-dxmax^d-ps(igrid)%x(ixomin^dd,^d))/dxb^d)+ixomin^d;
735 ^d&ixbmax^d=floor((xfnow(^d)+dxmax^d-ps(igrid)%x(ixomin^dd,^d))/dxb^d)+ixomin^d;
736
737 ! do interpolation inside the grid
738 {ixcmin^d=max(ixbmin^d,ixomin^d)\}
739 {ixcmax^d=min(ixbmax^d,ixomax^d)\}
740 xbmin^nd=rnode(rpxmin^nd_,igrid)
741 xbmax^nd=rnode(rpxmax^nd_,igrid)
742 ixmax^nd=floor((phys_trac_mask-xbmin^nd)/dxb^nd)+ixomin^nd
743 if (xbmax^nd>phys_trac_mask) ixcmax^nd=min(ixmax^nd,ixcmax^nd)
744 {do ixc^d=ixcmin^d,ixcmax^d\}
745 ds=0.d0
746 {ds=ds+(xfnow(^d)-ps(igrid)%x(ixc^dd,^d))**2\}
747 ds=sqrt(ds)
748 if(ds<1.0d-2*dxb1) then
749 weight=(1/(1.0d-2*dxb1))**weightindex
750 else
751 weight=(1/ds)**weightindex
752 endif
753 ps(igrid)%wextra(ixc^d,iw_tweight)=ps(igrid)%wextra(ixc^d,iw_tweight)+weight
754 ps(igrid)%wextra(ixc^d,iw_tcoff)=ps(igrid)%wextra(ixc^d,iw_tcoff)+weight*tcnow
755 {enddo\}
756
757 ! do interpolation in neighbor grids that have the same level and pe
758 {
759 if (ixbmin^d<ixomin^d) then
760 idn^dd=0;
761 idn^d=-1
762 if (neighbor(2,idn^dd,igrid)==mype .and. neighbor_type(idn^dd,igrid)==neighbor_sibling) then
763 igrid_nb=neighbor(1,idn^dd,igrid)
764 ixcmin^dd=max(ixbmin^dd,ixomin^dd);
765 ixcmax^dd=min(ixbmax^dd,ixomax^dd);
766 ixcmin^d=ixomax^d+(ixbmin^d-ixomin^d)
767 ixcmax^d=ixomax^d
768 xbmin^nd=rnode(rpxmin^nd_,igrid_nb)
769 xbmax^nd=rnode(rpxmax^nd_,igrid_nb)
770 ixmax^nd=floor((phys_trac_mask-xbmin^nd)/dxb^nd)+ixomin^nd
771 if (xbmax^nd>phys_trac_mask) ixcmax^nd=min(ixmax^nd,ixcmax^nd)
772
773 {do ixc^dd=ixcmin^dd,ixcmax^dd;}
774 ds=0.d0
775 xc(:)=ps(igrid_nb)%x(ixc^dd,:)
776 {ds=ds+(xfnow(^dd)-xc(^dd))**2;}
777 ds=sqrt(ds)
778 if(ds<1.0d-2*dxb1) then
779 weight=(1/(1.0d-2*dxb1))**weightindex
780 else
781 weight=(1/ds)**weightindex
782 endif
783 ps(igrid_nb)%wextra(ixc^dd,iw_tweight)=ps(igrid_nb)%wextra(ixc^dd,iw_tweight)+weight
784 ps(igrid_nb)%wextra(ixc^dd,iw_tcoff)=ps(igrid_nb)%wextra(ixc^dd,iw_tcoff)+weight*tcnow
785 {enddo;}
786 endif
787 endif
788
789 if (ixbmax^d>ixomin^d) then
790 idn^dd=0;
791 idn^d=1
792 if (neighbor(2,idn^dd,igrid)==mype .and. neighbor_type(idn^dd,igrid)==neighbor_sibling) then
793 igrid_nb=neighbor(1,idn^dd,igrid)
794 xbmin^nd=rnode(rpxmin^nd_,igrid_nb)
795 if (xbmin^nd<phys_trac_mask) then
796 ixcmin^dd=max(ixbmin^dd,ixomin^dd);
797 ixcmax^dd=min(ixbmax^dd,ixomax^dd);
798 ixcmin^d=ixomin^d
799 ixcmax^d=ixomin^d+(ixbmax^d-ixomax^d)
800 xbmax^nd=rnode(rpxmax^nd_,igrid_nb)
801 ixmax^nd=floor((phys_trac_mask-xbmin^nd)/dxb^nd)+ixomin^nd
802 if (xbmax^nd>phys_trac_mask) ixcmax^nd=min(ixmax^nd,ixcmax^nd)
803
804 {do ixc^dd=ixcmin^dd,ixcmax^dd;}
805 ds=0.d0
806 xc(:)=ps(igrid_nb)%x(ixc^dd,:)
807 {ds=ds+(xfnow(^dd)-xc(^dd))**2;}
808 ds=sqrt(ds)
809 if(ds<1.0d-2*dxb1) then
810 weight=(1/(1.0d-2*dxb1))**weightindex
811 else
812 weight=(1/ds)**weightindex
813 endif
814 ps(igrid_nb)%wextra(ixc^dd,iw_tweight)=ps(igrid_nb)%wextra(ixc^dd,iw_tweight)+weight
815 ps(igrid_nb)%wextra(ixc^dd,iw_tcoff)=ps(igrid_nb)%wextra(ixc^dd,iw_tcoff)+weight*tcnow
816 {enddo;}
817 endif
818 endif
819 endif
820 \}
821 enddo
822
823 ilp=ipmax+1
824 enddo
825 enddo
826
827 do j=1,ngrid_trac
828 igrid=trac_grid(j)
829 where(ps(igrid)%wextra(ixo^s,iw_tweight)>0.d0)
830 ps(igrid)%wextra(ixo^s,iw_tcoff)=ps(igrid)%wextra(ixo^s,iw_tcoff)/ps(igrid)%wextra(ixo^s,iw_tweight)
831 elsewhere
832 ps(igrid)%wextra(ixo^s,iw_tcoff)=t_bott
833 endwhere
834 enddo
835 end subroutine interp_tcoff
836
837 subroutine trac_after_setdt(tco,trac_alfa,T_peak, T_bott_in)
838 double precision, intent(in) :: trac_alfa,tco,T_peak, T_bott_in
839 ! default lower limit of cutoff temperature
840 t_bott = t_bott_in
841 select case(phys_trac_type)
842 case(0)
843 !> Test case, fixed cutoff temperature
844 !> do nothing here
845 case(1)
846 !> 1D TRAC method
847 call trac_simple(tco,trac_alfa,t_peak)
848 case(2)
849 !> LTRAC method, by iijima et al. 2021
850 !> do nothing here
851 call ltrac(t_peak)
852 case(3)
853 !> 2D or 3D TRACL(ine) method
854 call tracl(.false.,t_peak)
855 case(4)
856 !> 2D or 3D TRACB(lock) method
857 call tracb(.false.,t_peak)
858 case(5)
859 !> 2D or 3D TRACL(ine) method with mask
860 call tracl(.true.,t_peak)
861 case(6)
862 !> 2D or 3D TRACB(lock) method with mask
863 call tracb(.true.,t_peak)
864 case(7)
865 !> Johnston et al. 2021 local TRAC (clamp per-cell Tcoff)
866 call ltrac(t_peak)
867 case default
868 call mpistop("undefined TRAC method type")
869 end select
870 end subroutine trac_after_setdt
871
875
876 if(phys_trac) then
877 phys_trac_after_setdt => trac_after_setdt
878 if(phys_trac_type .eq. 3) then
879 if(mype .eq. 0) write(*,*) 'Using TRACL(ine) global method'
880 if(mype .eq. 0) write(*,*) 'By default, magnetic field lines are traced every 4 grid cells'
881 call init_trac_line(.false.)
882 end if
883 if(phys_trac_type .eq. 4) then
884 if(mype .eq. 0) write(*,*) 'Using TRACB(lock) global method'
885 if(mype .eq. 0) write(*,*) 'Currently, only valid in Cartesian uniform settings'
886 if(mype .eq. 0) write(*,*) 'By default, magnetic field lines are traced every 4 grid cells'
887 call init_trac_block(.false.)
888 end if
889 if(phys_trac_type .eq. 5) then
890 if(mype .eq. 0) write(*,*) 'Using TRACL(ine) method with a mask'
891 if(mype .eq. 0) write(*,*) 'By default, magnetic field lines are traced every 4 grid cells'
892 call init_trac_line(.true.)
893 end if
894 if(phys_trac_type .eq. 6) then
895 if(mype .eq. 0) write(*,*) 'Using TRACB(lock) method with a mask'
896 if(mype .eq. 0) write(*,*) 'Currently, only valid in Cartesian uniform settings'
897 if(mype .eq. 0) write(*,*) 'By default, magnetic field lines are traced every 4 grid cells'
898 call init_trac_block(.true.)
899 end if
900 end if
901 end subroutine initialize_trac_after_settree
902end module mod_trac
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
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer domain_nx
number of cells for each dimension in level-one mesh
integer icomm
The MPI communicator.
integer mype
The rank of the current MPI task.
integer ierrmpi
A global MPI error return code.
integer npe
The number of MPI tasks.
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
logical phys_trac
Use TRAC for MHD or 1D HD.
integer refine_max_level
Maximal number of AMR levels.
integer max_blocks
The maximum number of grid blocks in a processor.
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition mod_physics.t:4
procedure(sub_trac_after_setdt), pointer phys_trac_after_setdt
Definition mod_physics.t:62
subroutine, public initialize_trac_after_settree
Definition mod_trac.t:873
subroutine trace_field_multi(xfm, wpm, wlm, dl, numl, nump, nwp, nwl, forwardm, ftype, tcondi)