38 double precision ::
tmf
44 double precision,
public ::
mf_vmax = 3.d6
47 integer,
private,
protected :: rho_
50 integer,
allocatable,
private,
protected :: mom(:)
53 integer,
allocatable,
private,
protected :: mag(:)
72 character(len=*),
intent(in) :: files(:)
80 open(
unitpar, file=trim(files(n)), status=
"old")
131 double precision :: dvolume(ixG^T),dsurface(ixG^T),dvone
132 double precision :: dtfff,dtfff_pe,dtnew,dx^D
133 double precision :: cwsin_theta_new,cwsin_theta_old
134 double precision :: sum_jbb,sum_jbb_ipe,sum_j,sum_j_ipe,sum_l_ipe,sum_l
135 double precision :: f_i_ipe,f_i,volumepe,volume,tmpt,time_in
136 double precision,
external :: integral_grid
137 integer :: i,iigrid, igrid, idims,ix^D,hxM^LL,fhmf,tmpit,i^D
138 logical :: patchwi(ixG^T), stagger_flag
145 if(
mype==0)
write(*,*)
'Evolving to force-free field using magnetofricitonal method...'
155 if(i==0 .and.
it>0) i=
it
166 call mpistop(
"mf_log_mode must be 'auto', 'append', or 'replace'")
192 do iigrid=1,igridstail; igrid=igrids(iigrid);
209 do iigrid=1,igridstail; igrid=igrids(iigrid);
213 dtfff_pe=min(dtfff_pe,dtnew)
215 call mpi_allreduce(dtfff_pe,dtfff,1,mpi_double_precision,mpi_min, &
240 if(mod(i,10)==0)
then
248 do iigrid=1,igridstail; igrid=igrids(iigrid);
254 do iigrid=1,igridstail; igrid=igrids(iigrid);
260 write(*,*)
'<CW sin theta>:',cwsin_theta_new
261 write(*,*)
'<f_i>:',f_i
262 write(*,*)
'----------------------------------------------------------'
268 if(mod(i,10)/=0)
then
274 write (*,*)
'Reach maximum iteration step!'
275 write (*,*)
'The total iteration step is:', i
289 do iigrid=1,igridstail; igrid=igrids(iigrid);
290 ps(igrid)%w(ixg^t,mom(:))=zero
299 if(
mype==0)
write(*,*)
'Magnetofriction phase took : ',mpi_wtime()-time_in,
' sec'
310 do iigrid=1,igridstail; igrid=igrids(iigrid);
314 hxm^ll=
ixm^ll-
kr(idims,^d);
315 dsurface(
ixm^t)=dsurface(
ixm^t)+
block%surfaceC(hxm^t,idims)
318 call mask_inner(ixg^ll,
ixm^ll,ps(igrid)%w,ps(igrid)%x)
319 sum_jbb_ipe = sum_jbb_ipe+integral_grid_mf(ixg^ll,
ixm^ll,ps(igrid)%w,&
320 ps(igrid)%x,1,patchwi)
321 sum_j_ipe = sum_j_ipe+integral_grid_mf(ixg^ll,
ixm^ll,ps(igrid)%w,&
322 ps(igrid)%x,2,patchwi)
323 f_i_ipe=f_i_ipe+integral_grid_mf(ixg^ll,
ixm^ll,ps(igrid)%w,&
324 ps(igrid)%x,3,patchwi)
325 sum_l_ipe = sum_l_ipe+integral_grid_mf(ixg^ll,
ixm^ll,ps(igrid)%w,&
326 ps(igrid)%x,4,patchwi)
328 call mpi_allreduce(sum_jbb_ipe,sum_jbb,1,mpi_double_precision,&
330 call mpi_allreduce(sum_j_ipe,sum_j,1,mpi_double_precision,mpi_sum,&
332 call mpi_allreduce(f_i_ipe,f_i,1,mpi_double_precision,mpi_sum,&
334 call mpi_allreduce(sum_l_ipe,sum_l,1,mpi_double_precision,mpi_sum,&
336 call mpi_allreduce(volumepe,volume,1,mpi_double_precision,mpi_sum,&
340 cwsin_theta_new = sum_jbb/sum_j
348 subroutine mask_inner(ixI^L,ixO^L,w,x)
350 integer,
intent(in) :: ixI^L,ixO^L
351 double precision,
intent(in):: w(ixI^S,nw),x(ixI^S,1:ndim)
352 double precision :: xO^L
355 {xomin^d = xprobmin^d + 0.05d0*(xprobmax^d-xprobmin^d)\}
356 {xomax^d = xprobmax^d - 0.05d0*(xprobmax^d-xprobmin^d)\}
358 xomin^nd = xprobmin^nd
363 {
do ix^db=ixomin^db,ixomax^db\}
364 if({ x(ix^dd,^d) > xomin^d .and. x(ix^dd,^d) < xomax^d | .and. })
then
366 volumepe=volumepe+dvolume(ix^d)
368 patchwi(ix^d)=.false.
372 end subroutine mask_inner
374 subroutine printlog_mf
375 integer :: amode, status(MPI_STATUS_SIZE)
376 integer :: truncate_unit, ios
377 character(len=800) :: filename,filehead
378 character(len=2048) :: line,datastr
379 logical,
save :: logmfopened=.false.
380 logical :: logfile_exists
383 if(.not.logmfopened)
then
388 write(filename,
"(a,a)") trim(base_filename),
"_mflog.csv"
391 inquire(file=trim(filename),exist=logfile_exists)
395 open(newunit=truncate_unit,file=trim(filename),status=
'replace', &
396 action=
'write',iostat=ios)
397 if(ios/=0)
call mpistop(
'Unable to replace magnetofriction log file')
399 logfile_exists=.false.
402 amode=ior(mpi_mode_create,mpi_mode_wronly)
403 amode=ior(amode,mpi_mode_append)
404 call mpi_file_open(mpi_comm_self,filename,amode,mpi_info_null,fhmf,ierrmpi)
407 if(.not.logfile_exists)
then
408 filehead=
" itmf, dt, <f_i>, <CW sin theta>, <Current>, <Lorenz force>"
409 call mpi_file_write(fhmf,filehead,len_trim(filehead), &
410 mpi_character,status,ierrmpi)
411 call mpi_file_write(fhmf,achar(10),1,mpi_character,status,ierrmpi)
415 write(datastr,
'(i6,a)') i,
','
416 line=trim(line)//trim(datastr)
417 write(datastr,
'(es13.6,a)') dtfff,
','
418 line=trim(line)//trim(datastr)
419 write(datastr,
'(es13.6,a)') f_i,
','
420 line=trim(line)//trim(datastr)
421 write(datastr,
'(es13.6,a)') cwsin_theta_new,
','
422 line=trim(line)//trim(datastr)
423 write(datastr,
'(es13.6,a)') sum_j,
','
424 line=trim(line)//trim(datastr)
425 write(datastr,
'(es13.6)') sum_l
426 line=trim(line)//trim(datastr)//new_line(
'A')
427 call mpi_file_write(fhmf,line,len_trim(line),mpi_character,status,ierrmpi)
430 end subroutine printlog_mf
432 function integral_grid_mf(ixI^L,ixO^L,w,x,iw,patchwi)
435 integer,
intent(in) :: ixI^L,ixO^L,iw
436 double precision,
intent(in) :: x(ixI^S,1:ndim)
437 double precision,
intent(in) :: w(ixI^S,nw+nwauxio)
438 logical,
intent(in) :: patchwi(ixI^S)
440 double precision,
dimension(ixI^S,1:ndir) :: bvec,qvec,current
441 double precision :: integral_grid_mf,tmp(ixI^S),b_mag(ixI^S)
442 integer :: ix^D,i,idirmin,idir,jdir,kdir
444 integral_grid_mf=0.d0
449 bvec(ixi^s,:)=w(ixi^s,mag(:))+block%b0(ixi^s,mag(:),0)
451 bvec(ixi^s,:)=w(ixi^s,mag(:))
455 qvec(ixo^s,1:ndir)=zero
456 do idir=1,ndir;
do jdir=1,ndir;
do kdir=idirmin,3
457 if(lvc(idir,jdir,kdir)/=0)
then
458 tmp(ixo^s)=current(ixo^s,jdir)*bvec(ixo^s,kdir)
459 if(lvc(idir,jdir,kdir)==1)
then
460 qvec(ixo^s,idir)=qvec(ixo^s,idir)+tmp(ixo^s)
462 qvec(ixo^s,idir)=qvec(ixo^s,idir)-tmp(ixo^s)
467 {
do ix^db=ixomin^db,ixomax^db\}
468 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+sqrt(sum(qvec(ix^d,:)**2)/&
469 sum(bvec(ix^d,:)**2))*dvolume(ix^d)
474 {
do ix^db=ixomin^db,ixomax^db\}
475 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+sqrt(sum(current(ix^d,:)**2))*&
482 bvec(ixi^s,:)=w(ixi^s,mag(:))+block%b0(ixi^s,mag(:),0)
484 bvec(ixi^s,:)=w(ixi^s,mag(:))
486 call divvector(bvec,ixi^l,ixo^l,tmp)
487 {
do ix^db=ixomin^db,ixomax^db\}
488 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+abs(tmp(ix^d))*&
489 dvolume(ix^d)**2/sqrt(sum(bvec(ix^d,:)**2))/dsurface(ix^d)
494 bvec(ixi^s,:)=w(ixi^s,mag(:))+block%b0(ixi^s,mag(:),0)
496 bvec(ixi^s,:)=w(ixi^s,mag(:))
498 call curlvector(bvec,ixi^l,ixo^l,current,idirmin,1,ndir)
500 qvec(ixo^s,1:ndir)=zero
501 do idir=1,ndir;
do jdir=1,ndir;
do kdir=idirmin,3
502 if(lvc(idir,jdir,kdir)/=0)
then
503 tmp(ixo^s)=current(ixo^s,jdir)*bvec(ixo^s,kdir)
504 if(lvc(idir,jdir,kdir)==1)
then
505 qvec(ixo^s,idir)=qvec(ixo^s,idir)+tmp(ixo^s)
507 qvec(ixo^s,idir)=qvec(ixo^s,idir)-tmp(ixo^s)
512 {
do ix^db=ixomin^db,ixomax^db\}
513 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+sqrt(sum(qvec(ix^d,:)**2))*dvolume(ix^d)
517 end function integral_grid_mf
524 double precision,
intent(in) :: dtfff
525 double precision :: vhatmax,vhatmax_pe,vhatmaxgrid
526 integer :: i,iigrid, igrid
528 vhatmax_pe=smalldouble
529 do iigrid=1,igridstail; igrid=igrids(iigrid);
532 call vhat(ps(igrid)%w,ps(igrid)%x,ixg^
ll,
ixm^
ll,vhatmaxgrid)
533 vhatmax_pe=max(vhatmax_pe,vhatmaxgrid)
535 call mpi_allreduce(vhatmax_pe,vhatmax,1,mpi_double_precision,mpi_max, &
537 do iigrid=1,igridstail; igrid=igrids(iigrid);
546 subroutine vhat(w,x,ixI^L,ixO^L,vhatmaxgrid)
550 integer,
intent(in) :: ixI^L, ixO^L
551 double precision,
intent(inout) :: w(ixI^S,nw)
552 double precision,
intent(in) :: x(ixI^S,1:ndim)
553 double precision,
intent(out) :: vhatmaxgrid
555 double precision :: current(ixI^S,7-2*ndir:3),tmp(ixI^S),dxhm
556 double precision :: dxhms(ixO^S)
557 integer :: idirmin,idir,jdir,kdir
562 do idir=1,ndir;
do jdir=1,ndir;
do kdir=idirmin,3
563 if(
lvc(idir,jdir,kdir)/=0)
then
565 tmp(ixo^s)=current(ixo^s,jdir)*(w(ixo^s,mag(kdir))+
block%b0(ixo^s,kdir,0))
567 tmp(ixo^s)=current(ixo^s,jdir)*w(ixo^s,mag(kdir))
569 if(
lvc(idir,jdir,kdir)==1)
then
570 w(ixo^s,mom(idir))=w(ixo^s,mom(idir))+tmp(ixo^s)
572 w(ixo^s,mom(idir))=w(ixo^s,mom(idir))-tmp(ixo^s)
579 tmp(ixo^s)=1.d0/(sum((w(ixo^s,mag(:))+
block%b0(ixo^s,:,0))**2,dim=ndim+1)+smalldouble)
581 tmp(ixo^s)=1.d0/(sum(w(ixo^s,mag(:))**2,dim=ndim+1)+smalldouble)
587 w(ixo^s,mom(idir))=dxhm*w(ixo^s,mom(idir))*tmp(ixo^s)
590 dxhms(ixo^s)=dble(ndim)/sum(1.d0/
block%dx(ixo^s,:),dim=ndim+1)
592 w(ixo^s,mom(idir))=dxhms(ixo^s)*w(ixo^s,mom(idir))*tmp(ixo^s)
595 vhatmaxgrid=maxval(sqrt(sum(w(ixo^s,mom(:))**2,dim=ndim+1)))
602 integer,
intent(in) :: ixI^L, ixO^L
603 double precision,
intent(in) :: x(ixI^S,1:ndim),qdt,qvmax
604 double precision,
intent(inout) :: w(ixI^S,1:nw)
606 double precision :: dxhm,disbd(6),bfzone^D
607 double precision :: dxhms(ixO^S)
608 integer :: ix^D, idir
612 dxhm=dble(ndim)/(^d&1.0d0/
dxlevel(^d)+)
615 w(ixo^s,mom(:))=w(ixo^s,mom(:))*dxhm
617 dxhms(ixo^s)=dble(ndim)/sum(1.d0/
block%dx(ixo^s,:),dim=ndim+1)
618 dxhms(ixo^s)=
mf_cc*
mf_cy/qvmax*dxhms(ixo^s)/qdt
621 w(ixo^s,mom(idir))=w(ixo^s,mom(idir))*dxhms(ixo^s)
626 bfzone1=0.05d0*(xprobmax1-xprobmin1)
627 bfzone2=0.05d0*(xprobmax2-xprobmin2)
628 bfzone3=0.05d0*(xprobmax3-xprobmin3)
629 {
do ix^db=ixomin^db,ixomax^db\}
630 disbd(1)=x(ix^d,1)-xprobmin1
631 disbd(2)=xprobmax1-x(ix^d,1)
632 disbd(3)=x(ix^d,2)-xprobmin2
633 disbd(4)=xprobmax2-x(ix^d,2)
634 disbd(5)=x(ix^d,3)-xprobmin1
635 disbd(6)=xprobmax3-x(ix^d,3)
638 if(disbd(1)<bfzone1)
then
639 w(ix^d,mom(:))=(1.d0-((bfzone1-disbd(1))/bfzone1)**2)*w(ix^d,mom(:))
642 if(disbd(5)<bfzone3)
then
643 w(ix^d,mom(:))=(1.d0-((bfzone3-disbd(5))/bfzone3)**2)*w(ix^d,mom(:))
646 if(disbd(2)<bfzone1)
then
647 w(ix^d,mom(:))=(1.d0-((bfzone1-disbd(2))/bfzone1)**2)*w(ix^d,mom(:))
649 if(disbd(3)<bfzone2)
then
650 w(ix^d,mom(:))=(1.d0-((bfzone2-disbd(3))/bfzone2)**2)*w(ix^d,mom(:))
652 if(disbd(4)<bfzone2)
then
653 w(ix^d,mom(:))=(1.d0-((bfzone2-disbd(4))/bfzone2)**2)*w(ix^d,mom(:))
655 if(disbd(6)<bfzone3)
then
656 w(ix^d,mom(:))=(1.d0-((bfzone3-disbd(6))/bfzone3)**2)*w(ix^d,mom(:))
662 dxhms(ixo^s)=sqrt(sum(w(ixo^s,mom(:))**2,dim=ndim+1))/
mf_vmax+1.d-12
663 dxhms(ixo^s)=dtanh(dxhms(ixo^s))/dxhms(ixo^s)
665 w(ixo^s,mom(idir))=w(ixo^s,mom(idir))*dxhms(ixo^s)
677 integer,
intent(in) :: idim^LIM
678 double precision,
intent(in) :: qt, qdt
680 integer :: iigrid, igrid
685 do iigrid=1,igridstail; igrid=igrids(iigrid);
686 ps1(igrid)%w=ps(igrid)%w
705 do iigrid=1,igridstail; igrid=igrids(iigrid);
706 ps2(igrid)%w(ixg^t,1:nwflux)=0.75d0*ps(igrid)%w(ixg^t,1:nwflux)+0.25d0*&
707 ps1(igrid)%w(ixg^t,1:nwflux)
708 if (nw>nwflux) ps2(igrid)%w(ixg^t,nwflux+1:nw) = &
709 ps(igrid)%w(ixg^t,nwflux+1:nw)
714 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
715 ps(igrid)%w(ixg^t,1:nwflux)=1.0d0/3.0d0*ps(igrid)%w(ixg^t,1:nwflux)+&
716 2.0d0/3.0d0*ps2(igrid)%w(ixg^t,1:nwflux)
721 call mpistop(
"unkown time_stepper in advectmf")
726 subroutine advect1mf(method,dtin,dtfactor,idim^LIM,qtC,psa,qt,psb)
734 integer,
intent(in) :: idim^LIM
735 type(state) :: psa(max_blocks)
736 type(state) :: psb(max_blocks)
737 double precision,
intent(in) :: dtin,dtfactor, qtC, qt
738 integer,
intent(in) :: method(nlevelshi)
740 double precision :: qdt
741 integer :: iigrid, igrid, level, i^D
748 do iigrid=1,igridstail; igrid=igrids(iigrid);
753 psa(igrid)%w,qt,psb(igrid)%w)
793 integer,
intent(in) :: method
794 integer,
intent(in) :: igrid, ixG^L, idim^LIM
795 double precision,
intent(in) :: qdt, qtC, qt
796 double precision :: wCT(ixG^S,1:nw), w(ixG^S,1:nw)
797 double precision :: dx^D, fC(ixG^S,1:ndir,1:ndim)
804 ixo^l=ixg^l^lsubnghostcells;
810 call centdiff4mf(qdt,ixg^l,ixo^l,idim^lim,qtc,wct,qt,w,fc,dx^d,ps(igrid)%x)
815 call tvdlfmf(qdt,ixg^l,ixo^l,idim^lim,qtc,wct,qt,w,fc,dx^d,ps(igrid)%x)
818 call hancockmf(qdt,ixg^l,ixo^l,idim^lim,qtc,wct,qt,w,dx^d,ps(igrid)%x)
823 call fdmf(qdt,ixg^l,ixo^l,idim^lim,qtc,wct,qt,w,fc,dx^d,ps(igrid)%x)
825 call mpistop(
"unknown flux scheme in advect1_gridmf")
834 subroutine upwindlrmf(ixI^L,ixL^L,ixR^L,idim,w,wCT,wLC,wRC,x)
840 integer,
intent(in) :: ixI^L, ixL^L, ixR^L, idim
841 double precision,
dimension(ixI^S,1:nw) :: w, wCT
842 double precision,
dimension(ixI^S,1:nw) :: wLC, wRC
843 double precision,
dimension(ixI^S,1:ndim) :: x
845 double precision :: ldw(ixI^S), rdw(ixI^S), dwC(ixI^S)
846 integer :: jxR^L, ixC^L, jxC^L, iw
849 call mp5limiter(ixi^l,ixl^l,idim,w,wlc,wrc)
851 call ppmlimiter(ixi^l,
ixm^
ll,idim,w,wct,wlc,wrc)
853 jxr^l=ixr^l+
kr(idim,^
d);
854 ixcmax^
d=jxrmax^
d; ixcmin^
d=ixlmin^
d-
kr(idim,^
d);
855 jxc^l=ixc^l+
kr(idim,^
d);
859 w(ixcmin^
d:jxcmax^
d,iw)=dlog10(w(ixcmin^
d:jxcmax^
d,iw))
860 wlc(ixl^s,iw)=dlog10(wlc(ixl^s,iw))
861 wrc(ixr^s,iw)=dlog10(wrc(ixr^s,iw))
864 dwc(ixc^s)=w(jxc^s,iw)-w(ixc^s,iw)
868 wlc(ixl^s,iw)=wlc(ixl^s,iw)+half*ldw(ixl^s)
869 wrc(ixr^s,iw)=wrc(ixr^s,iw)-half*rdw(jxr^s)
872 w(ixcmin^
d:jxcmax^
d,iw)=10.0d0**w(ixcmin^
d:jxcmax^
d,iw)
873 wlc(ixl^s,iw)=10.0d0**wlc(ixl^s,iw)
874 wrc(ixr^s,iw)=10.0d0**wrc(ixr^s,iw)
886 integer,
intent(in) :: ixI^L, ixO^L, idir, idim
887 double precision,
intent(in) :: w(ixI^S,nw)
888 double precision,
intent(in) :: x(ixI^S,1:ndim)
889 double precision,
intent(out) :: f(ixI^S)
896 f(ixo^s)=w(ixo^s,mom(idim))*w(ixo^s,mag(idir))-w(ixo^s,mag(idim))*w(ixo^s,mom(idir))
899 +w(ixo^s,mom(idim))*
block%B0(ixo^s,idir,idim)&
900 -w(ixo^s,mom(idir))*
block%B0(ixo^s,idim,idim)
906 subroutine tvdlfmf(qdt,ixI^L,ixO^L,idim^LIM,qtC,wCT,qt,wnew,fC,dx^D,x)
912 double precision,
intent(in) :: qdt, qtC, qt, dx^D
913 integer,
intent(in) :: ixI^L, ixO^L, idim^LIM
914 double precision,
dimension(ixI^S,1:ndim),
intent(in) :: x
915 double precision,
dimension(ixI^S,1:nw) :: wCT, wnew
916 double precision,
dimension(ixI^S,1:ndir,1:ndim) :: fC
918 double precision,
dimension(ixI^S,1:nw) :: wLC, wRC, wmean
919 double precision,
dimension(ixI^S) :: fLC, fRC
920 double precision,
dimension(ixI^S) :: cmaxC
921 double precision :: dxinv(1:ndim), inv_volume(ixO^S)
922 integer :: idims, idir, ix^L, hxO^L, ixC^L, ixCR^L, jxC^L, kxC^L, kxR^L
928 ix^l=ix^l^ladd2*
kr(idims,^d);
930 if (ixi^l^ltix^l|.or.|.or.) &
931 call mpistop(
"Error in tvdlfmf: Nonconforming input limits")
933 ^d&dxinv(^d)=-qdt/dx^d;
938 hxo^l=ixo^l-
kr(idims,^d);
940 ixcmax^d=ixomax^d; ixcmin^d=hxomin^d;
942 jxc^l=ixc^l+
kr(idims,^d);
943 kxcmin^d=iximin^d; kxcmax^d=iximax^d-
kr(idims,^d);
944 kxr^l=kxc^l+
kr(idims,^d);
947 wrc(kxc^s,1:nwflux)=wct(kxr^s,1:nwflux)
948 wlc(kxc^s,1:nwflux)=wct(kxc^s,1:nwflux)
950 call upwindlrmf(ixi^l,ixcr^l,ixcr^l,idims,wct,wct,wlc,wrc,x)
955 wmean=0.5d0*(wlc+wrc)
963 flc(ixc^s)=half*(flc(ixc^s)+frc(ixc^s))
966 if (idir==idims)
then
967 flc(ixc^s)=flc(ixc^s)-
mf_tvdlfeps*
tvdlfeps*cmaxc(ixc^s)*half*(wrc(ixc^s,mag(idir))-wlc(ixc^s,mag(idir)))
970 fc(ixc^s,idir,idims)=flc(ixc^s)
972 fc(ixc^s,idir,idims)=
block%surfaceC(ixc^s,idims)*flc(ixc^s)
981 hxo^l=ixo^l-
kr(idims,^d);
984 fc(ixi^s,:,idims)=dxinv(idims)*fc(ixi^s,:,idims)
985 wnew(ixo^s,mag(:))=wnew(ixo^s,mag(:)) &
986 + (fc(ixo^s,:,idims)-fc(hxo^s,:,idims))
988 inv_volume = 1.0d0/
block%dvolume(ixo^s)
989 fc(ixi^s,:,idims)=-qdt*fc(ixi^s,:,idims)
992 wnew(ixo^s,mag(idir))=wnew(ixo^s,mag(idir)) + (fc(ixo^s,idir,idims)-fc(hxo^s,idir,idims)) * &
1000 call divbclean(qdt,ixi^l,ixo^l,wct,wnew,x)
1004 subroutine hancockmf(qdt,ixI^L,ixO^L,idim^LIM,qtC,wCT,qt,wnew,dx^D,x)
1013 integer,
intent(in) :: ixI^L, ixO^L, idim^LIM
1014 double precision,
intent(in) :: qdt, qtC, qt, dx^D, x(ixI^S,1:ndim)
1015 double precision,
intent(inout) :: wCT(ixI^S,1:nw), wnew(ixI^S,1:nw)
1017 double precision,
dimension(ixI^S,1:nw) :: wLC, wRC
1018 double precision,
dimension(ixI^S) :: fLC, fRC
1019 double precision :: dxinv(1:ndim)
1020 integer :: idims, idir, ix^L, hxO^L, ixtest^L
1025 ix^l=ix^l^laddkr(idims,^d);
1027 if (ixi^l^ltix^l|.or.|.or.) &
1028 call mpistop(
"Error in Hancockmf: Nonconforming input limits")
1030 ^d&dxinv(^d)=-qdt/dx^d;
1036 hxo^l=ixo^l-
kr(idims,^d);
1038 wrc(hxo^s,1:nwflux)=wct(ixo^s,1:nwflux)
1039 wlc(ixo^s,1:nwflux)=wct(ixo^s,1:nwflux)
1041 call upwindlrmf(ixi^l,ixo^l,hxo^l,idims,wct,wct,wlc,wrc,x)
1046 call getfluxmf(wrc,x,ixi^l,hxo^l,idir,idims,frc)
1047 call getfluxmf(wlc,x,ixi^l,ixo^l,idir,idims,flc)
1050 wnew(ixo^s,mag(idir))=wnew(ixo^s,mag(idir))+dxinv(idims)* &
1051 (flc(ixo^s)-frc(hxo^s))
1053 wnew(ixo^s,mag(idir))=wnew(ixo^s,mag(idir))-qdt/
block%dvolume(ixo^s) &
1054 *(
block%surfaceC(ixo^s,idims)*flc(ixo^s) &
1055 -
block%surfaceC(hxo^s,idims)*frc(hxo^s))
1065 subroutine fdmf(qdt,ixI^L,ixO^L,idim^LIM,qtC,wCT,qt,wnew,fC,dx^D,x)
1067 double precision,
intent(in) :: qdt, qtC, qt, dx^D
1068 integer,
intent(in) :: ixI^L, ixO^L, idim^LIM
1069 double precision,
dimension(ixI^S,1:ndim),
intent(in) :: x
1071 double precision,
dimension(ixI^S,1:nw),
intent(inout) :: wCT, wnew
1072 double precision,
dimension(ixI^S,1:ndir,1:ndim),
intent(out) :: fC
1074 double precision,
dimension(ixI^S) :: fCT
1075 double precision,
dimension(ixI^S,1:nw) :: fm, fp, fmR, fpL
1076 double precision,
dimension(ixI^S) :: v
1077 double precision :: dxinv(1:ndim)
1078 integer :: idims, idir, ixC^L, ix^L, hxO^L, ixCR^L
1080 ^d&dxinv(^d)=-qdt/dx^d;
1087 hxo^l=ixo^l-
kr(idims,^d);
1089 ixmax^d=ixomax^d; ixmin^d=hxomin^d;
1093 call getfluxmf(wct,x,ixg^
ll,ixcr^l,idir,idims,fct)
1105 fc(ix^s,idir,idims) = dxinv(idims) * (fpl(ix^s,mag(idir)) + fmr(ix^s,mag(idir)))
1106 wnew(ixo^s,mag(idir))=wnew(ixo^s,mag(idir))+ &
1107 (fc(ixo^s,idir,idims)-fc(hxo^s,idir,idims))
1109 fc(ix^s,idir,idims)=-qdt*
block%surfaceC(ix^s,idims) * (fpl(ix^s,mag(idir)) + fmr(ix^s,mag(idir)))
1110 wnew(ixo^s,mag(idir))=wnew(ixo^s,mag(idir))+ &
1111 (fc(ixo^s,idir,idims)-fc(hxo^s,idir,idims))/
block%dvolume(ixo^s)
1118 call divbclean(qdt,ixi^l,ixo^l,wct,wnew,x)
1126 integer,
intent(in) :: ixI^L, iL^L, idims
1127 double precision,
intent(in) :: w(ixI^S,1:nw)
1129 double precision,
intent(out) :: wLC(ixI^S,1:nw)
1131 double precision :: ldw(ixI^S), dwC(ixI^S)
1132 integer :: jxR^L, ixC^L, jxC^L, kxC^L, iw
1136 call mp5limiterl(ixi^l,il^l,idims,w,wlc)
1138 call weno5limiterl(ixi^l,il^l,idims,w,wlc,1)
1140 call weno5limiterl(ixi^l,il^l,idims,w,wlc,2)
1143 kxcmin^
d=iximin^
d; kxcmax^
d=iximax^
d-
kr(idims,^
d);
1145 wlc(kxc^s,1:nwflux) = w(kxc^s,1:nwflux)
1147 jxr^l=il^l+
kr(idims,^
d);
1149 ixcmax^
d=jxrmax^
d; ixcmin^
d=ilmin^
d-
kr(idims,^
d);
1150 jxc^l=ixc^l+
kr(idims,^
d);
1153 dwc(ixc^s)=w(jxc^s,iw)-w(ixc^s,iw)
1157 wlc(il^s,iw)=wlc(il^s,iw)+half*ldw(il^s)
1167 integer,
intent(in) :: ixI^L, iL^L, idims
1168 double precision,
intent(in) :: w(ixI^S,1:nw)
1170 double precision,
intent(out) :: wRC(ixI^S,1:nw)
1172 double precision :: rdw(ixI^S), dwC(ixI^S)
1173 integer :: jxR^L, ixC^L, jxC^L, kxC^L, kxR^L, iw
1177 call mp5limiterr(ixi^l,il^l,idims,w,wrc)
1179 call weno5limiterr(ixi^l,il^l,idims,w,wrc,1)
1181 call weno5limiterr(ixi^l,il^l,idims,w,wrc,2)
1184 kxcmin^
d=iximin^
d; kxcmax^
d=iximax^
d-
kr(idims,^
d);
1185 kxr^l=kxc^l+
kr(idims,^
d);
1187 wrc(kxc^s,1:nwflux)=w(kxr^s,1:nwflux)
1189 jxr^l=il^l+
kr(idims,^
d);
1190 ixcmax^
d=jxrmax^
d; ixcmin^
d=ilmin^
d-
kr(idims,^
d);
1191 jxc^l=ixc^l+
kr(idims,^
d);
1194 dwc(ixc^s)=w(jxc^s,iw)-w(ixc^s,iw)
1197 wrc(il^s,iw)=wrc(il^s,iw)-half*rdw(jxr^s)
1203 subroutine centdiff4mf(qdt,ixI^L,ixO^L,idim^LIM,qtC,wCT,qt,w,fC,dx^D,x)
1212 integer,
intent(in) :: ixI^L, ixO^L, idim^LIM
1213 double precision,
intent(in) :: qdt, qtC, qt, dx^D
1214 double precision :: wCT(ixI^S,1:nw), w(ixI^S,1:nw)
1215 double precision,
intent(in) :: x(ixI^S,1:ndim)
1216 double precision :: fC(ixI^S,1:ndir,1:ndim)
1218 double precision :: v(ixI^S,ndim), f(ixI^S)
1219 double precision,
dimension(ixI^S,1:nw) :: wLC, wRC
1220 double precision,
dimension(ixI^S) :: vLC, vRC,cmaxLC,cmaxRC
1221 double precision :: dxinv(1:ndim)
1222 integer :: idims, idir, idirmin,ix^D
1223 integer :: ix^L, hxO^L, ixC^L, jxC^L, hxC^L, kxC^L, kkxC^L, kkxR^L
1228 ix^l=ix^l^ladd2*
kr(idims,^d);
1231 if (ixi^l^ltix^l|.or.|.or.)
then
1232 call mpistop(
"Error in evolve_CentDiff4: Non-conforming input limits")
1234 ^d&dxinv(^d)=-qdt/dx^d;
1239 ix^l=ixo^l^ladd2*
kr(idims,^d);
1240 hxo^l=ixo^l-
kr(idims,^d);
1242 ixcmin^d=hxomin^d; ixcmax^d=ixomax^d;
1243 hxc^l=ixc^l-
kr(idims,^d);
1244 jxc^l=ixc^l+
kr(idims,^d);
1245 kxc^l=ixc^l+2*
kr(idims,^d);
1247 kkxcmin^d=iximin^d; kkxcmax^d=iximax^d-
kr(idims,^d);
1248 kkxr^l=kkxc^l+
kr(idims,^d);
1249 wrc(kkxc^s,1:nwflux)=wct(kkxr^s,1:nwflux)
1250 wlc(kkxc^s,1:nwflux)=wct(kkxc^s,1:nwflux)
1252 call upwindlrmf(ixi^l,ixc^l,ixc^l,idims,wct,wct,wlc,wrc,x)
1258 vlc(ixc^s)=max(cmaxrc(ixc^s),cmaxlc(ixc^s))
1262 call getfluxmf(wct,x,ixi^l,ix^l,idir,idims,f)
1265 fc(ixc^s,idir,idims)=(-f(kxc^s)+7.0d0*(f(jxc^s)+f(ixc^s))-f(hxc^s))/12.0d0
1270 *(wrc(ixc^s,mag(idir))-wlc(ixc^s,mag(idir)))
1273 fc(ixc^s,idir,idims)=dxinv(idims)*fc(ixc^s,idir,idims)
1275 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))+(fc(ixo^s,idir,idims)-fc(hxo^s,idir,idims))
1277 fc(ixc^s,idir,idims)=-qdt*
block%surfaceC(ixc^s,idims)*fc(ixc^s,idir,idims)
1278 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))+ &
1279 (fc(ixo^s,idir,idims)-fc(hxo^s,idir,idims))/
block%dvolume(ixo^s)
1294 integer,
intent(in) :: ixI^L, ixO^L
1295 double precision,
intent(in) :: x(ixI^S,1:ndim)
1296 double precision,
intent(inout) :: w(ixI^S,1:nw), dtnew
1298 double precision :: courantmax, dxinv(1:ndim)
1299 double precision :: cmax(ixI^S),tmp(ixI^S),alfven(ixI^S)
1310 tmp(ixo^s)=cmax(ixo^s)/
block%dx(ixo^s,idims)
1311 courantmax=max(courantmax,maxval(tmp(ixo^s)))
1313 tmp(ixo^s)=cmax(ixo^s)*dxinv(idims)
1314 courantmax=max(courantmax,maxval(tmp(ixo^s)))
1318 if (courantmax>smalldouble) dtnew=min(dtnew,
mf_cc/courantmax)
1325 logical :: new_cmax,needcmin
1326 integer,
intent(in) :: ixI^L, ixO^L, idims
1327 double precision,
intent(in) :: w(ixI^S,1:nw)
1328 double precision,
intent(out) :: cmax(ixI^S)
1332 cmax(ixo^s)=sqrt(sum((w(ixo^s,mag(:))+
block%b0(ixo^s,:,0))**2,dim=
ndim+1)/w(ixo^s,rho_))
1334 cmax(ixo^s)=sqrt(sum(w(ixo^s,mag(:))**2,dim=
ndim+1)/w(ixo^s,rho_))
1336 cmax(ixo^s)=cmax(ixo^s)+abs(w(ixo^s,mom(idims)))
1345 integer,
intent(in) :: ixI^L, ixO^L
1346 double precision,
intent(in) :: x(ixI^S,1:ndim),wCT(ixI^S,1:nw),qdt
1347 double precision,
intent(inout) :: w(ixI^S,1:nw)
1348 double precision :: divb(ixI^S),graddivb(ixI^S),bdivb(ixI^S,1:ndir)
1349 integer :: idims, ix^L, ixp^L, i^D, iside
1360 call gradient(divb,ixi^l,ixp^l,idims,graddivb)
1366 graddivb(ixp^s)=graddivb(ixp^s)*
mf_cdivb &
1367 /(^d&1.0d0/
block%dx(ixp^s,^d)**2+)
1374 w(ixp^s,mag(idims))=w(ixp^s,mag(idims))+&
1385 integer,
intent(in) :: ixI^L, ixO^L
1386 double precision,
intent(in) :: qdt, x(ixI^S,1:ndim)
1387 double precision,
intent(inout) :: wCT(ixI^S,1:nw), w(ixI^S,1:nw)
1389 double precision :: tmp(ixI^S)
1391 integer :: mr_,mphi_
1392 integer :: br_,bphi_
1394 mr_=mom(1); mphi_=mom(1)-1+
phi_
1395 br_=mag(1); bphi_=mag(1)-1+
phi_
1401 tmp(ixo^s)=(wct(ixo^s,bphi_)*wct(ixo^s,mom(1)) &
1402 -wct(ixo^s,br_)*wct(ixo^s,mom(3)))
1403 w(ixo^s,bphi_)=w(ixo^s,bphi_)+qdt*tmp(ixo^s)/x(ixo^s,1)
1409 tmp(ixo^s)= wct(ixo^s,mom(1))*wct(ixo^s,mag(2)) &
1410 -wct(ixo^s,mom(2))*wct(ixo^s,mag(1))
1412 tmp(ixo^s)=tmp(ixo^s)+wct(ixo^s,mom(1))*
block%b0(ixo^s,2,0) &
1413 -wct(ixo^s,mom(2))*
block%b0(ixo^s,1,0)
1416 w(ixo^s,mag(2))=w(ixo^s,mag(2))+qdt*tmp(ixo^s)/x(ixo^s,1)
1421 tmp(ixo^s)=wct(ixo^s,mom(1))*wct(ixo^s,mag(3)) &
1422 -wct(ixo^s,mom(3))*wct(ixo^s,mag(1)){^nooned &
1423 -(wct(ixo^s,mom(3))*wct(ixo^s,mag(2)) &
1424 -wct(ixo^s,mom(2))*wct(ixo^s,mag(3)))*dcos(x(ixo^s,2)) &
1427 tmp(ixo^s)=tmp(ixo^s)+wct(ixo^s,mom(1))*
block%b0(ixo^s,3,0) &
1428 -wct(ixo^s,mom(3))*
block%b0(ixo^s,1,0){^nooned &
1429 -(wct(ixo^s,mom(3))*
block%b0(ixo^s,2,0) &
1430 -wct(ixo^s,mom(2))*
block%b0(ixo^s,3,0))*dcos(x(ixo^s,2)) &
1434 w(ixo^s,mag(3))=w(ixo^s,mag(3))+qdt*tmp(ixo^s)/x(ixo^s,1)
1447 integer :: ixO^L, idirmin, ixI^L
1448 double precision :: w(ixI^S,1:nw)
1451 double precision :: current(ixI^S,7-2*ndir:3),bvec(ixI^S,1:ndir)
1456 bvec(ixi^s,1:ndir)=w(ixi^s,mag(1:ndir))
1458 call curlvector(bvec,ixi^l,ixo^l,current,idirmin,idirmin0,ndir)
1460 if(
b0field) current(ixo^s,idirmin0:3)=current(ixo^s,idirmin0:3)+&
1461 block%J0(ixo^s,idirmin0:3)
1470 integer,
intent(in) :: ixI^L, ixO^L
1471 double precision,
intent(in) :: w(ixI^S,1:nw)
1472 double precision :: divb(ixI^S)
1474 double precision :: bvec(ixI^S,1:ndir)
1476 bvec(ixi^s,:)=w(ixi^s,mag(:))
subroutine, public resettree
reset AMR and (de)allocate boundary flux storage at level changes
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Module for flux conservation near refinement boundaries.
subroutine, public init_comm_fix_conserve(idimlim, nwfluxin)
subroutine, public recvflux(idimlim)
subroutine, public sendflux(idimlim)
subroutine, public store_flux(igrid, fc, idimlim, nwfluxin)
subroutine, public fix_conserve(psb, idimlim, nw0, nwfluxin)
Module with geometry-related routines (e.g., divergence, curl)
subroutine divvector(qvec, ixil, ixol, divq, nth_in)
integer, parameter spherical
integer, parameter cylindrical
subroutine curlvector(qvec, ixil, ixol, curlvec, idirmin, idirmin0, ndir0, fourthorder)
Calculate curl of a vector qvec within ixL Options to employ standard second order CD evaluations use...
subroutine gradient(q, ixil, ixol, idir, gradq, nth_in)
subroutine divvectors(qvec, ixil, ixol, divq)
Calculate divergence of a vector qvec within ixL using limited extrapolation to cell edges.
update ghost cells of all blocks including physical boundaries
integer, dimension(0:3^d &), target type_recv_p_p1
integer, dimension( :^d &), pointer type_recv_r
integer, dimension(-1:1^d &), target type_send_srl_p1
integer, dimension(-1:1^d &), target type_send_r_p2
subroutine getbc(time, qdt, psb, nwstart, nwbc)
do update ghost cells of all blocks including physical boundaries
integer, dimension(0:3^d &), target type_send_p_f
integer, dimension( :^d &), pointer type_send_p
integer, dimension(0:3^d &), target type_recv_p_p2
integer, dimension( :^d &), pointer type_send_srl
integer, dimension(-1:1^d &), target type_send_r_p1
integer, dimension(-1:1^d &), target type_send_srl_p2
subroutine create_bc_mpi_datatype(nwstart, nwbc)
integer, dimension(0:3^d &), target type_send_p_p2
integer, dimension(0:3^d &), target type_recv_r_f
integer, dimension(-1:1^d &), target type_recv_srl_f
integer, dimension(-1:1^d &), target type_send_r_f
integer, dimension(-1:1^d &), target type_send_srl_f
integer, dimension(0:3^d &), target type_send_p_p1
integer, dimension( :^d &), pointer type_send_r
integer, dimension(0:3^d &), target type_recv_r_p1
integer, dimension(0:3^d &), target type_recv_r_p2
integer, dimension(-1:1^d &), target type_recv_srl_p2
integer, dimension( :^d &), pointer type_recv_p
integer, dimension(-1:1^d &), target type_recv_srl_p1
integer, dimension(0:3^d &), target type_recv_p_f
integer, dimension( :^d &), pointer type_recv_srl
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.
double precision tvdlfeps
integer, dimension(:), allocatable typepred1
The spatial discretization for the predictor step when using a two step PC method.
integer, parameter fs_tvdlf
integer, dimension(3, 3, 3) lvc
Levi-Civita tensor.
integer, parameter unitpar
file handle for IO
double precision global_time
The global simulation time.
integer istep
Index of the sub-step in a multi-step time integrator.
integer, dimension(3, 3) kr
Kronecker delta tensor.
integer, parameter threestep
integer snapshotini
Resume from the snapshot with this index.
integer it
Number of time steps taken.
logical, dimension(:), allocatable loglimit
integer ditregrid
Reconstruct the AMR grid once every ditregrid iteration(s)
integer, parameter ndim
Number of spatial dimensions for grid variables.
logical stagger_grid
True for using stagger grid.
double precision cmax_global
global fastest wave speed needed in fd scheme and glm method
character(len=std_len), dimension(:), allocatable par_files
Which par files are used as input.
integer icomm
The MPI communicator.
integer b0i
background magnetic field location indicator
integer mype
The rank of the current MPI task.
character(len=std_len) typediv
integer, parameter plevel_
double precision dt
global time step
integer ndir
Number of spatial dimensions (components) for vector variables.
integer ixm
the mesh range of a physical block without ghost cells
integer ierrmpi
A global MPI error return code.
integer, dimension(:), allocatable flux_method
Which flux scheme of spatial discretization to use (per grid level)
double precision, dimension(:), allocatable, parameter d
logical slab
Cartesian geometry or not.
double precision unit_velocity
Physical scaling factor for velocity.
logical prolongprimitive
prolongate primitive variables in level-jump ghost cells
logical b0field
split magnetic field as background B0 field
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
integer, dimension(:), allocatable type_limiter
Type of slope limiter used for reconstructing variables on cell edges.
integer, parameter twostep
integer, parameter onestep
integer nghostcells
Number of ghost cells surrounding a grid.
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
integer t_stepper
time stepper type
integer, parameter fs_cd4
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
integer refine_max_level
Maximal number of AMR levels.
integer, parameter fs_hancock
integer, dimension(:,:), allocatable node
Module with slope/flux limiters.
integer, parameter limiter_ppm
subroutine dwlimiter2(dwc, ixil, ixcl, idims, typelim, ldw, rdw)
Limit the centered dwC differences within ixC for iw in direction idim. The limiter is chosen accordi...
integer, parameter limiter_weno5
integer, parameter limiter_wenoz5
integer, parameter limiter_mp5
module mod_magnetofriction.t Purpose: use magnetofrictional method to relax 3D magnetic field to forc...
subroutine fdmf(qdt, ixil, ixol, idimlim, qtc, wct, qt, wnew, fc, dxd, x)
subroutine getdtfff_courant(w, x, ixil, ixol, dtnew)
subroutine hancockmf(qdt, ixil, ixol, idimlim, qtc, wct, qt, wnew, dxd, x)
subroutine getfluxmf(w, x, ixil, ixol, idir, idim, f)
subroutine magnetofriction
subroutine reconstructrmf(ixil, ill, idims, w, wrc)
subroutine getcmaxfff(w, ixil, ixol, idims, cmax)
subroutine divbclean(qdt, ixil, ixol, wct, w, x)
Clean divergence of magnetic field by Janhunen's and Linde's source terms.
subroutine centdiff4mf(qdt, ixil, ixol, idimlim, qtc, wct, qt, w, fc, dxd, x)
double precision mf_tvdlfeps
TVDLF dissipation coefficient controls the dissipation term.
character(len=16) mf_log_mode
How to open the MF diagnostics CSV: auto, append, or replace.
subroutine magnetofriction_init()
Initialize the module.
double precision, public mf_vmax
maximal limit of magnetofrictional velocity in cm s^-1 (Pomoell 2019 A&A)
subroutine vhat(w, x, ixil, ixol, vhatmaxgrid)
double precision tmf
time in magnetofriction process
subroutine get_current(w, ixil, ixol, idirmin, current)
Calculate idirmin and the idirmin:3 components of the common current array make sure that dxlevel(^D)...
double precision mf_cy_max
subroutine addgeometrymf(qdt, ixil, ixol, wct, w, x)
logical mf_continue_run
Whether this run continues an existing MF diagnostics series.
subroutine frictional_velocity(w, x, ixil, ixol, qvmax, qdt)
double precision mf_cdivb
divb cleaning coefficient controls diffusion speed of divb
subroutine upwindlrmf(ixil, ixll, ixrl, idim, w, wct, wlc, wrc, x)
subroutine mf_velocity_update(dtfff)
double precision cmax_mype
maximal speed for fd scheme
subroutine process1_gridmf(method, igrid, qdt, ixgl, idimlim, qtc, wct, qt, w)
subroutine advect1mf(method, dtin, dtfactor, idimlim, qtc, psa, qt, psb)
double precision mf_cy
frictional velocity coefficient
logical fix_conserve_at_step
subroutine advectmf(idimlim, qt, qdt)
double precision mf_tvdlfeps_min
character(len=256) mf_log_filename
Optional diagnostics filename; empty uses <base_filename>_mflog.csv.
subroutine tvdlfmf(qdt, ixil, ixol, idimlim, qtc, wct, qt, wnew, fc, dxd, x)
double precision mf_cdivb_max
double precision mf_cc
stability coefficient controls numerical stability
subroutine mf_params_read(files)
Read this module"s parameters from a file.
double precision cmax_global
maximal speed for fd scheme
subroutine reconstructlmf(ixil, ill, idims, w, wlc)
subroutine get_divb(w, ixil, ixol, divb)
Calculate div B within ixO.
This module defines the procedures of a physics module. It contains function pointers for the various...
procedure(sub_convert), pointer phys_to_primitive
procedure(sub_convert), pointer phys_to_conserved
Module with all the methods that users can customize in AMRVAC.
procedure(p_no_args), pointer usr_before_main_loop