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.
88 logical :: compactres = .false.
97 character(len=std_len),
public,
protected ::
typedivbfix =
'ct'
100 character(len=std_len),
public,
protected ::
type_ct =
'average'
103 character(len=std_len) :: typedivbdiff =
'all'
123 subroutine mf_read_params(files)
126 character(len=*),
intent(in) :: files(:)
137 do n = 1,
size(files)
138 open(
unitpar, file=trim(files(n)), status=
"old")
139 read(
unitpar, mf_list,
end=111)
143 end subroutine mf_read_params
146 subroutine mf_write_info(fh)
148 integer,
intent(in) :: fh
149 integer,
parameter :: n_par = 1
150 double precision :: values(n_par)
151 character(len=name_len) :: names(n_par)
152 integer,
dimension(MPI_STATUS_SIZE) :: st
155 call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
159 call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
160 call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
161 end subroutine mf_write_info
182 type_divb = divb_none
185 type_divb = divb_multigrid
187 mg%operator_type = mg_laplacian
194 case (
'powel',
'powell')
195 type_divb = divb_powel
197 type_divb = divb_janhunen
199 type_divb = divb_linde
200 case (
'lindejanhunen')
201 type_divb = divb_lindejanhunen
203 type_divb = divb_lindepowel
207 type_divb = divb_lindeglm
212 call mpistop(
'Unknown divB fix')
217 mom(:) = var_set_momentum(
ndir)
222 mag(:) = var_set_bfield(
ndir)
227 allocate(start_indices(number_species),stop_indices(number_species))
229 start_indices(1)=mag(1)
232 psi_ = var_set_fluxvar(
'psi',
'psi', need_bc=.false.)
241 stop_indices(1)=nwflux
247 allocate(iw_vector(nvector))
248 iw_vector(1) =
mom(1) - 1
249 iw_vector(2) = mag(1) - 1
256 call mpistop(
"phys_check error: flux_type has wrong shape")
275 if(type_divb==divb_glm)
then
289 write(*,*)
'*****Using particles: particles_eta, particles_etah :', particles_eta, particles_etah
310 call mpistop(
'choose average, uct_contact,or uct_hll for type_ct!')
322 call mf_physical_units()
326 subroutine mf_check_params
329 end subroutine mf_check_params
331 subroutine mf_physical_units()
333 double precision :: mp,kb,miu0,c_lightspeed
334 double precision :: a,
b
470 end subroutine mf_physical_units
475 integer,
intent(in) :: ixi^
l, ixo^
l
476 double precision,
intent(inout) :: w(ixi^s, nw)
477 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
485 integer,
intent(in) :: ixi^
l, ixo^
l
486 double precision,
intent(inout) :: w(ixi^s, nw)
487 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
493 subroutine mf_get_cmax(w,x,ixI^L,ixO^L,idim,cmax)
496 integer,
intent(in) :: ixi^
l, ixo^
l, idim
497 double precision,
intent(in) :: w(ixi^s, nw), x(ixi^s,1:
ndim)
498 double precision,
intent(inout) :: cmax(ixi^s)
500 cmax(ixo^s)=abs(w(ixo^s,
mom(idim)))+one
502 end subroutine mf_get_cmax
505 subroutine mf_get_cbounds(wLC,wRC,wLp,wRp,x,ixI^L,ixO^L,idim,Hspeed,cmax,cmin)
509 integer,
intent(in) :: ixi^
l, ixo^
l, idim
510 double precision,
intent(in) :: wlc(ixi^s,
nw), wrc(ixi^s,
nw)
511 double precision,
intent(in) :: wlp(ixi^s,
nw), wrp(ixi^s,
nw)
512 double precision,
intent(in) :: x(ixi^s,1:
ndim)
514 double precision,
intent(inout),
optional :: cmin(ixi^s,1:
number_species)
517 double precision,
dimension(ixI^S) :: tmp1
519 tmp1(ixo^s)=0.5d0*(wlc(ixo^s,
mom(idim))+wrc(ixo^s,
mom(idim)))
520 if(
present(cmin))
then
521 cmax(ixo^s,1)=max(tmp1(ixo^s)+one,zero)
522 cmin(ixo^s,1)=min(tmp1(ixo^s)-one,zero)
524 cmax(ixo^s,1)=abs(tmp1(ixo^s))+one
527 end subroutine mf_get_cbounds
530 subroutine mf_get_ct_velocity_average(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
533 integer,
intent(in) :: ixi^
l, ixo^
l, idim
534 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
535 double precision,
intent(in) :: cmax(ixi^s)
536 double precision,
intent(in),
optional :: cmin(ixi^s)
537 type(ct_velocity),
intent(inout):: vcts
539 end subroutine mf_get_ct_velocity_average
541 subroutine mf_get_ct_velocity_contact(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
544 integer,
intent(in) :: ixi^
l, ixo^
l, idim
545 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
546 double precision,
intent(in) :: cmax(ixi^s)
547 double precision,
intent(in),
optional :: cmin(ixi^s)
548 type(ct_velocity),
intent(inout):: vcts
551 if(.not.
allocated(vcts%vnorm))
allocate(vcts%vnorm(ixi^s,1:
ndim))
553 vcts%vnorm(ixo^s,idim)=0.5d0*(wlp(ixo^s,
mom(idim))+wrp(ixo^s,
mom(idim)))
555 end subroutine mf_get_ct_velocity_contact
557 subroutine mf_get_ct_velocity_hll(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
560 integer,
intent(in) :: ixi^
l, ixo^
l, idim
561 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
562 double precision,
intent(in) :: cmax(ixi^s)
563 double precision,
intent(in),
optional :: cmin(ixi^s)
564 type(ct_velocity),
intent(inout):: vcts
566 integer :: idime,idimn
568 if(.not.
allocated(vcts%vbarC))
then
569 allocate(vcts%vbarC(ixi^s,1:
ndir,2),vcts%vbarLC(ixi^s,1:
ndir,2),vcts%vbarRC(ixi^s,1:
ndir,2))
570 allocate(vcts%cbarmin(ixi^s,1:
ndim),vcts%cbarmax(ixi^s,1:
ndim))
573 if(
present(cmin))
then
574 vcts%cbarmin(ixo^s,idim)=max(-cmin(ixo^s),zero)
575 vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
577 vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
578 vcts%cbarmin(ixo^s,idim)=vcts%cbarmax(ixo^s,idim)
581 idimn=mod(idim,
ndir)+1
582 idime=mod(idim+1,
ndir)+1
584 vcts%vbarLC(ixo^s,idim,1)=wlp(ixo^s,
mom(idimn))
585 vcts%vbarRC(ixo^s,idim,1)=wrp(ixo^s,
mom(idimn))
586 vcts%vbarC(ixo^s,idim,1)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,1) &
587 +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
588 /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
590 vcts%vbarLC(ixo^s,idim,2)=wlp(ixo^s,
mom(idime))
591 vcts%vbarRC(ixo^s,idim,2)=wrp(ixo^s,
mom(idime))
592 vcts%vbarC(ixo^s,idim,2)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,2) &
593 +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
594 /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
596 end subroutine mf_get_ct_velocity_hll
599 subroutine mf_get_flux(wC,w,x,ixI^L,ixO^L,idim,f)
604 integer,
intent(in) :: ixi^
l, ixo^
l, idim
606 double precision,
intent(in) :: wc(ixi^s,nw)
608 double precision,
intent(in) :: w(ixi^s,nw)
609 double precision,
intent(in) :: x(ixi^s,1:
ndim)
610 double precision,
intent(out) :: f(ixi^s,nwflux)
614 {
do ix^db=ixomin^db,ixomax^db\}
620 {
do ix^db=ixomin^db,ixomax^db\}
621 f(ix^d,mag(idim))=w(ix^d,
psi_)
623 f(ix^d,
psi_)=cmax_global**2*w(ix^d,mag(idim))
627 end subroutine mf_get_flux
630 subroutine mf_velocity_update(qt,psa)
633 double precision,
intent(in) :: qt
636 integer :: iigrid,igrid
637 logical :: stagger_flag
638 logical :: firstmf=.true.
653 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
655 call frictional_velocity(psa(igrid)%w,psa(igrid)%x,ixg^
ll,
ixm^
ll)
679 end subroutine mf_velocity_update
682 subroutine mf_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
685 integer,
intent(in) :: ixi^
l, ixo^
l
686 double precision,
intent(in) :: qdt, dtfactor
687 double precision,
intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw), x(ixi^s,1:
ndim)
688 double precision,
intent(inout) :: w(ixi^s,1:nw)
689 logical,
intent(in) :: qsourcesplit
690 logical,
intent(inout) :: active
692 if (.not. qsourcesplit)
then
695 if (abs(
mf_eta)>smalldouble)
then
697 call add_source_res2(qdt,ixi^
l,ixo^
l,wct,w,x)
702 call add_source_hyperres(qdt,ixi^
l,ixo^
l,wct,w,x)
710 select case (type_divb)
715 call add_source_glm(qdt,ixi^
l,ixo^
l,wct,w,x)
718 call add_source_powel(qdt,ixi^
l,ixo^
l,wct,w,x)
721 call add_source_janhunen(qdt,ixi^
l,ixo^
l,wct,w,x)
724 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
725 case (divb_lindejanhunen)
727 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
728 call add_source_janhunen(qdt,ixi^
l,ixo^
l,wct,w,x)
729 case (divb_lindepowel)
731 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
732 call add_source_powel(qdt,ixi^
l,ixo^
l,wct,w,x)
735 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
736 call add_source_glm(qdt,ixi^
l,ixo^
l,wct,w,x)
739 case (divb_multigrid)
742 call mpistop(
'Unknown divB fix')
747 end subroutine mf_add_source
749 subroutine frictional_velocity(w,x,ixI^L,ixO^L)
752 integer,
intent(in) :: ixi^
l, ixo^
l
753 double precision,
intent(in) :: x(ixi^s,1:
ndim)
754 double precision,
intent(inout) :: w(ixi^s,1:nw)
756 double precision :: xmin(
ndim),xmax(
ndim)
757 double precision :: decay(ixo^s)
758 double precision :: current(ixi^s,7-2*
ndir:3),tmp(ixo^s)
759 integer :: ix^
d, idirmin,idir,jdir,kdir
765 if(
block%is_physical_boundary(2*^
d-1))
then
768 if(2*^
d-1==5.and.
ndim==3)
then
770 current(ixomin^
d^
d%ixO^s,:)=current(ixomin^
d+1^
d%ixO^s,:)
775 current(ixomin^
d^
d%ixO^s,:)=current(ixomin^
d+1^
d%ixO^s,:)
779 if(
block%is_physical_boundary(2*^
d))
then
780 current(ixomax^
d^
d%ixO^s,:)=current(ixomax^
d-1^
d%ixO^s,:)
785 do idir=1,
ndir;
do jdir=idirmin,3;
do kdir=1,
ndir
786 if(
lvc(idir,jdir,kdir)/=0)
then
787 if(
lvc(idir,jdir,kdir)==1)
then
788 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))+current(ixo^s,jdir)*w(ixo^s,mag(kdir))
790 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))-current(ixo^s,jdir)*w(ixo^s,mag(kdir))
793 end do;
end do;
end do
795 tmp(ixo^s)=sum(w(ixo^s,mag(:))**2,dim=ndim+1)
797 where(tmp(ixo^s)/=0.d0)
798 tmp(ixo^s)=1.d0/(tmp(ixo^s)*
mf_nu)
802 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))*tmp(ixo^s)
806 ^d&xmin(^d)=xprobmin^d\
807 ^d&xmax(^d)=xprobmax^d\
817 tmp(ixo^s)=sqrt(sum(w(ixo^s,
mom(:))**2,dim=ndim+1))/
mf_vmax+1.d-12
818 tmp(ixo^s)=dtanh(tmp(ixo^s))/tmp(ixo^s)
820 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))*tmp(ixo^s)*decay(ixo^s)
823 end subroutine frictional_velocity
829 subroutine add_source_res1(qdt,ixI^L,ixO^L,wCT,w,x)
834 integer,
intent(in) :: ixi^
l, ixo^
l
835 double precision,
intent(in) :: qdt
836 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
837 double precision,
intent(inout) :: w(ixi^s,1:nw)
840 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s)
841 double precision :: gradeta(ixi^s,1:
ndim), bf(ixi^s,1:
ndir)
842 double precision :: tmp(ixi^s),tmp2(ixi^s)
843 integer :: ixa^
l,idir,jdir,kdir,idirmin,idim,jxo^
l,hxo^
l,ix
844 integer :: lxo^
l, kxo^
l
853 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
854 call mpistop(
"Error in add_source_res1: Non-conforming input limits")
861 gradeta(ixo^s,1:
ndim)=zero
867 gradeta(ixo^s,idim)=tmp(ixo^s)
871 bf(ixi^s,1:
ndir)=wct(ixi^s,mag(1:
ndir))
877 tmp2(ixi^s)=bf(ixi^s,idir)
879 lxo^
l=ixo^
l+2*
kr(idim,^
d);
880 jxo^
l=ixo^
l+
kr(idim,^
d);
881 hxo^
l=ixo^
l-
kr(idim,^
d);
882 kxo^
l=ixo^
l-2*
kr(idim,^
d);
883 tmp(ixo^s)=tmp(ixo^s)+&
884 (-tmp2(lxo^s)+16.0d0*tmp2(jxo^s)-30.0d0*tmp2(ixo^s)+16.0d0*tmp2(hxo^s)-tmp2(kxo^s)) &
889 tmp2(ixi^s)=bf(ixi^s,idir)
891 jxo^
l=ixo^
l+
kr(idim,^
d);
892 hxo^
l=ixo^
l-
kr(idim,^
d);
893 tmp(ixo^s)=tmp(ixo^s)+&
894 (tmp2(jxo^s)-2.0d0*tmp2(ixo^s)+tmp2(hxo^s))/
dxlevel(idim)**2
899 tmp(ixo^s)=tmp(ixo^s)*eta(ixo^s)
903 do jdir=1,
ndim;
do kdir=idirmin,3
904 if (
lvc(idir,jdir,kdir)/=0)
then
905 if (
lvc(idir,jdir,kdir)==1)
then
906 tmp(ixo^s)=tmp(ixo^s)-gradeta(ixo^s,jdir)*current(ixo^s,kdir)
908 tmp(ixo^s)=tmp(ixo^s)+gradeta(ixo^s,jdir)*current(ixo^s,kdir)
915 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))+qdt*tmp(ixo^s)
919 end subroutine add_source_res1
923 subroutine add_source_res2(qdt,ixI^L,ixO^L,wCT,w,x)
928 integer,
intent(in) :: ixi^
l, ixo^
l
929 double precision,
intent(in) :: qdt
930 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
931 double precision,
intent(inout) :: w(ixi^s,1:nw)
934 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s),curlj(ixi^s,1:3)
935 double precision :: tmpvec(ixi^s,1:3)
936 integer :: ixa^
l,idir,idirmin,idirmin1
943 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
944 call mpistop(
"Error in add_source_res2: Non-conforming input limits")
958 tmpvec(ixa^s,1:
ndir)=zero
960 tmpvec(ixa^s,idir)=current(ixa^s,idir)*eta(ixa^s)
967 w(ixo^s,mag(
ndir)) = w(ixo^s,mag(
ndir))-qdt*curlj(ixo^s,
ndir)
970 w(ixo^s,mag(1:
ndir)) = w(ixo^s,mag(1:
ndir))-qdt*curlj(ixo^s,1:
ndir)
973 end subroutine add_source_res2
977 subroutine add_source_hyperres(qdt,ixI^L,ixO^L,wCT,w,x)
981 integer,
intent(in) :: ixi^
l, ixo^
l
982 double precision,
intent(in) :: qdt
983 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
984 double precision,
intent(inout) :: w(ixi^s,1:nw)
986 double precision :: current(ixi^s,7-2*
ndir:3)
987 double precision :: tmpvec(ixi^s,1:3),tmpvec2(ixi^s,1:3),tmp(ixi^s),ehyper(ixi^s,1:3)
988 integer :: ixa^
l,idir,jdir,kdir,idirmin,idirmin1
991 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
992 call mpistop(
"Error in add_source_hyperres: Non-conforming input limits")
995 tmpvec(ixa^s,1:
ndir)=zero
997 tmpvec(ixa^s,jdir)=current(ixa^s,jdir)
1001 call curlvector(tmpvec,ixi^
l,ixa^
l,tmpvec2,idirmin1,1,3)
1004 tmpvec(ixa^s,1:
ndir)=zero
1005 call curlvector(tmpvec2,ixi^
l,ixa^
l,tmpvec,idirmin1,1,3)
1009 tmpvec2(ixa^s,1:
ndir)=zero
1010 call curlvector(ehyper,ixi^
l,ixa^
l,tmpvec2,idirmin1,1,3)
1013 w(ixo^s,mag(idir)) = w(ixo^s,mag(idir))-tmpvec2(ixo^s,idir)*qdt
1016 end subroutine add_source_hyperres
1018 subroutine add_source_glm(qdt,ixI^L,ixO^L,wCT,w,x)
1025 integer,
intent(in) :: ixi^
l, ixo^
l
1026 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1027 double precision,
intent(inout) :: w(ixi^s,1:nw)
1028 double precision:: divb(ixi^s)
1029 double precision :: gradpsi(ixi^s)
1030 integer :: idim,idir
1057 end subroutine add_source_glm
1060 subroutine add_source_powel(qdt,ixI^L,ixO^L,wCT,w,x)
1063 integer,
intent(in) :: ixi^
l, ixo^
l
1064 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1065 double precision,
intent(inout) :: w(ixi^s,1:nw)
1067 double precision :: divb(ixi^s)
1075 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*wct(ixo^s,
mom(idir))*divb(ixo^s)
1078 end subroutine add_source_powel
1080 subroutine add_source_janhunen(qdt,ixI^L,ixO^L,wCT,w,x)
1085 integer,
intent(in) :: ixi^
l, ixo^
l
1086 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1087 double precision,
intent(inout) :: w(ixi^s,1:nw)
1088 double precision :: divb(ixi^s)
1096 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*wct(ixo^s,
mom(idir))*divb(ixo^s)
1099 end subroutine add_source_janhunen
1101 subroutine add_source_linde(qdt,ixI^L,ixO^L,wCT,w,x)
1106 integer,
intent(in) :: ixi^
l, ixo^
l
1107 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1108 double precision,
intent(inout) :: w(ixi^s,1:nw)
1109 double precision :: divb(ixi^s),graddivb(ixi^s)
1110 integer :: idim, idir, ixp^
l, i^
d, iside
1111 logical,
dimension(-1:1^D&) :: leveljump
1119 if(i^
d==0|.and.) cycle
1120 if(neighbor_type(i^
d,
block%igrid)==2 .or. neighbor_type(i^
d,
block%igrid)==4)
then
1121 leveljump(i^
d)=.true.
1123 leveljump(i^
d)=.false.
1132 i^dd=kr(^dd,^d)*(2*iside-3);
1133 if (leveljump(i^dd))
then
1135 ixpmin^d=ixomin^d-i^d
1137 ixpmax^d=ixomax^d-i^d
1148 select case(typegrad)
1150 call gradient(divb,ixi^l,ixp^l,idim,graddivb)
1152 call gradientl(divb,ixi^l,ixp^l,idim,graddivb)
1156 if (slab_uniform)
then
1157 graddivb(ixp^s)=graddivb(ixp^s)*divbdiff/(^d&1.0d0/dxlevel(^d)**2+)
1159 graddivb(ixp^s)=graddivb(ixp^s)*divbdiff &
1160 /(^d&1.0d0/block%ds(ixp^s,^d)**2+)
1163 w(ixp^s,mag(idim))=w(ixp^s,mag(idim))+graddivb(ixp^s)
1166 end subroutine add_source_linde
1174 integer,
intent(in) :: ixi^
l, ixo^
l
1175 double precision,
intent(in) :: w(ixi^s,1:nw)
1176 double precision :: divb(ixi^s), dsurface(ixi^s)
1178 double precision :: invb(ixo^s)
1179 integer :: ixa^
l,idims
1181 call get_divb(w,ixi^
l,ixo^
l,divb)
1182 invb(ixo^s)=sqrt(sum(w(ixo^s, mag(:))**2, dim=
ndim+1))
1183 where(invb(ixo^s)/=0.d0)
1184 invb(ixo^s)=1.d0/invb(ixo^s)
1187 divb(ixo^s)=0.5d0*abs(divb(ixo^s))*invb(ixo^s)/sum(1.d0/
dxlevel(:))
1189 ixamin^
d=ixomin^
d-1;
1190 ixamax^
d=ixomax^
d-1;
1191 dsurface(ixo^s)= sum(
block%surfaceC(ixo^s,:),dim=
ndim+1)
1193 ixa^
l=ixo^
l-
kr(idims,^
d);
1194 dsurface(ixo^s)=dsurface(ixo^s)+
block%surfaceC(ixa^s,idims)
1196 divb(ixo^s)=abs(divb(ixo^s))*invb(ixo^s)*&
1197 block%dvolume(ixo^s)/dsurface(ixo^s)
1208 integer,
intent(in) :: ixo^
l, ixi^
l
1209 double precision,
intent(in) :: w(ixi^s,1:nw)
1210 integer,
intent(out) :: idirmin
1211 logical,
intent(in),
optional :: fourthorder
1214 double precision :: current(ixi^s,7-2*
ndir:3)
1215 integer :: idir, idirmin0
1219 if(
present(fourthorder))
then
1228 subroutine mf_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
1232 integer,
intent(in) :: ixi^
l, ixo^
l
1233 double precision,
intent(inout) :: dtnew
1234 double precision,
intent(in) ::
dx^
d
1235 double precision,
intent(in) :: w(ixi^s,1:nw)
1236 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1238 double precision :: dxarr(
ndim)
1239 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s)
1240 integer :: idirmin,idim
1247 else if (
mf_eta<zero)
then
1254 dtdiffpar/(smalldouble+maxval(eta(ixo^s)/dxarr(idim)**2)))
1257 dtdiffpar/(smalldouble+maxval(eta(ixo^s)/
block%ds(ixo^s,idim)**2)))
1269 end subroutine mf_get_dt
1272 subroutine mf_add_source_geom(qdt,dtfactor, ixI^L,ixO^L,wCT,wprim,w,x)
1276 integer,
intent(in) :: ixi^
l, ixo^
l
1277 double precision,
intent(in) :: qdt, dtfactor, x(ixi^s,1:
ndim)
1278 double precision,
intent(inout) :: wct(ixi^s,1:nw), wprim(ixi^s,1:nw), w(ixi^s,1:nw)
1280 double precision :: tmp,invr,cs2
1281 integer :: iw,idir,ix^
d
1283 integer :: mr_,mphi_
1284 integer :: br_,bphi_
1287 br_=mag(1); bphi_=mag(1)-1+
phi_
1293 {
do ix^db=ixomin^db,ixomax^db\}
1294 w(ix^
d,bphi_)=w(ix^
d,bphi_)+qdt/x(ix^
d,1)*&
1295 (wct(ix^
d,bphi_)*wct(ix^
d,mr_) &
1296 -wct(ix^
d,br_)*wct(ix^
d,mphi_))
1300 if(
mf_glm) w(ixo^s,br_)=w(ixo^s,br_)+qdt*wct(ixo^s,
psi_)/x(ixo^s,1)
1302 {
do ix^db=ixomin^db,ixomax^db\}
1306 w(ix^d,mag(1))=w(ix^d,mag(1))+invr*2.0d0*wct(ix^d,
psi_)
1311 if(.not.stagger_grid)
then
1312 tmp=wct(ix^d,
mom(1))*wct(ix^d,mag(2))-wct(ix^d,
mom(2))*wct(ix^d,mag(1))
1313 cs2=1.d0/tan(x(ix^d,2))
1315 tmp=tmp+cs2*wct(ix^d,
psi_)
1317 w(ix^d,mag(2))=w(ix^d,mag(2))+tmp*invr
1324 if(.not.stagger_grid)
then
1325 w(ix^d,mag(3))=w(ix^d,mag(3))+invr*&
1326 (wct(ix^d,
mom(1))*wct(ix^d,mag(3)) &
1327 -wct(ix^d,
mom(3))*wct(ix^d,mag(1)))
1332 if(.not.stagger_grid)
then
1333 w(ix^d,mag(3))=w(ix^d,mag(3))+invr*&
1334 (wct(ix^d,
mom(1))*wct(ix^d,mag(3)) &
1335 -wct(ix^d,
mom(3))*wct(ix^d,mag(1)) &
1336 -(wct(ix^d,
mom(3))*wct(ix^d,mag(2)) &
1337 -wct(ix^d,
mom(2))*wct(ix^d,mag(3)))*cs2)
1344 end subroutine mf_add_source_geom
1346 subroutine mf_modify_wlr(ixI^L,ixO^L,qt,wLC,wRC,wLp,wRp,s,idir)
1349 integer,
intent(in) :: ixi^
l, ixo^
l, idir
1350 double precision,
intent(in) :: qt
1351 double precision,
intent(inout) :: wlc(ixi^s,1:nw), wrc(ixi^s,1:nw)
1352 double precision,
intent(inout) :: wlp(ixi^s,1:nw), wrp(ixi^s,1:nw)
1354 double precision :: db(ixi^s), dpsi(ixi^s)
1362 db(ixo^s) = wrp(ixo^s,mag(idir)) - wlp(ixo^s,mag(idir))
1363 dpsi(ixo^s) = wrp(ixo^s,
psi_) - wlp(ixo^s,
psi_)
1365 wlp(ixo^s,mag(idir)) = 0.5d0 * (wrp(ixo^s,mag(idir)) + wlp(ixo^s,mag(idir))) &
1367 wlp(ixo^s,
psi_) = 0.5d0 * (wrp(ixo^s,
psi_) + wlp(ixo^s,
psi_)) &
1370 wrp(ixo^s,mag(idir)) = wlp(ixo^s,mag(idir))
1373 end subroutine mf_modify_wlr
1375 subroutine mf_boundary_adjust(igrid,psb)
1377 integer,
intent(in) :: igrid
1380 integer :: ib, idims, iside, ixo^
l, i^
d
1389 i^
d=
kr(^
d,idims)*(2*iside-3);
1390 if (neighbor_type(i^
d,igrid)/=1) cycle
1391 ib=(idims-1)*2+iside
1409 call fixdivb_boundary(ixg^
ll,ixo^
l,psb(igrid)%w,psb(igrid)%x,ib)
1414 end subroutine mf_boundary_adjust
1416 subroutine fixdivb_boundary(ixG^L,ixO^L,w,x,iB)
1419 integer,
intent(in) :: ixg^
l,ixo^
l,ib
1420 double precision,
intent(inout) :: w(ixg^s,1:nw)
1421 double precision,
intent(in) :: x(ixg^s,1:
ndim)
1423 double precision :: dx1x2,dx1x3,dx2x1,dx2x3,dx3x1,dx3x2
1424 integer :: ix^
d,ixf^
l
1436 do ix1=ixfmax1,ixfmin1,-1
1437 w(ix1-1,ixfmin2:ixfmax2,mag(1))=w(ix1+1,ixfmin2:ixfmax2,mag(1)) &
1438 +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
1439 w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
1442 do ix1=ixfmax1,ixfmin1,-1
1443 w(ix1-1,ixfmin2:ixfmax2,mag(1))=( (w(ix1+1,ixfmin2:ixfmax2,mag(1))+&
1444 w(ix1,ixfmin2:ixfmax2,mag(1)))*
block%surfaceC(ix1,ixfmin2:ixfmax2,1)&
1445 +(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
1446 block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
1447 -(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
1448 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
1449 /
block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
1463 do ix1=ixfmax1,ixfmin1,-1
1464 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1465 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
1466 +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
1467 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
1468 +dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
1469 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
1472 do ix1=ixfmax1,ixfmin1,-1
1473 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1474 ( (w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
1475 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
1476 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
1477 +(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
1478 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
1479 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
1480 -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
1481 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
1482 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
1483 +(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
1484 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
1485 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
1486 -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
1487 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1488 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
1489 /
block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
1490 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
1502 do ix1=ixfmin1,ixfmax1
1503 w(ix1+1,ixfmin2:ixfmax2,mag(1))=w(ix1-1,ixfmin2:ixfmax2,mag(1)) &
1504 -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
1505 w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
1508 do ix1=ixfmin1,ixfmax1
1509 w(ix1+1,ixfmin2:ixfmax2,mag(1))=( (w(ix1-1,ixfmin2:ixfmax2,mag(1))+&
1510 w(ix1,ixfmin2:ixfmax2,mag(1)))*
block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)&
1511 -(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
1512 block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
1513 +(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
1514 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
1515 /
block%surfaceC(ix1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
1529 do ix1=ixfmin1,ixfmax1
1530 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1531 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
1532 -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
1533 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
1534 -dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
1535 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
1538 do ix1=ixfmin1,ixfmax1
1539 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1540 ( (w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
1541 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
1542 block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
1543 -(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
1544 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
1545 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
1546 +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
1547 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
1548 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
1549 -(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
1550 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
1551 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
1552 +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
1553 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1554 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
1555 /
block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
1556 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
1568 do ix2=ixfmax2,ixfmin2,-1
1569 w(ixfmin1:ixfmax1,ix2-1,mag(2))=w(ixfmin1:ixfmax1,ix2+1,mag(2)) &
1570 +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
1571 w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
1574 do ix2=ixfmax2,ixfmin2,-1
1575 w(ixfmin1:ixfmax1,ix2-1,mag(2))=( (w(ixfmin1:ixfmax1,ix2+1,mag(2))+&
1576 w(ixfmin1:ixfmax1,ix2,mag(2)))*
block%surfaceC(ixfmin1:ixfmax1,ix2,2)&
1577 +(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
1578 block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
1579 -(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
1580 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
1581 /
block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
1595 do ix2=ixfmax2,ixfmin2,-1
1596 w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
1597 ix2+1,ixfmin3:ixfmax3,mag(2)) &
1598 +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
1599 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
1600 +dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
1601 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
1604 do ix2=ixfmax2,ixfmin2,-1
1605 w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=&
1606 ( (w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))+&
1607 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
1608 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)&
1609 +(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
1610 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1611 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
1612 -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
1613 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1614 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
1615 +(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
1616 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
1617 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
1618 -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
1619 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1620 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
1621 /
block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)-&
1622 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
1634 do ix2=ixfmin2,ixfmax2
1635 w(ixfmin1:ixfmax1,ix2+1,mag(2))=w(ixfmin1:ixfmax1,ix2-1,mag(2)) &
1636 -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
1637 w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
1640 do ix2=ixfmin2,ixfmax2
1641 w(ixfmin1:ixfmax1,ix2+1,mag(2))=( (w(ixfmin1:ixfmax1,ix2-1,mag(2))+&
1642 w(ixfmin1:ixfmax1,ix2,mag(2)))*
block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)&
1643 -(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
1644 block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
1645 +(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
1646 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
1647 /
block%surfaceC(ixfmin1:ixfmax1,ix2,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
1661 do ix2=ixfmin2,ixfmax2
1662 w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
1663 ix2-1,ixfmin3:ixfmax3,mag(2)) &
1664 -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
1665 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
1666 -dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
1667 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
1670 do ix2=ixfmin2,ixfmax2
1671 w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=&
1672 ( (w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))+&
1673 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
1674 block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)&
1675 -(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
1676 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1677 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
1678 +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
1679 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1680 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
1681 -(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
1682 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
1683 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
1684 +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
1685 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1686 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
1687 /
block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)-&
1688 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
1703 do ix3=ixfmax3,ixfmin3,-1
1704 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=w(ixfmin1:ixfmax1,&
1705 ixfmin2:ixfmax2,ix3+1,mag(3)) &
1706 +dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
1707 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
1708 +dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
1709 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
1712 do ix3=ixfmax3,ixfmin3,-1
1713 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=&
1714 ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))+&
1715 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
1716 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)&
1717 +(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
1718 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1719 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
1720 -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
1721 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1722 block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
1723 +(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
1724 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
1725 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
1726 -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
1727 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
1728 block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
1729 /
block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)-&
1730 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
1743 do ix3=ixfmin3,ixfmax3
1744 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=w(ixfmin1:ixfmax1,&
1745 ixfmin2:ixfmax2,ix3-1,mag(3)) &
1746 -dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
1747 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
1748 -dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
1749 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
1752 do ix3=ixfmin3,ixfmax3
1753 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=&
1754 ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))+&
1755 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
1756 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)&
1757 -(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
1758 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1759 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
1760 +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
1761 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1762 block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
1763 -(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
1764 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
1765 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
1766 +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
1767 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
1768 block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
1769 /
block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)-&
1770 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
1775 call mpistop(
"Special boundary is not defined for this region")
1778 end subroutine fixdivb_boundary
1787 double precision,
intent(in) :: qdt
1788 double precision,
intent(in) :: qt
1789 logical,
intent(inout) :: active
1791 double precision :: tmp(ixg^t), grad(ixg^t,
ndim)
1792 double precision :: res
1793 double precision,
parameter :: max_residual = 1
d-3
1794 double precision,
parameter :: residual_reduction = 1
d-10
1796 integer,
parameter :: max_its = 50
1797 double precision :: residual_it(max_its), max_divb
1798 integer :: iigrid, igrid
1799 integer :: n, nc, lvl, ix^
l, ixc^
l, idim
1802 mg%operator_type = mg_laplacian
1810 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1811 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1814 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
1815 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1817 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1818 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1821 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
1822 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1826 write(*,*)
"mf_clean_divb_multigrid warning: unknown boundary type"
1827 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1828 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1836 do iigrid = 1, igridstail
1837 igrid = igrids(iigrid);
1840 lvl =
mg%boxes(id)%lvl
1841 nc =
mg%box_size_lvl(lvl)
1847 call get_divb(ps(igrid)%w(ixg^t, 1:nw), ixg^
ll,
ixm^
ll, tmp, &
1849 mg%boxes(id)%cc({1:nc}, mg_irhs) = tmp(
ixm^t)
1850 max_divb = max(max_divb, maxval(abs(tmp(
ixm^t))))
1855 call mpi_allreduce(mpi_in_place, max_divb, 1, mpi_double_precision, &
1858 if (
mype == 0) print *,
"Performing multigrid divB cleaning"
1859 if (
mype == 0) print *,
"iteration vs residual"
1862 call mg_fas_fmg(
mg, n>1, max_res=residual_it(n))
1863 if (
mype == 0)
write(*,
"(I4,E11.3)") n, residual_it(n)
1864 if (residual_it(n) < residual_reduction * max_divb)
exit
1866 if (
mype == 0 .and. n > max_its)
then
1867 print *,
"divb_multigrid warning: not fully converged"
1868 print *,
"current amplitude of divb: ", residual_it(max_its)
1869 print *,
"multigrid smallest grid: ", &
1870 mg%domain_size_lvl(:,
mg%lowest_lvl)
1871 print *,
"note: smallest grid ideally has <= 8 cells"
1872 print *,
"multigrid dx/dy/dz ratio: ",
mg%dr(:, 1)/
mg%dr(1, 1)
1873 print *,
"note: dx/dy/dz should be similar"
1877 call mg_fas_vcycle(
mg, max_res=res)
1878 if (res < max_residual)
exit
1880 if (res > max_residual)
call mpistop(
"divb_multigrid: no convergence")
1885 do iigrid = 1, igridstail
1886 igrid = igrids(iigrid);
1895 tmp(ix^s) =
mg%boxes(id)%cc({:,}, mg_iphi)
1899 ixcmin^
d=ixmlo^
d-
kr(idim,^
d);
1901 call gradientf(tmp,ps(igrid)%x,ixg^
ll,ixc^
l,idim,grad(ixg^t,idim))
1902 ps(igrid)%ws(ixc^s,idim)=ps(igrid)%ws(ixc^s,idim)-grad(ixc^s,idim)
1910 ps(igrid)%w(
ixm^t, mag(1:
ndim)) = &
1911 ps(igrid)%w(
ixm^t, mag(1:
ndim)) - grad(
ixm^t, :)
1922 subroutine mf_update_faces_average(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
1926 integer,
intent(in) :: ixi^
l, ixo^
l
1927 double precision,
intent(in) :: qt, qdt
1929 double precision,
intent(in) :: wp(ixi^s,1:nw)
1930 type(state) :: sct, s
1931 type(ct_velocity) :: vcts
1932 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
1933 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
1935 double precision :: circ(ixi^s,1:
ndim)
1936 double precision :: e_resi(ixi^s,
sdim:3)
1937 integer :: ix^
d,ixc^
l,ixa^
l,i1kr^
d,i2kr^
d
1938 integer :: idim1,idim2,idir,iwdim1,iwdim2
1940 associate(bfaces=>s%ws,x=>s%x)
1947 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,e_resi)
1951 i1kr^
d=
kr(idim1,^
d);
1954 i2kr^
d=
kr(idim2,^
d);
1957 if (
lvc(idim1,idim2,idir)==1)
then
1959 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
1961 {
do ix^db=ixcmin^db,ixcmax^db\}
1962 fe(ix^
d,idir)=quarter*&
1963 (fc(ix^
d,iwdim1,idim2)+fc({ix^
d+i1kr^
d},iwdim1,idim2)&
1964 -fc(ix^
d,iwdim2,idim1)-fc({ix^
d+i2kr^
d},iwdim2,idim1))
1966 if(
mf_eta/=zero) fe(ix^
d,idir)=fe(ix^
d,idir)+e_resi(ix^
d,idir)
1969 fe(ix^
d,idir)=fe(ix^
d,idir)*qdt*s%dsC(ix^
d,idir)
1977 if(
associated(usr_set_electric_field)) &
1978 call usr_set_electric_field(ixi^l,ixo^l,qt,qdt,fe,sct)
1980 circ(ixi^s,1:ndim)=zero
1986 ixcmin^d=ixomin^d-kr(idim1,^d);
1988 ixa^l=ixc^l-kr(idim2,^d);
1991 if(lvc(idim1,idim2,idir)==1)
then
1993 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
1996 else if(lvc(idim1,idim2,idir)==-1)
then
1998 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2005 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2007 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2012 end subroutine mf_update_faces_average
2015 subroutine mf_update_faces_contact(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
2019 integer,
intent(in) :: ixi^
l, ixo^
l
2020 double precision,
intent(in) :: qt, qdt
2022 double precision,
intent(in) :: wp(ixi^s,1:nw)
2023 type(state) :: sct, s
2024 type(ct_velocity) :: vcts
2025 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
2026 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
2028 double precision :: circ(ixi^s,1:
ndim)
2030 double precision :: ecc(ixi^s,
sdim:3)
2032 double precision :: el(ixi^s),er(ixi^s)
2034 double precision :: elc(ixi^s),erc(ixi^s)
2036 double precision :: jce(ixi^s,
sdim:3)
2037 integer :: hxc^
l,ixc^
l,jxc^
l,ixa^
l,ixb^
l
2038 integer :: idim1,idim2,idir,iwdim1,iwdim2
2040 associate(bfaces=>s%ws,x=>s%x,w=>s%w,vnorm=>vcts%vnorm)
2045 if(
lvc(idim1,idim2,idir)==1)
then
2046 ecc(ixi^s,idir)=ecc(ixi^s,idir)+wp(ixi^s,mag(idim1))*wp(ixi^s,
mom(idim2))
2047 else if(
lvc(idim1,idim2,idir)==-1)
then
2048 ecc(ixi^s,idir)=ecc(ixi^s,idir)-wp(ixi^s,mag(idim1))*wp(ixi^s,
mom(idim2))
2053 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,jce)
2065 if (
lvc(idim1,idim2,idir)==1)
then
2067 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
2069 jxc^
l=ixc^
l+
kr(idim1,^
d);
2070 hxc^
l=ixc^
l+
kr(idim2,^
d);
2072 fe(ixc^s,idir)=quarter*&
2073 (fc(ixc^s,iwdim1,idim2)+fc(jxc^s,iwdim1,idim2)&
2074 -fc(ixc^s,iwdim2,idim1)-fc(hxc^s,iwdim2,idim1))
2078 ixamax^
d=ixcmax^
d+
kr(idim1,^
d);
2079 el(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(ixa^s,idir)
2080 hxc^
l=ixa^
l+
kr(idim2,^
d);
2081 er(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(hxc^s,idir)
2082 where(vnorm(ixc^s,idim1)>0.d0)
2083 elc(ixc^s)=el(ixc^s)
2084 else where(vnorm(ixc^s,idim1)<0.d0)
2085 elc(ixc^s)=el(jxc^s)
2087 elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
2089 hxc^
l=ixc^
l+
kr(idim2,^
d);
2090 where(vnorm(hxc^s,idim1)>0.d0)
2091 erc(ixc^s)=er(ixc^s)
2092 else where(vnorm(hxc^s,idim1)<0.d0)
2093 erc(ixc^s)=er(jxc^s)
2095 erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
2097 fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
2100 jxc^
l=ixc^
l+
kr(idim2,^
d);
2102 ixamax^
d=ixcmax^
d+
kr(idim2,^
d);
2103 el(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(ixa^s,idir)
2104 hxc^
l=ixa^
l+
kr(idim1,^
d);
2105 er(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(hxc^s,idir)
2106 where(vnorm(ixc^s,idim2)>0.d0)
2107 elc(ixc^s)=el(ixc^s)
2108 else where(vnorm(ixc^s,idim2)<0.d0)
2109 elc(ixc^s)=el(jxc^s)
2111 elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
2113 hxc^
l=ixc^
l+
kr(idim1,^
d);
2114 where(vnorm(hxc^s,idim2)>0.d0)
2115 erc(ixc^s)=er(ixc^s)
2116 else where(vnorm(hxc^s,idim2)<0.d0)
2117 erc(ixc^s)=er(jxc^s)
2119 erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
2121 fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
2124 if(
mf_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+jce(ixc^s,idir)
2128 fe(ixc^s,idir)=fe(ixc^s,idir)*qdt*s%dsC(ixc^s,idir)
2143 circ(ixi^s,1:
ndim)=zero
2148 ixcmin^
d=ixomin^
d-
kr(idim1,^
d);
2152 if(
lvc(idim1,idim2,idir)/=0)
then
2153 hxc^
l=ixc^
l-
kr(idim2,^
d);
2155 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2156 +
lvc(idim1,idim2,idir)&
2163 where(s%surfaceC(ixc^s,idim1) > 1.0
d-9*s%dvolume(ixc^s))
2164 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2166 circ(ixc^s,idim1)=zero
2169 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2174 end subroutine mf_update_faces_contact
2177 subroutine mf_update_faces_hll(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
2182 integer,
intent(in) :: ixi^
l, ixo^
l
2183 double precision,
intent(in) :: qt, qdt
2185 double precision,
intent(in) :: wp(ixi^s,1:nw)
2186 type(state) :: sct, s
2187 type(ct_velocity) :: vcts
2188 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
2189 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
2191 double precision :: vtill(ixi^s,2)
2192 double precision :: vtilr(ixi^s,2)
2193 double precision :: btill(ixi^s,
ndim)
2194 double precision :: btilr(ixi^s,
ndim)
2195 double precision :: cp(ixi^s,2)
2196 double precision :: cm(ixi^s,2)
2197 double precision :: circ(ixi^s,1:
ndim)
2199 double precision :: jce(ixi^s,
sdim:3)
2200 integer :: hxc^
l,ixc^
l,ixcp^
l,jxc^
l,ixcm^
l
2201 integer :: idim1,idim2,idir
2203 associate(bfaces=>s%ws,bfacesct=>sct%ws,x=>s%x,vbarc=>vcts%vbarC,cbarmin=>vcts%cbarmin,&
2204 cbarmax=>vcts%cbarmax)
2217 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,jce)
2230 ixcmin^
d=ixomin^
d-1+
kr(idir,^
d);
2234 idim2=mod(idir+1,3)+1
2236 jxc^
l=ixc^
l+
kr(idim1,^
d);
2237 ixcp^
l=ixc^
l+
kr(idim2,^
d);
2241 vtill(ixi^s,2),vtilr(ixi^s,2))
2244 vtill(ixi^s,1),vtilr(ixi^s,1))
2250 btill(ixi^s,idim1),btilr(ixi^s,idim1))
2253 btill(ixi^s,idim2),btilr(ixi^s,idim2))
2257 cm(ixc^s,1)=max(cbarmin(ixcp^s,idim1),cbarmin(ixc^s,idim1))
2258 cp(ixc^s,1)=max(cbarmax(ixcp^s,idim1),cbarmax(ixc^s,idim1))
2260 cm(ixc^s,2)=max(cbarmin(jxc^s,idim2),cbarmin(ixc^s,idim2))
2261 cp(ixc^s,2)=max(cbarmax(jxc^s,idim2),cbarmax(ixc^s,idim2))
2265 fe(ixc^s,idir)=-(cp(ixc^s,1)*vtill(ixc^s,1)*btill(ixc^s,idim2) &
2266 + cm(ixc^s,1)*vtilr(ixc^s,1)*btilr(ixc^s,idim2) &
2267 - cp(ixc^s,1)*cm(ixc^s,1)*(btilr(ixc^s,idim2)-btill(ixc^s,idim2)))&
2268 /(cp(ixc^s,1)+cm(ixc^s,1)) &
2269 +(cp(ixc^s,2)*vtill(ixc^s,2)*btill(ixc^s,idim1) &
2270 + cm(ixc^s,2)*vtilr(ixc^s,2)*btilr(ixc^s,idim1) &
2271 - cp(ixc^s,2)*cm(ixc^s,2)*(btilr(ixc^s,idim1)-btill(ixc^s,idim1)))&
2272 /(cp(ixc^s,2)+cm(ixc^s,2))
2275 if(
mf_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+jce(ixc^s,idir)
2279 fe(ixc^s,idir)=qdt*s%dsC(ixc^s,idir)*fe(ixc^s,idir)
2293 circ(ixi^s,1:
ndim)=zero
2299 ixcmin^
d=ixomin^
d-
kr(idim1,^
d);
2303 if(
lvc(idim1,idim2,idir)/=0)
then
2304 hxc^
l=ixc^
l-
kr(idim2,^
d);
2306 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2307 +
lvc(idim1,idim2,idir)&
2314 where(s%surfaceC(ixc^s,idim1) > 1.0
d-9*s%dvolume(ixc^s))
2315 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2317 circ(ixc^s,idim1)=zero
2320 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2324 end subroutine mf_update_faces_hll
2327 subroutine get_resistive_electric_field(ixI^L,ixO^L,sCT,s,jce)
2332 integer,
intent(in) :: ixi^
l, ixo^
l
2333 type(state),
intent(in) :: sct, s
2335 double precision :: jce(ixi^s,
sdim:3)
2338 double precision :: jcc(ixi^s,7-2*
ndir:3)
2340 double precision :: xs(ixgs^t,1:
ndim)
2342 double precision :: eta(ixi^s)
2343 double precision :: gradi(ixgs^t)
2344 integer :: ix^
d,ixc^
l,ixa^
l,ixb^
l,idir,idirmin,idim1,idim2
2346 associate(x=>s%x,
dx=>s%dx,w=>s%w,wct=>sct%w,wcts=>sct%ws)
2352 if (
lvc(idim1,idim2,idir)==0) cycle
2353 ixcmax^
d=ixomax^
d+1;
2354 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-2;
2355 ixbmax^
d=ixcmax^
d-
kr(idir,^
d)+1;
2358 xs(ixb^s,:)=x(ixb^s,:)
2359 xs(ixb^s,idim2)=x(ixb^s,idim2)+half*
dx(ixb^s,idim2)
2360 call gradientf(wcts(ixgs^t,idim2),xs,ixgs^
ll,ixc^
l,idim1,gradi)
2361 if (
lvc(idim1,idim2,idir)==1)
then
2362 jce(ixc^s,idir)=jce(ixc^s,idir)+gradi(ixc^s)
2364 jce(ixc^s,idir)=jce(ixc^s,idir)-gradi(ixc^s)
2371 jce(ixi^s,:)=jce(ixi^s,:)*
mf_eta
2379 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
2380 jcc(ixc^s,idir)=0.d0
2382 if({ ix^
d==1 .and. ^
d==idir | .or.}) cycle
2383 ixamin^
d=ixcmin^
d+ix^
d;
2384 ixamax^
d=ixcmax^
d+ix^
d;
2385 jcc(ixc^s,idir)=jcc(ixc^s,idir)+eta(ixa^s)
2387 jcc(ixc^s,idir)=jcc(ixc^s,idir)*0.25d0
2388 jce(ixc^s,idir)=jce(ixc^s,idir)*jcc(ixc^s,idir)
2393 end subroutine get_resistive_electric_field
2399 integer,
intent(in) :: ixo^
l
2406 do ix^db=ixomin^db,ixomax^db\}
2408 s%w(ix^
d,mag(1))=half/s%surface(ix^
d,1)*(s%ws(ix^
d,1)*s%surfaceC(ix^
d,1)&
2409 +s%ws(ix1-1,ix2,ix3,1)*s%surfaceC(ix1-1,ix2,ix3,1))
2410 s%w(ix^
d,mag(2))=half/s%surface(ix^
d,2)*(s%ws(ix^
d,2)*s%surfaceC(ix^
d,2)&
2411 +s%ws(ix1,ix2-1,ix3,2)*s%surfaceC(ix1,ix2-1,ix3,2))
2412 s%w(ix^
d,mag(3))=half/s%surface(ix^
d,3)*(s%ws(ix^
d,3)*s%surfaceC(ix^
d,3)&
2413 +s%ws(ix1,ix2,ix3-1,3)*s%surfaceC(ix1,ix2,ix3-1,3))
2416 s%w(ix^
d,mag(1))=half/s%surface(ix^
d,1)*(s%ws(ix^
d,1)*s%surfaceC(ix^
d,1)&
2417 +s%ws(ix1-1,ix2,1)*s%surfaceC(ix1-1,ix2,1))
2418 s%w(ix^
d,mag(2))=half/s%surface(ix^
d,2)*(s%ws(ix^
d,2)*s%surfaceC(ix^
d,2)&
2419 +s%ws(ix1,ix2-1,2)*s%surfaceC(ix1,ix2-1,2))
2462 integer,
intent(in) :: ixis^
l, ixi^
l, ixo^
l
2463 double precision,
intent(inout) :: ws(ixis^s,1:nws)
2464 double precision,
intent(in) :: x(ixi^s,1:
ndim)
2466 double precision :: adummy(ixis^s,1:3)
2475 double precision :: sum_jbb_ipe, sum_j_ipe, sum_l_ipe, f_i_ipe, volume_pe
2476 double precision :: sum_jbb, sum_j, sum_l, f_i, volume, cw_sin_theta
2477 integer :: iigrid, igrid, ix^
d
2478 integer :: amode, istatus(mpi_status_size)
2479 integer,
save :: fhmf
2480 logical :: patchwi(ixg^t)
2481 logical,
save :: logmfopened=.false.
2482 character(len=800) :: filename,filehead
2483 character(len=800) :: line,datastr
2490 do iigrid=1,igridstail; igrid=igrids(iigrid);
2493 call mask_inner(ixg^
ll,
ixm^
ll,ps(igrid)%w,ps(igrid)%x,patchwi,volume_pe)
2494 sum_jbb_ipe = sum_jbb_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2495 ps(igrid)%x,1,patchwi)
2496 sum_j_ipe = sum_j_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2497 ps(igrid)%x,2,patchwi)
2498 f_i_ipe=f_i_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2499 ps(igrid)%x,3,patchwi)
2500 sum_l_ipe = sum_l_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2501 ps(igrid)%x,4,patchwi)
2503 call mpi_reduce(sum_jbb_ipe,sum_jbb,1,mpi_double_precision,&
2505 call mpi_reduce(sum_j_ipe,sum_j,1,mpi_double_precision,mpi_sum,0,&
2507 call mpi_reduce(f_i_ipe,f_i,1,mpi_double_precision,mpi_sum,0,&
2509 call mpi_reduce(sum_l_ipe,sum_l,1,mpi_double_precision,mpi_sum,0,&
2511 call mpi_reduce(volume_pe,volume,1,mpi_double_precision,mpi_sum,0,&
2517 cw_sin_theta = sum_jbb/sum_j
2523 if(.not.logmfopened)
then
2525 write(filename,
"(a,a)") trim(
base_filename),
"_mf_metrics.csv"
2529 open(unit=20,file=trim(filename),status=
'replace')
2530 close(20, status=
'delete')
2533 amode=ior(mpi_mode_create,mpi_mode_wronly)
2534 amode=ior(amode,mpi_mode_append)
2535 call mpi_file_open(mpi_comm_self,filename,amode,mpi_info_null,fhmf,
ierrmpi)
2537 filehead=
" it, time, CW_sin_theta, current, Lorenz_force, f_i"
2539 call mpi_file_write(fhmf,filehead,len_trim(filehead), &
2540 mpi_character,istatus,
ierrmpi)
2541 call mpi_file_write(fhmf,achar(10),1,mpi_character,istatus,
ierrmpi)
2545 write(datastr,
'(i8,a)')
it,
','
2546 line=trim(line)//trim(datastr)
2548 line=trim(line)//trim(datastr)
2549 write(datastr,
'(es13.6,a)') cw_sin_theta,
','
2550 line=trim(line)//trim(datastr)
2551 write(datastr,
'(es13.6,a)') sum_j,
','
2552 line=trim(line)//trim(datastr)
2553 write(datastr,
'(es13.6,a)') sum_l,
','
2554 line=trim(line)//trim(datastr)
2555 write(datastr,
'(es13.6)') f_i
2556 line=trim(line)//trim(datastr)//new_line(
'A')
2557 call mpi_file_write(fhmf,line,len_trim(line),mpi_character,istatus,
ierrmpi)
2559 call mpi_file_close(fhmf,
ierrmpi)
2566 subroutine mask_inner(ixI^L,ixO^L,w,x,patchwi,volume_pe)
2569 integer,
intent(in) :: ixi^
l,ixo^
l
2570 double precision,
intent(in):: w(ixi^s,nw),x(ixi^s,1:
ndim)
2571 double precision,
intent(inout) :: volume_pe
2572 logical,
intent(out) :: patchwi(ixi^s)
2574 double precision :: xo^
l
2577 {xomin^
d = xprobmin^
d + 0.05d0*(xprobmax^
d-xprobmin^
d)\}
2578 {xomax^
d = xprobmax^
d - 0.05d0*(xprobmax^
d-xprobmin^
d)\}
2580 xomin^nd = xprobmin^nd
2585 {
do ix^db=ixomin^db,ixomax^db\}
2586 if({ x(ix^dd,^
d) > xomin^
d .and. x(ix^dd,^
d) < xomax^
d | .and. })
then
2587 patchwi(ix^
d)=.true.
2588 volume_pe=volume_pe+
block%dvolume(ix^
d)
2590 patchwi(ix^
d)=.false.
2594 end subroutine mask_inner
2596 function integral_grid_mf(ixI^L,ixO^L,w,x,iw,patchwi)
2599 integer,
intent(in) :: ixi^
l,ixo^
l,iw
2600 double precision,
intent(in) :: x(ixi^s,1:
ndim)
2601 double precision :: w(ixi^s,nw+
nwauxio)
2602 logical,
intent(in) :: patchwi(ixi^s)
2604 double precision,
dimension(ixI^S,7-2*ndir:3) :: current
2605 double precision,
dimension(ixI^S,1:ndir) :: bvec,qvec
2606 double precision :: integral_grid_mf,tmp(ixi^s),bm2
2607 integer :: ix^
d,idirmin0,idirmin,idir,jdir,kdir
2609 integral_grid_mf=0.d0
2613 bvec(ixo^s,:)=w(ixo^s,mag(:))
2616 qvec(ixo^s,1:
ndir)=zero
2617 do idir=1,
ndir;
do jdir=idirmin,3;
do kdir=1,
ndir
2618 if(
lvc(idir,jdir,kdir)/=0)
then
2619 if(
lvc(idir,jdir,kdir)==1)
then
2620 qvec(ixo^s,idir)=qvec(ixo^s,idir)+current(ixo^s,jdir)*bvec(ixo^s,kdir)
2622 qvec(ixo^s,idir)=qvec(ixo^s,idir)-current(ixo^s,jdir)*bvec(ixo^s,kdir)
2625 end do;
end do;
end do
2627 {
do ix^db=ixomin^db,ixomax^db\}
2628 if(patchwi(ix^d))
then
2629 bm2=sum(bvec(ix^d,:)**2)
2630 if(bm2/=0.d0) bm2=1.d0/bm2
2631 integral_grid_mf=integral_grid_mf+sqrt(sum(qvec(ix^d,:)**2)*&
2632 bm2)*block%dvolume(ix^d)
2638 {
do ix^db=ixomin^db,ixomax^db\}
2639 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+sqrt(sum(current(ix^d,:)**2))*&
2646 {
do ix^db=ixomin^db,ixomax^db\}
2647 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+tmp(ix^d)*block%dvolume(ix^d)
2651 bvec(ixo^s,:)=w(ixo^s,mag(:))
2654 qvec(ixo^s,1:ndir)=zero
2655 do idir=1,ndir;
do jdir=idirmin,3;
do kdir=1,ndir
2656 if(lvc(idir,jdir,kdir)/=0)
then
2657 if(lvc(idir,jdir,kdir)==1)
then
2658 qvec(ixo^s,idir)=qvec(ixo^s,idir)+current(ixo^s,jdir)*bvec(ixo^s,kdir)
2660 qvec(ixo^s,idir)=qvec(ixo^s,idir)-current(ixo^s,jdir)*bvec(ixo^s,kdir)
2663 end do;
end do;
end do
2665 {
do ix^db=ixomin^db,ixomax^db\}
2666 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+&
2667 sqrt(sum(qvec(ix^d,:)**2))*block%dvolume(ix^d)
2671 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.
logical, public, protected mf_4th_order
MHD fourth order.
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.