12 double precision,
public ::
mf_nu = 1.
d-15
15 double precision,
public ::
mf_vmax = 3.d6
25 double precision,
public ::
mf_eta = 0.0d0
31 double precision :: divbdiff = 0.8d0
40 integer,
allocatable,
public,
protected ::
mom(:)
43 integer,
public,
protected :: ^
c&m^C_
46 integer,
public,
protected :: ^
c&b^C_
49 integer,
public,
protected ::
psi_
55 integer,
parameter :: divb_none = 0
56 integer,
parameter :: divb_multigrid = -1
57 integer,
parameter :: divb_glm = 1
58 integer,
parameter :: divb_powel = 2
59 integer,
parameter :: divb_janhunen = 3
60 integer,
parameter :: divb_linde = 4
61 integer,
parameter :: divb_lindejanhunen = 5
62 integer,
parameter :: divb_lindepowel = 6
63 integer,
parameter :: divb_lindeglm = 7
64 integer,
parameter :: divb_ct = 8
70 logical,
public,
protected ::
mf_glm = .false.
85 logical :: compactres = .false.
94 character(len=std_len),
public,
protected ::
typedivbfix =
'ct'
97 character(len=std_len),
public,
protected ::
type_ct =
'average'
100 character(len=std_len) :: typedivbdiff =
'all'
120 subroutine mf_read_params(files)
123 character(len=*),
intent(in) :: files(:)
134 do n = 1,
size(files)
135 open(
unitpar, file=trim(files(n)), status=
"old")
136 read(
unitpar, mf_list,
end=111)
140 end subroutine mf_read_params
143 subroutine mf_write_info(fh)
145 integer,
intent(in) :: fh
146 integer,
parameter :: n_par = 1
147 double precision :: values(n_par)
148 character(len=name_len) :: names(n_par)
149 integer,
dimension(MPI_STATUS_SIZE) :: st
152 call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
156 call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
157 call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
158 end subroutine mf_write_info
179 type_divb = divb_none
182 type_divb = divb_multigrid
184 mg%operator_type = mg_laplacian
191 case (
'powel',
'powell')
192 type_divb = divb_powel
194 type_divb = divb_janhunen
196 type_divb = divb_linde
197 case (
'lindejanhunen')
198 type_divb = divb_lindejanhunen
200 type_divb = divb_lindepowel
204 type_divb = divb_lindeglm
209 call mpistop(
'Unknown divB fix')
214 mom(:) = var_set_momentum(
ndir)
219 mag(:) = var_set_bfield(
ndir)
224 allocate(start_indices(number_species),stop_indices(number_species))
226 start_indices(1)=mag(1)
229 psi_ = var_set_fluxvar(
'psi',
'psi', need_bc=.false.)
238 stop_indices(1)=nwflux
244 allocate(iw_vector(nvector))
245 iw_vector(1) =
mom(1) - 1
246 iw_vector(2) = mag(1) - 1
253 call mpistop(
"phys_check error: flux_type has wrong shape")
272 if(type_divb==divb_glm)
then
286 write(*,*)
'*****Using particles: particles_eta, particles_etah :', particles_eta, particles_etah
307 call mpistop(
'choose average, uct_contact,or uct_hll for type_ct!')
319 call mf_physical_units()
323 subroutine mf_check_params
326 end subroutine mf_check_params
328 subroutine mf_physical_units()
330 double precision :: mp,kb,miu0,c_lightspeed
331 double precision :: a,
b
467 end subroutine mf_physical_units
472 integer,
intent(in) :: ixi^
l, ixo^
l
473 double precision,
intent(inout) :: w(ixi^s, nw)
474 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
482 integer,
intent(in) :: ixi^
l, ixo^
l
483 double precision,
intent(inout) :: w(ixi^s, nw)
484 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
490 subroutine mf_get_cmax(w,x,ixI^L,ixO^L,idim,cmax)
493 integer,
intent(in) :: ixi^
l, ixo^
l, idim
494 double precision,
intent(in) :: w(ixi^s, nw), x(ixi^s,1:
ndim)
495 double precision,
intent(inout) :: cmax(ixi^s)
497 cmax(ixo^s)=abs(w(ixo^s,
mom(idim)))+one
499 end subroutine mf_get_cmax
502 subroutine mf_get_cbounds(wLC,wRC,wLp,wRp,x,ixI^L,ixO^L,idim,Hspeed,cmax,cmin)
506 integer,
intent(in) :: ixi^
l, ixo^
l, idim
507 double precision,
intent(in) :: wlc(ixi^s,
nw), wrc(ixi^s,
nw)
508 double precision,
intent(in) :: wlp(ixi^s,
nw), wrp(ixi^s,
nw)
509 double precision,
intent(in) :: x(ixi^s,1:
ndim)
511 double precision,
intent(inout),
optional :: cmin(ixi^s,1:
number_species)
514 double precision,
dimension(ixI^S) :: tmp1
516 tmp1(ixo^s)=0.5d0*(wlc(ixo^s,
mom(idim))+wrc(ixo^s,
mom(idim)))
517 if(
present(cmin))
then
518 cmax(ixo^s,1)=max(tmp1(ixo^s)+one,zero)
519 cmin(ixo^s,1)=min(tmp1(ixo^s)-one,zero)
521 cmax(ixo^s,1)=abs(tmp1(ixo^s))+one
524 end subroutine mf_get_cbounds
527 subroutine mf_get_ct_velocity_average(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
530 integer,
intent(in) :: ixi^
l, ixo^
l, idim
531 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
532 double precision,
intent(in) :: cmax(ixi^s)
533 double precision,
intent(in),
optional :: cmin(ixi^s)
534 type(ct_velocity),
intent(inout):: vcts
536 end subroutine mf_get_ct_velocity_average
538 subroutine mf_get_ct_velocity_contact(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
541 integer,
intent(in) :: ixi^
l, ixo^
l, idim
542 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
543 double precision,
intent(in) :: cmax(ixi^s)
544 double precision,
intent(in),
optional :: cmin(ixi^s)
545 type(ct_velocity),
intent(inout):: vcts
548 if(.not.
allocated(vcts%vnorm))
allocate(vcts%vnorm(ixi^s,1:
ndim))
550 vcts%vnorm(ixo^s,idim)=0.5d0*(wlp(ixo^s,
mom(idim))+wrp(ixo^s,
mom(idim)))
552 end subroutine mf_get_ct_velocity_contact
554 subroutine mf_get_ct_velocity_hll(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
557 integer,
intent(in) :: ixi^
l, ixo^
l, idim
558 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
559 double precision,
intent(in) :: cmax(ixi^s)
560 double precision,
intent(in),
optional :: cmin(ixi^s)
561 type(ct_velocity),
intent(inout):: vcts
563 integer :: idime,idimn
565 if(.not.
allocated(vcts%vbarC))
then
566 allocate(vcts%vbarC(ixi^s,1:
ndir,2),vcts%vbarLC(ixi^s,1:
ndir,2),vcts%vbarRC(ixi^s,1:
ndir,2))
567 allocate(vcts%cbarmin(ixi^s,1:
ndim),vcts%cbarmax(ixi^s,1:
ndim))
570 if(
present(cmin))
then
571 vcts%cbarmin(ixo^s,idim)=max(-cmin(ixo^s),zero)
572 vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
574 vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
575 vcts%cbarmin(ixo^s,idim)=vcts%cbarmax(ixo^s,idim)
578 idimn=mod(idim,
ndir)+1
579 idime=mod(idim+1,
ndir)+1
581 vcts%vbarLC(ixo^s,idim,1)=wlp(ixo^s,
mom(idimn))
582 vcts%vbarRC(ixo^s,idim,1)=wrp(ixo^s,
mom(idimn))
583 vcts%vbarC(ixo^s,idim,1)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,1) &
584 +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
585 /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
587 vcts%vbarLC(ixo^s,idim,2)=wlp(ixo^s,
mom(idime))
588 vcts%vbarRC(ixo^s,idim,2)=wrp(ixo^s,
mom(idime))
589 vcts%vbarC(ixo^s,idim,2)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,2) &
590 +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
591 /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
593 end subroutine mf_get_ct_velocity_hll
596 subroutine mf_get_flux(wC,w,x,ixI^L,ixO^L,idim,f)
601 integer,
intent(in) :: ixi^
l, ixo^
l, idim
603 double precision,
intent(in) :: wc(ixi^s,nw)
605 double precision,
intent(in) :: w(ixi^s,nw)
606 double precision,
intent(in) :: x(ixi^s,1:
ndim)
607 double precision,
intent(out) :: f(ixi^s,nwflux)
611 {
do ix^db=ixomin^db,ixomax^db\}
617 {
do ix^db=ixomin^db,ixomax^db\}
618 f(ix^d,mag(idim))=w(ix^d,
psi_)
620 f(ix^d,
psi_)=cmax_global**2*w(ix^d,mag(idim))
624 end subroutine mf_get_flux
627 subroutine mf_velocity_update(qt,psa)
630 double precision,
intent(in) :: qt
633 integer :: iigrid,igrid
634 logical :: stagger_flag
635 logical :: firstmf=.true.
650 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
652 call frictional_velocity(psa(igrid)%w,psa(igrid)%x,ixg^
ll,
ixm^
ll)
676 end subroutine mf_velocity_update
679 subroutine mf_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
682 integer,
intent(in) :: ixi^
l, ixo^
l
683 double precision,
intent(in) :: qdt, dtfactor
684 double precision,
intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw), x(ixi^s,1:
ndim)
685 double precision,
intent(inout) :: w(ixi^s,1:nw)
686 logical,
intent(in) :: qsourcesplit
687 logical,
intent(inout) :: active
689 if (.not. qsourcesplit)
then
692 if (abs(
mf_eta)>smalldouble)
then
694 call add_source_res2(qdt,ixi^
l,ixo^
l,wct,w,x)
699 call add_source_hyperres(qdt,ixi^
l,ixo^
l,wct,w,x)
707 select case (type_divb)
712 call add_source_glm(qdt,ixi^
l,ixo^
l,wct,w,x)
715 call add_source_powel(qdt,ixi^
l,ixo^
l,wct,w,x)
718 call add_source_janhunen(qdt,ixi^
l,ixo^
l,wct,w,x)
721 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
722 case (divb_lindejanhunen)
724 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
725 call add_source_janhunen(qdt,ixi^
l,ixo^
l,wct,w,x)
726 case (divb_lindepowel)
728 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
729 call add_source_powel(qdt,ixi^
l,ixo^
l,wct,w,x)
732 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
733 call add_source_glm(qdt,ixi^
l,ixo^
l,wct,w,x)
736 case (divb_multigrid)
739 call mpistop(
'Unknown divB fix')
744 end subroutine mf_add_source
746 subroutine frictional_velocity(w,x,ixI^L,ixO^L)
749 integer,
intent(in) :: ixi^
l, ixo^
l
750 double precision,
intent(in) :: x(ixi^s,1:
ndim)
751 double precision,
intent(inout) :: w(ixi^s,1:nw)
753 double precision :: xmin(
ndim),xmax(
ndim)
754 double precision :: decay(ixo^s)
755 double precision :: current(ixi^s,7-2*
ndir:3),tmp(ixo^s)
756 integer :: ix^
d, idirmin,idir,jdir,kdir
762 if(
block%is_physical_boundary(2*^
d-1))
then
765 if(2*^
d-1==5.and.
ndim==3)
then
767 current(ixomin^
d^
d%ixO^s,:)=current(ixomin^
d+1^
d%ixO^s,:)
772 current(ixomin^
d^
d%ixO^s,:)=current(ixomin^
d+1^
d%ixO^s,:)
776 if(
block%is_physical_boundary(2*^
d))
then
777 current(ixomax^
d^
d%ixO^s,:)=current(ixomax^
d-1^
d%ixO^s,:)
782 do idir=1,
ndir;
do jdir=idirmin,3;
do kdir=1,
ndir
783 if(
lvc(idir,jdir,kdir)/=0)
then
784 if(
lvc(idir,jdir,kdir)==1)
then
785 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))+current(ixo^s,jdir)*w(ixo^s,mag(kdir))
787 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))-current(ixo^s,jdir)*w(ixo^s,mag(kdir))
790 end do;
end do;
end do
792 tmp(ixo^s)=sum(w(ixo^s,mag(:))**2,dim=ndim+1)
794 where(tmp(ixo^s)/=0.d0)
795 tmp(ixo^s)=1.d0/(tmp(ixo^s)*
mf_nu)
799 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))*tmp(ixo^s)
803 ^d&xmin(^d)=xprobmin^d\
804 ^d&xmax(^d)=xprobmax^d\
814 tmp(ixo^s)=sqrt(sum(w(ixo^s,
mom(:))**2,dim=ndim+1))/
mf_vmax+1.d-12
815 tmp(ixo^s)=dtanh(tmp(ixo^s))/tmp(ixo^s)
817 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))*tmp(ixo^s)*decay(ixo^s)
820 end subroutine frictional_velocity
826 subroutine add_source_res1(qdt,ixI^L,ixO^L,wCT,w,x)
831 integer,
intent(in) :: ixi^
l, ixo^
l
832 double precision,
intent(in) :: qdt
833 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
834 double precision,
intent(inout) :: w(ixi^s,1:nw)
837 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s)
838 double precision :: gradeta(ixi^s,1:
ndim), bf(ixi^s,1:
ndir)
839 double precision :: tmp(ixi^s),tmp2(ixi^s)
840 integer :: ixa^
l,idir,jdir,kdir,idirmin,idim,jxo^
l,hxo^
l,ix
841 integer :: lxo^
l, kxo^
l
846 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
847 call mpistop(
"Error in add_source_res1: Non-conforming input limits")
854 gradeta(ixo^s,1:
ndim)=zero
860 gradeta(ixo^s,idim)=tmp(ixo^s)
864 bf(ixi^s,1:
ndir)=wct(ixi^s,mag(1:
ndir))
869 tmp2(ixi^s)=bf(ixi^s,idir)
871 lxo^
l=ixo^
l+2*
kr(idim,^
d);
872 jxo^
l=ixo^
l+
kr(idim,^
d);
873 hxo^
l=ixo^
l-
kr(idim,^
d);
874 kxo^
l=ixo^
l-2*
kr(idim,^
d);
875 tmp(ixo^s)=tmp(ixo^s)+&
876 (-tmp2(lxo^s)+16.0d0*tmp2(jxo^s)-30.0d0*tmp2(ixo^s)+16.0d0*tmp2(hxo^s)-tmp2(kxo^s)) &
881 tmp(ixo^s)=tmp(ixo^s)*eta(ixo^s)
885 do jdir=1,
ndim;
do kdir=idirmin,3
886 if (
lvc(idir,jdir,kdir)/=0)
then
887 if (
lvc(idir,jdir,kdir)==1)
then
888 tmp(ixo^s)=tmp(ixo^s)-gradeta(ixo^s,jdir)*current(ixo^s,kdir)
890 tmp(ixo^s)=tmp(ixo^s)+gradeta(ixo^s,jdir)*current(ixo^s,kdir)
897 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))+qdt*tmp(ixo^s)
901 end subroutine add_source_res1
905 subroutine add_source_res2(qdt,ixI^L,ixO^L,wCT,w,x)
910 integer,
intent(in) :: ixi^
l, ixo^
l
911 double precision,
intent(in) :: qdt
912 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
913 double precision,
intent(inout) :: w(ixi^s,1:nw)
916 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s),curlj(ixi^s,1:3)
917 double precision :: tmpvec(ixi^s,1:3)
918 integer :: ixa^
l,idir,idirmin,idirmin1
925 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
926 call mpistop(
"Error in add_source_res2: Non-conforming input limits")
940 tmpvec(ixa^s,1:
ndir)=zero
942 tmpvec(ixa^s,idir)=current(ixa^s,idir)*eta(ixa^s)
949 w(ixo^s,mag(
ndir)) = w(ixo^s,mag(
ndir))-qdt*curlj(ixo^s,
ndir)
952 w(ixo^s,mag(1:
ndir)) = w(ixo^s,mag(1:
ndir))-qdt*curlj(ixo^s,1:
ndir)
955 end subroutine add_source_res2
959 subroutine add_source_hyperres(qdt,ixI^L,ixO^L,wCT,w,x)
963 integer,
intent(in) :: ixi^
l, ixo^
l
964 double precision,
intent(in) :: qdt
965 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
966 double precision,
intent(inout) :: w(ixi^s,1:nw)
968 double precision :: current(ixi^s,7-2*
ndir:3)
969 double precision :: tmpvec(ixi^s,1:3),tmpvec2(ixi^s,1:3),tmp(ixi^s),ehyper(ixi^s,1:3)
970 integer :: ixa^
l,idir,jdir,kdir,idirmin,idirmin1
973 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
974 call mpistop(
"Error in add_source_hyperres: Non-conforming input limits")
977 tmpvec(ixa^s,1:
ndir)=zero
979 tmpvec(ixa^s,jdir)=current(ixa^s,jdir)
983 call curlvector(tmpvec,ixi^
l,ixa^
l,tmpvec2,idirmin1,1,3)
986 tmpvec(ixa^s,1:
ndir)=zero
987 call curlvector(tmpvec2,ixi^
l,ixa^
l,tmpvec,idirmin1,1,3)
991 tmpvec2(ixa^s,1:
ndir)=zero
992 call curlvector(ehyper,ixi^
l,ixa^
l,tmpvec2,idirmin1,1,3)
995 w(ixo^s,mag(idir)) = w(ixo^s,mag(idir))-tmpvec2(ixo^s,idir)*qdt
998 end subroutine add_source_hyperres
1000 subroutine add_source_glm(qdt,ixI^L,ixO^L,wCT,w,x)
1007 integer,
intent(in) :: ixi^
l, ixo^
l
1008 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1009 double precision,
intent(inout) :: w(ixi^s,1:nw)
1010 double precision:: divb(ixi^s)
1011 double precision :: gradpsi(ixi^s)
1012 integer :: idim,idir
1039 end subroutine add_source_glm
1042 subroutine add_source_powel(qdt,ixI^L,ixO^L,wCT,w,x)
1045 integer,
intent(in) :: ixi^
l, ixo^
l
1046 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1047 double precision,
intent(inout) :: w(ixi^s,1:nw)
1049 double precision :: divb(ixi^s)
1057 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*wct(ixo^s,
mom(idir))*divb(ixo^s)
1060 end subroutine add_source_powel
1062 subroutine add_source_janhunen(qdt,ixI^L,ixO^L,wCT,w,x)
1067 integer,
intent(in) :: ixi^
l, ixo^
l
1068 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1069 double precision,
intent(inout) :: w(ixi^s,1:nw)
1070 double precision :: divb(ixi^s)
1078 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*wct(ixo^s,
mom(idir))*divb(ixo^s)
1081 end subroutine add_source_janhunen
1083 subroutine add_source_linde(qdt,ixI^L,ixO^L,wCT,w,x)
1088 integer,
intent(in) :: ixi^
l, ixo^
l
1089 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1090 double precision,
intent(inout) :: w(ixi^s,1:nw)
1091 double precision :: divb(ixi^s),graddivb(ixi^s)
1092 integer :: idim, idir, ixp^
l, i^
d, iside
1093 logical,
dimension(-1:1^D&) :: leveljump
1101 if(i^
d==0|.and.) cycle
1102 if(neighbor_type(i^
d,
block%igrid)==2 .or. neighbor_type(i^
d,
block%igrid)==4)
then
1103 leveljump(i^
d)=.true.
1105 leveljump(i^
d)=.false.
1114 i^dd=kr(^dd,^d)*(2*iside-3);
1115 if (leveljump(i^dd))
then
1117 ixpmin^d=ixomin^d-i^d
1119 ixpmax^d=ixomax^d-i^d
1130 select case(typegrad)
1132 call gradient(divb,ixi^l,ixp^l,idim,graddivb)
1134 call gradientl(divb,ixi^l,ixp^l,idim,graddivb)
1138 if (slab_uniform)
then
1139 graddivb(ixp^s)=graddivb(ixp^s)*divbdiff/(^d&1.0d0/dxlevel(^d)**2+)
1141 graddivb(ixp^s)=graddivb(ixp^s)*divbdiff &
1142 /(^d&1.0d0/block%ds(ixp^s,^d)**2+)
1145 w(ixp^s,mag(idim))=w(ixp^s,mag(idim))+graddivb(ixp^s)
1148 end subroutine add_source_linde
1156 integer,
intent(in) :: ixi^
l, ixo^
l
1157 double precision,
intent(in) :: w(ixi^s,1:nw)
1158 double precision :: divb(ixi^s), dsurface(ixi^s)
1160 double precision :: invb(ixo^s)
1161 integer :: ixa^
l,idims
1163 call get_divb(w,ixi^
l,ixo^
l,divb)
1164 invb(ixo^s)=sqrt(sum(w(ixo^s, mag(:))**2, dim=
ndim+1))
1165 where(invb(ixo^s)/=0.d0)
1166 invb(ixo^s)=1.d0/invb(ixo^s)
1169 divb(ixo^s)=0.5d0*abs(divb(ixo^s))*invb(ixo^s)/sum(1.d0/
dxlevel(:))
1171 ixamin^
d=ixomin^
d-1;
1172 ixamax^
d=ixomax^
d-1;
1173 dsurface(ixo^s)= sum(
block%surfaceC(ixo^s,:),dim=
ndim+1)
1175 ixa^
l=ixo^
l-
kr(idims,^
d);
1176 dsurface(ixo^s)=dsurface(ixo^s)+
block%surfaceC(ixa^s,idims)
1178 divb(ixo^s)=abs(divb(ixo^s))*invb(ixo^s)*&
1179 block%dvolume(ixo^s)/dsurface(ixo^s)
1190 integer,
intent(in) :: ixo^
l, ixi^
l
1191 double precision,
intent(in) :: w(ixi^s,1:nw)
1192 integer,
intent(out) :: idirmin
1193 logical,
intent(in),
optional :: fourthorder
1196 double precision :: current(ixi^s,7-2*
ndir:3)
1197 integer :: idir, idirmin0
1201 if(
present(fourthorder))
then
1210 subroutine mf_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
1214 integer,
intent(in) :: ixi^
l, ixo^
l
1215 double precision,
intent(inout) :: dtnew
1216 double precision,
intent(in) ::
dx^
d
1217 double precision,
intent(in) :: w(ixi^s,1:nw)
1218 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1220 double precision :: dxarr(
ndim)
1221 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s)
1222 integer :: idirmin,idim
1229 else if (
mf_eta<zero)
then
1236 dtdiffpar/(smalldouble+maxval(eta(ixo^s)/dxarr(idim)**2)))
1239 dtdiffpar/(smalldouble+maxval(eta(ixo^s)/
block%ds(ixo^s,idim)**2)))
1251 end subroutine mf_get_dt
1254 subroutine mf_add_source_geom(qdt,dtfactor, ixI^L,ixO^L,wCT,wprim,w,x)
1258 integer,
intent(in) :: ixi^
l, ixo^
l
1259 double precision,
intent(in) :: qdt, dtfactor, x(ixi^s,1:
ndim)
1260 double precision,
intent(inout) :: wct(ixi^s,1:nw), wprim(ixi^s,1:nw), w(ixi^s,1:nw)
1262 double precision :: tmp,invr,cs2
1263 integer :: iw,idir,ix^
d
1265 integer :: mr_,mphi_
1266 integer :: br_,bphi_
1269 br_=mag(1); bphi_=mag(1)-1+
phi_
1275 {
do ix^db=ixomin^db,ixomax^db\}
1276 w(ix^
d,bphi_)=w(ix^
d,bphi_)+qdt/x(ix^
d,1)*&
1277 (wct(ix^
d,bphi_)*wct(ix^
d,mr_) &
1278 -wct(ix^
d,br_)*wct(ix^
d,mphi_))
1282 if(
mf_glm) w(ixo^s,br_)=w(ixo^s,br_)+qdt*wct(ixo^s,
psi_)/x(ixo^s,1)
1284 {
do ix^db=ixomin^db,ixomax^db\}
1288 w(ix^d,mag(1))=w(ix^d,mag(1))+invr*2.0d0*wct(ix^d,
psi_)
1293 if(.not.stagger_grid)
then
1294 tmp=wct(ix^d,
mom(1))*wct(ix^d,mag(2))-wct(ix^d,
mom(2))*wct(ix^d,mag(1))
1295 cs2=1.d0/tan(x(ix^d,2))
1297 tmp=tmp+cs2*wct(ix^d,
psi_)
1299 w(ix^d,mag(2))=w(ix^d,mag(2))+tmp*invr
1306 if(.not.stagger_grid)
then
1307 w(ix^d,mag(3))=w(ix^d,mag(3))+invr*&
1308 (wct(ix^d,
mom(1))*wct(ix^d,mag(3)) &
1309 -wct(ix^d,
mom(3))*wct(ix^d,mag(1)))
1314 if(.not.stagger_grid)
then
1315 w(ix^d,mag(3))=w(ix^d,mag(3))+invr*&
1316 (wct(ix^d,
mom(1))*wct(ix^d,mag(3)) &
1317 -wct(ix^d,
mom(3))*wct(ix^d,mag(1)) &
1318 -(wct(ix^d,
mom(3))*wct(ix^d,mag(2)) &
1319 -wct(ix^d,
mom(2))*wct(ix^d,mag(3)))*cs2)
1326 end subroutine mf_add_source_geom
1328 subroutine mf_modify_wlr(ixI^L,ixO^L,qt,wLC,wRC,wLp,wRp,s,idir)
1331 integer,
intent(in) :: ixi^
l, ixo^
l, idir
1332 double precision,
intent(in) :: qt
1333 double precision,
intent(inout) :: wlc(ixi^s,1:nw), wrc(ixi^s,1:nw)
1334 double precision,
intent(inout) :: wlp(ixi^s,1:nw), wrp(ixi^s,1:nw)
1336 double precision :: db(ixi^s), dpsi(ixi^s)
1344 db(ixo^s) = wrp(ixo^s,mag(idir)) - wlp(ixo^s,mag(idir))
1345 dpsi(ixo^s) = wrp(ixo^s,
psi_) - wlp(ixo^s,
psi_)
1347 wlp(ixo^s,mag(idir)) = 0.5d0 * (wrp(ixo^s,mag(idir)) + wlp(ixo^s,mag(idir))) &
1349 wlp(ixo^s,
psi_) = 0.5d0 * (wrp(ixo^s,
psi_) + wlp(ixo^s,
psi_)) &
1352 wrp(ixo^s,mag(idir)) = wlp(ixo^s,mag(idir))
1355 end subroutine mf_modify_wlr
1357 subroutine mf_boundary_adjust(igrid,psb)
1359 integer,
intent(in) :: igrid
1362 integer :: ib, idims, iside, ixo^
l, i^
d
1371 i^
d=
kr(^
d,idims)*(2*iside-3);
1372 if (neighbor_type(i^
d,igrid)/=1) cycle
1373 ib=(idims-1)*2+iside
1391 call fixdivb_boundary(ixg^
ll,ixo^
l,psb(igrid)%w,psb(igrid)%x,ib)
1396 end subroutine mf_boundary_adjust
1398 subroutine fixdivb_boundary(ixG^L,ixO^L,w,x,iB)
1401 integer,
intent(in) :: ixg^
l,ixo^
l,ib
1402 double precision,
intent(inout) :: w(ixg^s,1:nw)
1403 double precision,
intent(in) :: x(ixg^s,1:
ndim)
1405 double precision :: dx1x2,dx1x3,dx2x1,dx2x3,dx3x1,dx3x2
1406 integer :: ix^
d,ixf^
l
1418 do ix1=ixfmax1,ixfmin1,-1
1419 w(ix1-1,ixfmin2:ixfmax2,mag(1))=w(ix1+1,ixfmin2:ixfmax2,mag(1)) &
1420 +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
1421 w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
1424 do ix1=ixfmax1,ixfmin1,-1
1425 w(ix1-1,ixfmin2:ixfmax2,mag(1))=( (w(ix1+1,ixfmin2:ixfmax2,mag(1))+&
1426 w(ix1,ixfmin2:ixfmax2,mag(1)))*
block%surfaceC(ix1,ixfmin2:ixfmax2,1)&
1427 +(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
1428 block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
1429 -(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
1430 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
1431 /
block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
1445 do ix1=ixfmax1,ixfmin1,-1
1446 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1447 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
1448 +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
1449 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
1450 +dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
1451 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
1454 do ix1=ixfmax1,ixfmin1,-1
1455 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1456 ( (w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
1457 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
1458 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
1459 +(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
1460 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
1461 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
1462 -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
1463 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
1464 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
1465 +(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
1466 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
1467 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
1468 -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
1469 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1470 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
1471 /
block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
1472 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
1484 do ix1=ixfmin1,ixfmax1
1485 w(ix1+1,ixfmin2:ixfmax2,mag(1))=w(ix1-1,ixfmin2:ixfmax2,mag(1)) &
1486 -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
1487 w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
1490 do ix1=ixfmin1,ixfmax1
1491 w(ix1+1,ixfmin2:ixfmax2,mag(1))=( (w(ix1-1,ixfmin2:ixfmax2,mag(1))+&
1492 w(ix1,ixfmin2:ixfmax2,mag(1)))*
block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)&
1493 -(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
1494 block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
1495 +(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
1496 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
1497 /
block%surfaceC(ix1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
1511 do ix1=ixfmin1,ixfmax1
1512 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1513 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
1514 -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
1515 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
1516 -dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
1517 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
1520 do ix1=ixfmin1,ixfmax1
1521 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1522 ( (w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
1523 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
1524 block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
1525 -(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
1526 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
1527 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
1528 +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
1529 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
1530 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
1531 -(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
1532 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
1533 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
1534 +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
1535 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1536 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
1537 /
block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
1538 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
1550 do ix2=ixfmax2,ixfmin2,-1
1551 w(ixfmin1:ixfmax1,ix2-1,mag(2))=w(ixfmin1:ixfmax1,ix2+1,mag(2)) &
1552 +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
1553 w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
1556 do ix2=ixfmax2,ixfmin2,-1
1557 w(ixfmin1:ixfmax1,ix2-1,mag(2))=( (w(ixfmin1:ixfmax1,ix2+1,mag(2))+&
1558 w(ixfmin1:ixfmax1,ix2,mag(2)))*
block%surfaceC(ixfmin1:ixfmax1,ix2,2)&
1559 +(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
1560 block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
1561 -(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
1562 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
1563 /
block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
1577 do ix2=ixfmax2,ixfmin2,-1
1578 w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
1579 ix2+1,ixfmin3:ixfmax3,mag(2)) &
1580 +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
1581 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
1582 +dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
1583 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
1586 do ix2=ixfmax2,ixfmin2,-1
1587 w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=&
1588 ( (w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))+&
1589 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
1590 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)&
1591 +(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
1592 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1593 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
1594 -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
1595 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1596 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
1597 +(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
1598 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
1599 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
1600 -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
1601 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1602 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
1603 /
block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)-&
1604 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
1616 do ix2=ixfmin2,ixfmax2
1617 w(ixfmin1:ixfmax1,ix2+1,mag(2))=w(ixfmin1:ixfmax1,ix2-1,mag(2)) &
1618 -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
1619 w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
1622 do ix2=ixfmin2,ixfmax2
1623 w(ixfmin1:ixfmax1,ix2+1,mag(2))=( (w(ixfmin1:ixfmax1,ix2-1,mag(2))+&
1624 w(ixfmin1:ixfmax1,ix2,mag(2)))*
block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)&
1625 -(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
1626 block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
1627 +(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
1628 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
1629 /
block%surfaceC(ixfmin1:ixfmax1,ix2,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
1643 do ix2=ixfmin2,ixfmax2
1644 w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
1645 ix2-1,ixfmin3:ixfmax3,mag(2)) &
1646 -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
1647 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
1648 -dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
1649 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
1652 do ix2=ixfmin2,ixfmax2
1653 w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=&
1654 ( (w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))+&
1655 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
1656 block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)&
1657 -(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
1658 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1659 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
1660 +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
1661 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1662 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
1663 -(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
1664 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
1665 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
1666 +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
1667 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1668 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
1669 /
block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)-&
1670 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
1685 do ix3=ixfmax3,ixfmin3,-1
1686 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=w(ixfmin1:ixfmax1,&
1687 ixfmin2:ixfmax2,ix3+1,mag(3)) &
1688 +dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
1689 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
1690 +dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
1691 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
1694 do ix3=ixfmax3,ixfmin3,-1
1695 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=&
1696 ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))+&
1697 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
1698 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)&
1699 +(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
1700 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1701 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
1702 -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
1703 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1704 block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
1705 +(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
1706 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
1707 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
1708 -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
1709 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
1710 block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
1711 /
block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)-&
1712 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
1725 do ix3=ixfmin3,ixfmax3
1726 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=w(ixfmin1:ixfmax1,&
1727 ixfmin2:ixfmax2,ix3-1,mag(3)) &
1728 -dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
1729 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
1730 -dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
1731 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
1734 do ix3=ixfmin3,ixfmax3
1735 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=&
1736 ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))+&
1737 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
1738 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)&
1739 -(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
1740 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1741 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
1742 +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
1743 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1744 block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
1745 -(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
1746 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
1747 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
1748 +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
1749 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
1750 block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
1751 /
block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)-&
1752 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
1757 call mpistop(
"Special boundary is not defined for this region")
1760 end subroutine fixdivb_boundary
1769 double precision,
intent(in) :: qdt
1770 double precision,
intent(in) :: qt
1771 logical,
intent(inout) :: active
1773 double precision :: tmp(ixg^t), grad(ixg^t,
ndim)
1774 double precision :: res
1775 double precision,
parameter :: max_residual = 1
d-3
1776 double precision,
parameter :: residual_reduction = 1
d-10
1778 integer,
parameter :: max_its = 50
1779 double precision :: residual_it(max_its), max_divb
1780 integer :: iigrid, igrid
1781 integer :: n, nc, lvl, ix^
l, ixc^
l, idim
1784 mg%operator_type = mg_laplacian
1792 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1793 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1796 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
1797 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1799 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1800 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1803 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
1804 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1808 write(*,*)
"mf_clean_divb_multigrid warning: unknown boundary type"
1809 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1810 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1818 do iigrid = 1, igridstail
1819 igrid = igrids(iigrid);
1822 lvl =
mg%boxes(id)%lvl
1823 nc =
mg%box_size_lvl(lvl)
1829 call get_divb(ps(igrid)%w(ixg^t, 1:nw), ixg^
ll,
ixm^
ll, tmp, &
1831 mg%boxes(id)%cc({1:nc}, mg_irhs) = tmp(
ixm^t)
1832 max_divb = max(max_divb, maxval(abs(tmp(
ixm^t))))
1837 call mpi_allreduce(mpi_in_place, max_divb, 1, mpi_double_precision, &
1840 if (
mype == 0) print *,
"Performing multigrid divB cleaning"
1841 if (
mype == 0) print *,
"iteration vs residual"
1844 call mg_fas_fmg(
mg, n>1, max_res=residual_it(n))
1845 if (
mype == 0)
write(*,
"(I4,E11.3)") n, residual_it(n)
1846 if (residual_it(n) < residual_reduction * max_divb)
exit
1848 if (
mype == 0 .and. n > max_its)
then
1849 print *,
"divb_multigrid warning: not fully converged"
1850 print *,
"current amplitude of divb: ", residual_it(max_its)
1851 print *,
"multigrid smallest grid: ", &
1852 mg%domain_size_lvl(:,
mg%lowest_lvl)
1853 print *,
"note: smallest grid ideally has <= 8 cells"
1854 print *,
"multigrid dx/dy/dz ratio: ",
mg%dr(:, 1)/
mg%dr(1, 1)
1855 print *,
"note: dx/dy/dz should be similar"
1859 call mg_fas_vcycle(
mg, max_res=res)
1860 if (res < max_residual)
exit
1862 if (res > max_residual)
call mpistop(
"divb_multigrid: no convergence")
1867 do iigrid = 1, igridstail
1868 igrid = igrids(iigrid);
1877 tmp(ix^s) =
mg%boxes(id)%cc({:,}, mg_iphi)
1881 ixcmin^
d=ixmlo^
d-
kr(idim,^
d);
1883 call gradientf(tmp,ps(igrid)%x,ixg^
ll,ixc^
l,idim,grad(ixg^t,idim))
1884 ps(igrid)%ws(ixc^s,idim)=ps(igrid)%ws(ixc^s,idim)-grad(ixc^s,idim)
1892 ps(igrid)%w(
ixm^t, mag(1:
ndim)) = &
1893 ps(igrid)%w(
ixm^t, mag(1:
ndim)) - grad(
ixm^t, :)
1904 subroutine mf_update_faces_average(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
1908 integer,
intent(in) :: ixi^
l, ixo^
l
1909 double precision,
intent(in) :: qt, qdt
1911 double precision,
intent(in) :: wp(ixi^s,1:nw)
1912 type(state) :: sct, s
1913 type(ct_velocity) :: vcts
1914 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
1915 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
1917 double precision :: circ(ixi^s,1:
ndim)
1918 double precision :: e_resi(ixi^s,
sdim:3)
1919 integer :: ix^
d,ixc^
l,ixa^
l,i1kr^
d,i2kr^
d
1920 integer :: idim1,idim2,idir,iwdim1,iwdim2
1922 associate(bfaces=>s%ws,x=>s%x)
1929 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,e_resi)
1933 i1kr^
d=
kr(idim1,^
d);
1936 i2kr^
d=
kr(idim2,^
d);
1939 if (
lvc(idim1,idim2,idir)==1)
then
1941 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
1943 {
do ix^db=ixcmin^db,ixcmax^db\}
1944 fe(ix^
d,idir)=quarter*&
1945 (fc(ix^
d,iwdim1,idim2)+fc({ix^
d+i1kr^
d},iwdim1,idim2)&
1946 -fc(ix^
d,iwdim2,idim1)-fc({ix^
d+i2kr^
d},iwdim2,idim1))
1948 if(
mf_eta/=zero) fe(ix^
d,idir)=fe(ix^
d,idir)+e_resi(ix^
d,idir)
1951 fe(ix^
d,idir)=fe(ix^
d,idir)*qdt*s%dsC(ix^
d,idir)
1959 if(
associated(usr_set_electric_field)) &
1960 call usr_set_electric_field(ixi^l,ixo^l,qt,qdt,fe,sct)
1962 circ(ixi^s,1:ndim)=zero
1968 ixcmin^d=ixomin^d-kr(idim1,^d);
1970 ixa^l=ixc^l-kr(idim2,^d);
1973 if(lvc(idim1,idim2,idir)==1)
then
1975 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
1978 else if(lvc(idim1,idim2,idir)==-1)
then
1980 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
1987 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
1989 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
1994 end subroutine mf_update_faces_average
1997 subroutine mf_update_faces_contact(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
2001 integer,
intent(in) :: ixi^
l, ixo^
l
2002 double precision,
intent(in) :: qt, qdt
2004 double precision,
intent(in) :: wp(ixi^s,1:nw)
2005 type(state) :: sct, s
2006 type(ct_velocity) :: vcts
2007 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
2008 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
2010 double precision :: circ(ixi^s,1:
ndim)
2012 double precision :: ecc(ixi^s,
sdim:3)
2014 double precision :: el(ixi^s),er(ixi^s)
2016 double precision :: elc(ixi^s),erc(ixi^s)
2018 double precision :: jce(ixi^s,
sdim:3)
2019 integer :: hxc^
l,ixc^
l,jxc^
l,ixa^
l,ixb^
l
2020 integer :: idim1,idim2,idir,iwdim1,iwdim2
2022 associate(bfaces=>s%ws,x=>s%x,w=>s%w,vnorm=>vcts%vnorm)
2027 if(
lvc(idim1,idim2,idir)==1)
then
2028 ecc(ixi^s,idir)=ecc(ixi^s,idir)+wp(ixi^s,mag(idim1))*wp(ixi^s,
mom(idim2))
2029 else if(
lvc(idim1,idim2,idir)==-1)
then
2030 ecc(ixi^s,idir)=ecc(ixi^s,idir)-wp(ixi^s,mag(idim1))*wp(ixi^s,
mom(idim2))
2035 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,jce)
2047 if (
lvc(idim1,idim2,idir)==1)
then
2049 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
2051 jxc^
l=ixc^
l+
kr(idim1,^
d);
2052 hxc^
l=ixc^
l+
kr(idim2,^
d);
2054 fe(ixc^s,idir)=quarter*&
2055 (fc(ixc^s,iwdim1,idim2)+fc(jxc^s,iwdim1,idim2)&
2056 -fc(ixc^s,iwdim2,idim1)-fc(hxc^s,iwdim2,idim1))
2060 ixamax^
d=ixcmax^
d+
kr(idim1,^
d);
2061 el(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(ixa^s,idir)
2062 hxc^
l=ixa^
l+
kr(idim2,^
d);
2063 er(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(hxc^s,idir)
2064 where(vnorm(ixc^s,idim1)>0.d0)
2065 elc(ixc^s)=el(ixc^s)
2066 else where(vnorm(ixc^s,idim1)<0.d0)
2067 elc(ixc^s)=el(jxc^s)
2069 elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
2071 hxc^
l=ixc^
l+
kr(idim2,^
d);
2072 where(vnorm(hxc^s,idim1)>0.d0)
2073 erc(ixc^s)=er(ixc^s)
2074 else where(vnorm(hxc^s,idim1)<0.d0)
2075 erc(ixc^s)=er(jxc^s)
2077 erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
2079 fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
2082 jxc^
l=ixc^
l+
kr(idim2,^
d);
2084 ixamax^
d=ixcmax^
d+
kr(idim2,^
d);
2085 el(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(ixa^s,idir)
2086 hxc^
l=ixa^
l+
kr(idim1,^
d);
2087 er(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(hxc^s,idir)
2088 where(vnorm(ixc^s,idim2)>0.d0)
2089 elc(ixc^s)=el(ixc^s)
2090 else where(vnorm(ixc^s,idim2)<0.d0)
2091 elc(ixc^s)=el(jxc^s)
2093 elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
2095 hxc^
l=ixc^
l+
kr(idim1,^
d);
2096 where(vnorm(hxc^s,idim2)>0.d0)
2097 erc(ixc^s)=er(ixc^s)
2098 else where(vnorm(hxc^s,idim2)<0.d0)
2099 erc(ixc^s)=er(jxc^s)
2101 erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
2103 fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
2106 if(
mf_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+jce(ixc^s,idir)
2110 fe(ixc^s,idir)=fe(ixc^s,idir)*qdt*s%dsC(ixc^s,idir)
2125 circ(ixi^s,1:
ndim)=zero
2130 ixcmin^
d=ixomin^
d-
kr(idim1,^
d);
2134 if(
lvc(idim1,idim2,idir)/=0)
then
2135 hxc^
l=ixc^
l-
kr(idim2,^
d);
2137 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2138 +
lvc(idim1,idim2,idir)&
2145 where(s%surfaceC(ixc^s,idim1) > 1.0
d-9*s%dvolume(ixc^s))
2146 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2148 circ(ixc^s,idim1)=zero
2151 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2156 end subroutine mf_update_faces_contact
2159 subroutine mf_update_faces_hll(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
2164 integer,
intent(in) :: ixi^
l, ixo^
l
2165 double precision,
intent(in) :: qt, qdt
2167 double precision,
intent(in) :: wp(ixi^s,1:nw)
2168 type(state) :: sct, s
2169 type(ct_velocity) :: vcts
2170 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
2171 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
2173 double precision :: vtill(ixi^s,2)
2174 double precision :: vtilr(ixi^s,2)
2175 double precision :: btill(ixi^s,
ndim)
2176 double precision :: btilr(ixi^s,
ndim)
2177 double precision :: cp(ixi^s,2)
2178 double precision :: cm(ixi^s,2)
2179 double precision :: circ(ixi^s,1:
ndim)
2181 double precision :: jce(ixi^s,
sdim:3)
2182 integer :: hxc^
l,ixc^
l,ixcp^
l,jxc^
l,ixcm^
l
2183 integer :: idim1,idim2,idir
2185 associate(bfaces=>s%ws,bfacesct=>sct%ws,x=>s%x,vbarc=>vcts%vbarC,cbarmin=>vcts%cbarmin,&
2186 cbarmax=>vcts%cbarmax)
2199 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,jce)
2212 ixcmin^
d=ixomin^
d-1+
kr(idir,^
d);
2216 idim2=mod(idir+1,3)+1
2218 jxc^
l=ixc^
l+
kr(idim1,^
d);
2219 ixcp^
l=ixc^
l+
kr(idim2,^
d);
2223 vtill(ixi^s,2),vtilr(ixi^s,2))
2226 vtill(ixi^s,1),vtilr(ixi^s,1))
2232 btill(ixi^s,idim1),btilr(ixi^s,idim1))
2235 btill(ixi^s,idim2),btilr(ixi^s,idim2))
2239 cm(ixc^s,1)=max(cbarmin(ixcp^s,idim1),cbarmin(ixc^s,idim1))
2240 cp(ixc^s,1)=max(cbarmax(ixcp^s,idim1),cbarmax(ixc^s,idim1))
2242 cm(ixc^s,2)=max(cbarmin(jxc^s,idim2),cbarmin(ixc^s,idim2))
2243 cp(ixc^s,2)=max(cbarmax(jxc^s,idim2),cbarmax(ixc^s,idim2))
2247 fe(ixc^s,idir)=-(cp(ixc^s,1)*vtill(ixc^s,1)*btill(ixc^s,idim2) &
2248 + cm(ixc^s,1)*vtilr(ixc^s,1)*btilr(ixc^s,idim2) &
2249 - cp(ixc^s,1)*cm(ixc^s,1)*(btilr(ixc^s,idim2)-btill(ixc^s,idim2)))&
2250 /(cp(ixc^s,1)+cm(ixc^s,1)) &
2251 +(cp(ixc^s,2)*vtill(ixc^s,2)*btill(ixc^s,idim1) &
2252 + cm(ixc^s,2)*vtilr(ixc^s,2)*btilr(ixc^s,idim1) &
2253 - cp(ixc^s,2)*cm(ixc^s,2)*(btilr(ixc^s,idim1)-btill(ixc^s,idim1)))&
2254 /(cp(ixc^s,2)+cm(ixc^s,2))
2257 if(
mf_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+jce(ixc^s,idir)
2261 fe(ixc^s,idir)=qdt*s%dsC(ixc^s,idir)*fe(ixc^s,idir)
2275 circ(ixi^s,1:
ndim)=zero
2281 ixcmin^
d=ixomin^
d-
kr(idim1,^
d);
2285 if(
lvc(idim1,idim2,idir)/=0)
then
2286 hxc^
l=ixc^
l-
kr(idim2,^
d);
2288 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2289 +
lvc(idim1,idim2,idir)&
2296 where(s%surfaceC(ixc^s,idim1) > 1.0
d-9*s%dvolume(ixc^s))
2297 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2299 circ(ixc^s,idim1)=zero
2302 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2306 end subroutine mf_update_faces_hll
2309 subroutine get_resistive_electric_field(ixI^L,ixO^L,sCT,s,jce)
2314 integer,
intent(in) :: ixi^
l, ixo^
l
2315 type(state),
intent(in) :: sct, s
2317 double precision :: jce(ixi^s,
sdim:3)
2320 double precision :: jcc(ixi^s,7-2*
ndir:3)
2322 double precision :: xs(ixgs^t,1:
ndim)
2324 double precision :: eta(ixi^s)
2325 double precision :: gradi(ixgs^t)
2326 integer :: ix^
d,ixc^
l,ixa^
l,ixb^
l,idir,idirmin,idim1,idim2
2328 associate(x=>s%x,
dx=>s%dx,w=>s%w,wct=>sct%w,wcts=>sct%ws)
2334 if (
lvc(idim1,idim2,idir)==0) cycle
2335 ixcmax^
d=ixomax^
d+1;
2336 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-2;
2337 ixbmax^
d=ixcmax^
d-
kr(idir,^
d)+1;
2340 xs(ixb^s,:)=x(ixb^s,:)
2341 xs(ixb^s,idim2)=x(ixb^s,idim2)+half*
dx(ixb^s,idim2)
2342 call gradientf(wcts(ixgs^t,idim2),xs,ixgs^
ll,ixc^
l,idim1,gradi)
2343 if (
lvc(idim1,idim2,idir)==1)
then
2344 jce(ixc^s,idir)=jce(ixc^s,idir)+gradi(ixc^s)
2346 jce(ixc^s,idir)=jce(ixc^s,idir)-gradi(ixc^s)
2353 jce(ixi^s,:)=jce(ixi^s,:)*
mf_eta
2361 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
2362 jcc(ixc^s,idir)=0.d0
2364 if({ ix^
d==1 .and. ^
d==idir | .or.}) cycle
2365 ixamin^
d=ixcmin^
d+ix^
d;
2366 ixamax^
d=ixcmax^
d+ix^
d;
2367 jcc(ixc^s,idir)=jcc(ixc^s,idir)+eta(ixa^s)
2369 jcc(ixc^s,idir)=jcc(ixc^s,idir)*0.25d0
2370 jce(ixc^s,idir)=jce(ixc^s,idir)*jcc(ixc^s,idir)
2375 end subroutine get_resistive_electric_field
2381 integer,
intent(in) :: ixo^
l
2388 do ix^db=ixomin^db,ixomax^db\}
2390 s%w(ix^
d,mag(1))=half/s%surface(ix^
d,1)*(s%ws(ix^
d,1)*s%surfaceC(ix^
d,1)&
2391 +s%ws(ix1-1,ix2,ix3,1)*s%surfaceC(ix1-1,ix2,ix3,1))
2392 s%w(ix^
d,mag(2))=half/s%surface(ix^
d,2)*(s%ws(ix^
d,2)*s%surfaceC(ix^
d,2)&
2393 +s%ws(ix1,ix2-1,ix3,2)*s%surfaceC(ix1,ix2-1,ix3,2))
2394 s%w(ix^
d,mag(3))=half/s%surface(ix^
d,3)*(s%ws(ix^
d,3)*s%surfaceC(ix^
d,3)&
2395 +s%ws(ix1,ix2,ix3-1,3)*s%surfaceC(ix1,ix2,ix3-1,3))
2398 s%w(ix^
d,mag(1))=half/s%surface(ix^
d,1)*(s%ws(ix^
d,1)*s%surfaceC(ix^
d,1)&
2399 +s%ws(ix1-1,ix2,1)*s%surfaceC(ix1-1,ix2,1))
2400 s%w(ix^
d,mag(2))=half/s%surface(ix^
d,2)*(s%ws(ix^
d,2)*s%surfaceC(ix^
d,2)&
2401 +s%ws(ix1,ix2-1,2)*s%surfaceC(ix1,ix2-1,2))
2444 integer,
intent(in) :: ixis^
l, ixi^
l, ixo^
l
2445 double precision,
intent(inout) :: ws(ixis^s,1:nws)
2446 double precision,
intent(in) :: x(ixi^s,1:
ndim)
2448 double precision :: adummy(ixis^s,1:3)
2457 double precision :: sum_jbb_ipe, sum_j_ipe, sum_l_ipe, f_i_ipe, volume_pe
2458 double precision :: sum_jbb, sum_j, sum_l, f_i, volume, cw_sin_theta
2459 integer :: iigrid, igrid, ix^
d
2460 integer :: amode, istatus(mpi_status_size)
2461 integer,
save :: fhmf
2462 logical :: patchwi(ixg^t)
2463 logical,
save :: logmfopened=.false.
2464 character(len=800) :: filename,filehead
2465 character(len=800) :: line,datastr
2472 do iigrid=1,igridstail; igrid=igrids(iigrid);
2475 call mask_inner(ixg^
ll,
ixm^
ll,ps(igrid)%w,ps(igrid)%x,patchwi,volume_pe)
2476 sum_jbb_ipe = sum_jbb_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2477 ps(igrid)%x,1,patchwi)
2478 sum_j_ipe = sum_j_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2479 ps(igrid)%x,2,patchwi)
2480 f_i_ipe=f_i_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2481 ps(igrid)%x,3,patchwi)
2482 sum_l_ipe = sum_l_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2483 ps(igrid)%x,4,patchwi)
2485 call mpi_reduce(sum_jbb_ipe,sum_jbb,1,mpi_double_precision,&
2487 call mpi_reduce(sum_j_ipe,sum_j,1,mpi_double_precision,mpi_sum,0,&
2489 call mpi_reduce(f_i_ipe,f_i,1,mpi_double_precision,mpi_sum,0,&
2491 call mpi_reduce(sum_l_ipe,sum_l,1,mpi_double_precision,mpi_sum,0,&
2493 call mpi_reduce(volume_pe,volume,1,mpi_double_precision,mpi_sum,0,&
2499 cw_sin_theta = sum_jbb/sum_j
2505 if(.not.logmfopened)
then
2507 write(filename,
"(a,a)") trim(
base_filename),
"_mf_metrics.csv"
2511 open(unit=20,file=trim(filename),status=
'replace')
2512 close(20, status=
'delete')
2515 amode=ior(mpi_mode_create,mpi_mode_wronly)
2516 amode=ior(amode,mpi_mode_append)
2517 call mpi_file_open(mpi_comm_self,filename,amode,mpi_info_null,fhmf,
ierrmpi)
2519 filehead=
" it, time, CW_sin_theta, current, Lorenz_force, f_i"
2521 call mpi_file_write(fhmf,filehead,len_trim(filehead), &
2522 mpi_character,istatus,
ierrmpi)
2523 call mpi_file_write(fhmf,achar(10),1,mpi_character,istatus,
ierrmpi)
2527 write(datastr,
'(i8,a)')
it,
','
2528 line=trim(line)//trim(datastr)
2530 line=trim(line)//trim(datastr)
2531 write(datastr,
'(es13.6,a)') cw_sin_theta,
','
2532 line=trim(line)//trim(datastr)
2533 write(datastr,
'(es13.6,a)') sum_j,
','
2534 line=trim(line)//trim(datastr)
2535 write(datastr,
'(es13.6,a)') sum_l,
','
2536 line=trim(line)//trim(datastr)
2537 write(datastr,
'(es13.6)') f_i
2538 line=trim(line)//trim(datastr)//new_line(
'A')
2539 call mpi_file_write(fhmf,line,len_trim(line),mpi_character,istatus,
ierrmpi)
2541 call mpi_file_close(fhmf,
ierrmpi)
2548 subroutine mask_inner(ixI^L,ixO^L,w,x,patchwi,volume_pe)
2551 integer,
intent(in) :: ixi^
l,ixo^
l
2552 double precision,
intent(in):: w(ixi^s,nw),x(ixi^s,1:
ndim)
2553 double precision,
intent(inout) :: volume_pe
2554 logical,
intent(out) :: patchwi(ixi^s)
2556 double precision :: xo^
l
2559 {xomin^
d = xprobmin^
d + 0.05d0*(xprobmax^
d-xprobmin^
d)\}
2560 {xomax^
d = xprobmax^
d - 0.05d0*(xprobmax^
d-xprobmin^
d)\}
2562 xomin^nd = xprobmin^nd
2567 {
do ix^db=ixomin^db,ixomax^db\}
2568 if({ x(ix^dd,^
d) > xomin^
d .and. x(ix^dd,^
d) < xomax^
d | .and. })
then
2569 patchwi(ix^
d)=.true.
2570 volume_pe=volume_pe+
block%dvolume(ix^
d)
2572 patchwi(ix^
d)=.false.
2576 end subroutine mask_inner
2578 function integral_grid_mf(ixI^L,ixO^L,w,x,iw,patchwi)
2581 integer,
intent(in) :: ixi^
l,ixo^
l,iw
2582 double precision,
intent(in) :: x(ixi^s,1:
ndim)
2583 double precision :: w(ixi^s,nw+
nwauxio)
2584 logical,
intent(in) :: patchwi(ixi^s)
2586 double precision,
dimension(ixI^S,7-2*ndir:3) :: current
2587 double precision,
dimension(ixI^S,1:ndir) :: bvec,qvec
2588 double precision :: integral_grid_mf,tmp(ixi^s),bm2
2589 integer :: ix^
d,idirmin0,idirmin,idir,jdir,kdir
2591 integral_grid_mf=0.d0
2595 bvec(ixo^s,:)=w(ixo^s,mag(:))
2598 qvec(ixo^s,1:
ndir)=zero
2599 do idir=1,
ndir;
do jdir=idirmin,3;
do kdir=1,
ndir
2600 if(
lvc(idir,jdir,kdir)/=0)
then
2601 if(
lvc(idir,jdir,kdir)==1)
then
2602 qvec(ixo^s,idir)=qvec(ixo^s,idir)+current(ixo^s,jdir)*bvec(ixo^s,kdir)
2604 qvec(ixo^s,idir)=qvec(ixo^s,idir)-current(ixo^s,jdir)*bvec(ixo^s,kdir)
2607 end do;
end do;
end do
2609 {
do ix^db=ixomin^db,ixomax^db\}
2610 if(patchwi(ix^d))
then
2611 bm2=sum(bvec(ix^d,:)**2)
2612 if(bm2/=0.d0) bm2=1.d0/bm2
2613 integral_grid_mf=integral_grid_mf+sqrt(sum(qvec(ix^d,:)**2)*&
2614 bm2)*block%dvolume(ix^d)
2620 {
do ix^db=ixomin^db,ixomax^db\}
2621 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+sqrt(sum(current(ix^d,:)**2))*&
2628 {
do ix^db=ixomin^db,ixomax^db\}
2629 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+tmp(ix^d)*block%dvolume(ix^d)
2633 bvec(ixo^s,:)=w(ixo^s,mag(:))
2636 qvec(ixo^s,1:ndir)=zero
2637 do idir=1,ndir;
do jdir=idirmin,3;
do kdir=1,ndir
2638 if(lvc(idir,jdir,kdir)/=0)
then
2639 if(lvc(idir,jdir,kdir)==1)
then
2640 qvec(ixo^s,idir)=qvec(ixo^s,idir)+current(ixo^s,jdir)*bvec(ixo^s,kdir)
2642 qvec(ixo^s,idir)=qvec(ixo^s,idir)-current(ixo^s,jdir)*bvec(ixo^s,kdir)
2645 end do;
end do;
end do
2647 {
do ix^db=ixomin^db,ixomax^db\}
2648 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+&
2649 sqrt(sum(qvec(ix^d,:)**2))*block%dvolume(ix^d)
2653 end function integral_grid_mf
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
subroutine reconstruct(ixil, ixcl, idir, q, ql, qr)
Reconstruct scalar q within ixO^L to 1/2 dx in direction idir Return both left and right reconstructe...
subroutine b_from_vector_potentiala(ixisl, ixil, ixol, ws, x, a)
calculate magnetic field from vector potential A at cell edges
Module with basic grid data structures.
type(tree_node_ptr), dimension(:,:), allocatable, save igrid_to_node
Array to go from an [igrid, ipe] index to a node pointer.
subroutine, public get_divb(w, ixil, ixol, divb, nth_in)
Calculate div B within ixO.
integer, dimension(:), allocatable, public mag
Indices of the magnetic field.
Module with geometry-related routines (e.g., divergence, curl)
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 gradientf(q, x, ixil, ixol, idir, gradq, nth_in, pm_in)
subroutine gradientl(q, ixil, ixol, idir, gradq)
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
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( :^d &), pointer type_send_srl
integer, dimension(-1:1^d &), target type_send_r_p1
subroutine create_bc_mpi_datatype(nwstart, nwbc)
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( :^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 dtdiffpar
For resistive MHD, the time step is also limited by the diffusion time: .
character(len=std_len) typegrad
double precision unit_charge
Physical scaling factor for charge.
integer ixghi
Upper index of grid block arrays.
integer, dimension(3, 3, 3) lvc
Levi-Civita tensor.
double precision unit_time
Physical scaling factor for time.
double precision unit_density
Physical scaling factor for density.
integer, parameter unitpar
file handle for IO
integer, parameter bc_asymm
double precision global_time
The global simulation time.
double precision unit_mass
Physical scaling factor for mass.
integer, dimension(3, 3) kr
Kronecker delta tensor.
integer it
Number of time steps taken.
integer, dimension(:, :), allocatable typeboundary
Array indicating the type of boundary condition per variable and per physical boundary.
double precision unit_numberdensity
Physical scaling factor for number density.
double precision unit_pressure
Physical scaling factor for pressure.
integer, parameter ndim
Number of spatial dimensions for grid variables.
double precision unit_length
Physical scaling factor for length.
logical stagger_grid
True for using stagger grid.
double precision cmax_global
global fastest wave speed needed in fd scheme and glm method
logical use_particles
Use particles module or not.
character(len=std_len), dimension(:), allocatable par_files
Which par files are used as input.
integer icomm
The MPI communicator.
double precision bdip
amplitude of background dipolar, quadrupolar, octupolar, user's field
integer mype
The rank of the current MPI task.
double precision, dimension(:), allocatable, parameter d
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.
logical slab
Cartesian geometry or not.
integer, parameter bc_periodic
integer, parameter bc_special
boundary condition types
double precision unit_magneticfield
Physical scaling factor for magnetic field.
integer nwauxio
Number of auxiliary variables that are only included in output.
double precision unit_velocity
Physical scaling factor for velocity.
logical time_advance
do time evolving
character(len=std_len) restart_from_file
If not 'unavailable', resume from snapshot with this base file name.
double precision c_norm
Normalised speed of light.
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
double precision unit_temperature
Physical scaling factor for temperature.
integer, parameter bc_cont
logical si_unit
Use SI units (.true.) or use cgs units (.false.)
double precision, dimension(:,:), allocatable dx
spatial steps for all dimensions at all levels
integer nghostcells
Number of ghost cells surrounding a grid.
integer, parameter sdim
starting dimension for electric field
integer, parameter bc_symm
character(len= *), parameter undefined
logical need_global_cmax
need global maximal wave speed
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
logical use_multigrid
Use multigrid (only available in 2D and 3D)
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
character(len=std_len) base_filename
Base file name for simulation output, which will be followed by a number.
integer max_blocks
The maximum number of grid blocks in a processor.
integer r_
Indices for cylindrical coordinates FOR TESTS, negative value when not used:
logical record_electric_field
True for record electric field.
integer, parameter ixglo
Lower index of grid block arrays (always 1)
integer, public, protected b
double precision, public mf_nu
viscosity coefficient in s cm^-2 for solar corona (Cheung 2012 ApJ)
subroutine, public mf_phys_init()
integer, public, protected mf_divb_nth
Whether divB is computed with a fourth order approximation.
subroutine, public b_from_vector_potential(ixisl, ixil, ixol, ws, x)
calculate magnetic field from vector potential
logical, public, protected mf_record_electric_field
set to true if need to record electric field on cell edges
logical, public, protected clean_initial_divb
clean divb in the initial condition
logical, public divbwave
Add divB wave in Roe solver.
subroutine, public mf_face_to_center(ixol, s)
calculate cell-center values from face-center values
double precision, public mf_vmax
maximal limit of magnetofrictional velocity in cm s^-1 (Pomoell 2019 A&A)
logical, public, protected mf_glm
Whether GLM-MHD is used.
double precision, public mf_eta_hyper
The hyper-resistivity.
double precision, public mf_glm_alpha
GLM-MHD parameter: ratio of the diffusive and advective time scales for div b taking values within [0...
integer, public, protected c
Indices of the momentum density for the form of better vectorization.
integer, public, protected c_
logical, dimension(2 *^nd), public, protected boundary_divbfix
To control divB=0 fix for boundary.
character(len=std_len), public, protected type_ct
Method type of constrained transport.
character(len=std_len), public, protected typedivbfix
Method type to clean divergence of B.
subroutine, public get_normalized_divb(w, ixil, ixol, divb)
get dimensionless div B = |divB| * volume / area / |B|
integer, dimension(2 *^nd), public, protected boundary_divbfix_skip
To skip * layer of ghost cells during divB=0 fix for boundary.
double precision, dimension(2 *^nd), public mf_decay_scale
decay scale of frictional velocity near boundaries
subroutine, public record_force_free_metrics()
subroutine, public mf_to_conserved(ixil, ixol, w, x)
Transform primitive variables into conservative ones.
subroutine, public get_current(w, ixil, ixol, idirmin, current, fourthorder)
Calculate idirmin and the idirmin:3 components of the common current array make sure that dxlevel(^D)...
integer, public, protected psi_
Indices of the GLM psi.
integer, dimension(:), allocatable, public, protected mom
Indices of the momentum density.
subroutine, public mf_clean_divb_multigrid(qdt, qt, active)
logical, public, protected mf_particles
Whether particles module is added.
integer, public, protected m
subroutine, public mf_to_primitive(ixil, ixol, w, x)
Transform conservative variables into primitive ones.
double precision, public mf_eta
The resistivity.
logical, public, protected source_split_divb
Whether divB cleaning sources are added splitting from fluid solver.
double precision, public, protected he_abundance
Helium abundance over Hydrogen.
Module to couple the octree-mg library to AMRVAC. This file uses the VACPP preprocessor,...
type(mg_t) mg
Data structure containing the multigrid tree.
Module containing all the particle routines.
subroutine particles_init()
Initialize particle data and parameters.
This module defines the procedures of a physics module. It contains function pointers for the various...
procedure(sub_get_ct_velocity), pointer phys_get_ct_velocity
procedure(sub_convert), pointer phys_to_primitive
integer, parameter flux_tvdlf
Indicates the flux should be treated with tvdlf.
procedure(sub_write_info), pointer phys_write_info
procedure(sub_get_flux), pointer phys_get_flux
procedure(sub_get_cbounds), pointer phys_get_cbounds
procedure(sub_get_dt), pointer phys_get_dt
procedure(sub_add_source_geom), pointer phys_add_source_geom
procedure(sub_check_params), pointer phys_check_params
integer, parameter flux_default
Indicates a normal flux.
integer transverse_ghost_cells
extra ghost cells in the transverse dimensions for fluxes of CT
integer, dimension(:, :), allocatable flux_type
Array per direction per variable, which can be used to specify that certain fluxes have to be treated...
procedure(sub_update_faces), pointer phys_update_faces
procedure(sub_convert), pointer phys_to_conserved
character(len=name_len) physics_type
String describing the physics type of the simulation.
procedure(sub_clean_divb), pointer phys_clean_divb
procedure(sub_boundary_adjust), pointer phys_boundary_adjust
procedure(sub_global_source), pointer phys_global_source_after
procedure(sub_add_source), pointer phys_add_source
procedure(sub_face_to_center), pointer phys_face_to_center
procedure(sub_modify_wlr), pointer phys_modify_wlr
procedure(sub_get_cmax), pointer phys_get_cmax
logical phys_energy
Solve energy equation or not.
procedure(sub_special_advance), pointer phys_special_advance
Module with all the methods that users can customize in AMRVAC.
procedure(special_resistivity), pointer usr_special_resistivity
procedure(set_electric_field), pointer usr_set_electric_field
integer nw
Total number of variables.
integer number_species
number of species: each species has different characterictic speeds and should be used accordingly in...
The data structure that contains information about a tree node/grid block.