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 ::
psi_
49 integer,
parameter :: divb_none = 0
50 integer,
parameter :: divb_multigrid = -1
51 integer,
parameter :: divb_glm = 1
52 integer,
parameter :: divb_powel = 2
53 integer,
parameter :: divb_janhunen = 3
54 integer,
parameter :: divb_linde = 4
55 integer,
parameter :: divb_lindejanhunen = 5
56 integer,
parameter :: divb_lindepowel = 6
57 integer,
parameter :: divb_lindeglm = 7
58 integer,
parameter :: divb_ct = 8
64 logical,
public,
protected ::
mf_glm = .false.
82 logical :: compactres = .false.
91 character(len=std_len),
public,
protected ::
typedivbfix =
'ct'
94 character(len=std_len),
public,
protected ::
type_ct =
'average'
97 character(len=std_len) :: typedivbdiff =
'all'
117 subroutine mf_read_params(files)
120 character(len=*),
intent(in) :: files(:)
131 do n = 1,
size(files)
132 open(
unitpar, file=trim(files(n)), status=
"old")
133 read(
unitpar, mf_list,
end=111)
137 end subroutine mf_read_params
140 subroutine mf_write_info(fh)
142 integer,
intent(in) :: fh
143 integer,
parameter :: n_par = 1
144 double precision :: values(n_par)
145 character(len=name_len) :: names(n_par)
146 integer,
dimension(MPI_STATUS_SIZE) :: st
149 call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
153 call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
154 call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
155 end subroutine mf_write_info
176 type_divb = divb_none
179 type_divb = divb_multigrid
181 mg%operator_type = mg_laplacian
188 case (
'powel',
'powell')
189 type_divb = divb_powel
191 type_divb = divb_janhunen
193 type_divb = divb_linde
194 case (
'lindejanhunen')
195 type_divb = divb_lindejanhunen
197 type_divb = divb_lindepowel
201 type_divb = divb_lindeglm
206 call mpistop(
'Unknown divB fix')
211 mag(:) = var_set_bfield(
ndir)
215 allocate(start_indices(number_species),stop_indices(number_species))
217 start_indices(1)=mag(1)
220 psi_ = var_set_fluxvar(
'psi',
'psi', need_bc=.false.)
227 mom(:) = var_set_momentum(
ndir)
239 stop_indices(1)=nwflux
245 allocate(iw_vector(nvector))
246 iw_vector(1) =
mom(1) - 1
247 iw_vector(2) = mag(1) - 1
254 call mpistop(
"phys_check error: flux_type has wrong shape")
273 if(type_divb==divb_glm)
then
287 write(*,*)
'*****Using particles: particles_eta, particles_etah :', particles_eta, particles_etah
306 call mf_physical_units()
310 subroutine mf_check_params
313 end subroutine mf_check_params
315 subroutine mf_physical_units()
317 double precision :: mp,kb,miu0,c_lightspeed
372 end subroutine mf_physical_units
377 integer,
intent(in) :: ixi^
l, ixo^
l
378 double precision,
intent(inout) :: w(ixi^s, nw)
379 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
387 integer,
intent(in) :: ixi^
l, ixo^
l
388 double precision,
intent(inout) :: w(ixi^s, nw)
389 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
395 subroutine mf_get_cmax(w,x,ixI^L,ixO^L,idim,cmax)
398 integer,
intent(in) :: ixi^
l, ixo^
l, idim
399 double precision,
intent(in) :: w(ixi^s, nw), x(ixi^s,1:
ndim)
400 double precision,
intent(inout) :: cmax(ixi^s)
402 cmax(ixo^s)=abs(w(ixo^s,
mom(idim)))+one
404 end subroutine mf_get_cmax
407 subroutine mf_get_cbounds(wLC,wRC,wLp,wRp,x,ixI^L,ixO^L,idim,Hspeed,cmax,cmin)
411 integer,
intent(in) :: ixi^
l, ixo^
l, idim
412 double precision,
intent(in) :: wlc(ixi^s,
nw), wrc(ixi^s,
nw)
413 double precision,
intent(in) :: wlp(ixi^s,
nw), wrp(ixi^s,
nw)
414 double precision,
intent(in) :: x(ixi^s,1:
ndim)
416 double precision,
intent(inout),
optional :: cmin(ixi^s,1:
number_species)
419 double precision,
dimension(ixI^S) :: tmp1
421 tmp1(ixo^s)=0.5d0*(wlc(ixo^s,
mom(idim))+wrc(ixo^s,
mom(idim)))
422 if(
present(cmin))
then
423 cmax(ixo^s,1)=max(tmp1(ixo^s)+one,zero)
424 cmin(ixo^s,1)=min(tmp1(ixo^s)-one,zero)
426 cmax(ixo^s,1)=abs(tmp1(ixo^s))+one
429 end subroutine mf_get_cbounds
432 subroutine mf_get_ct_velocity(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
435 integer,
intent(in) :: ixi^
l, ixo^
l, idim
436 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
437 double precision,
intent(in) :: cmax(ixi^s)
438 double precision,
intent(in),
optional :: cmin(ixi^s)
439 type(ct_velocity),
intent(inout):: vcts
441 integer :: idime,idimn
447 if(.not.
allocated(vcts%vnorm))
allocate(vcts%vnorm(ixi^s,1:
ndim))
449 vcts%vnorm(ixo^s,idim)=0.5d0*(wlp(ixo^s,
mom(idim))+wrp(ixo^s,
mom(idim)))
451 if(.not.
allocated(vcts%vbarC))
then
452 allocate(vcts%vbarC(ixi^s,1:
ndir,2),vcts%vbarLC(ixi^s,1:
ndir,2),vcts%vbarRC(ixi^s,1:
ndir,2))
453 allocate(vcts%cbarmin(ixi^s,1:
ndim),vcts%cbarmax(ixi^s,1:
ndim))
456 if(
present(cmin))
then
457 vcts%cbarmin(ixo^s,idim)=max(-cmin(ixo^s),zero)
458 vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
460 vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
461 vcts%cbarmin(ixo^s,idim)=vcts%cbarmax(ixo^s,idim)
464 idimn=mod(idim,
ndir)+1
465 idime=mod(idim+1,
ndir)+1
467 vcts%vbarLC(ixo^s,idim,1)=wlp(ixo^s,
mom(idimn))
468 vcts%vbarRC(ixo^s,idim,1)=wrp(ixo^s,
mom(idimn))
469 vcts%vbarC(ixo^s,idim,1)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,1) &
470 +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
471 /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
473 vcts%vbarLC(ixo^s,idim,2)=wlp(ixo^s,
mom(idime))
474 vcts%vbarRC(ixo^s,idim,2)=wrp(ixo^s,
mom(idime))
475 vcts%vbarC(ixo^s,idim,2)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,2) &
476 +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
477 /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
479 call mpistop(
'choose average, uct_contact,or uct_hll for type_ct!')
482 end subroutine mf_get_ct_velocity
485 subroutine mf_get_flux(wC,w,x,ixI^L,ixO^L,idim,f)
490 integer,
intent(in) :: ixi^
l, ixo^
l, idim
492 double precision,
intent(in) :: wc(ixi^s,nw)
494 double precision,
intent(in) :: w(ixi^s,nw)
495 double precision,
intent(in) :: x(ixi^s,1:
ndim)
496 double precision,
intent(out) :: f(ixi^s,nwflux)
498 integer :: idir, ix^
d
501 {
do ix^db=ixomin^db,ixomax^db\}
504 f(ix^
d,mag(idir))=w(ix^
d,
mom(idim))*w(ix^
d,mag(idir))-w(ix^
d,mag(idim))*w(ix^
d,
mom(idir))
508 {
do ix^db=ixomin^db,ixomax^db\}
509 f(ix^d,mag(idim))=w(ix^d,
psi_)
511 f(ix^d,
psi_)=cmax_global**2*w(ix^d,mag(idim))
515 end subroutine mf_get_flux
518 subroutine mf_velocity_update(qt,psa)
521 double precision,
intent(in) :: qt
524 integer :: iigrid,igrid
525 logical :: stagger_flag
526 logical :: firstmf=.true.
541 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
543 call frictional_velocity(psa(igrid)%w,psa(igrid)%x,ixg^
ll,
ixm^
ll)
567 end subroutine mf_velocity_update
570 subroutine mf_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
573 integer,
intent(in) :: ixi^
l, ixo^
l
574 double precision,
intent(in) :: qdt, dtfactor
575 double precision,
intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw), x(ixi^s,1:
ndim)
576 double precision,
intent(inout) :: w(ixi^s,1:nw)
577 logical,
intent(in) :: qsourcesplit
578 logical,
intent(inout) :: active
580 if (.not. qsourcesplit)
then
583 if (abs(
mf_eta)>smalldouble)
then
585 call add_source_res2(qdt,ixi^
l,ixo^
l,wct,w,x)
590 call add_source_hyperres(qdt,ixi^
l,ixo^
l,wct,w,x)
598 select case (type_divb)
603 call add_source_glm(qdt,ixi^
l,ixo^
l,wct,w,x)
606 call add_source_powel(qdt,ixi^
l,ixo^
l,wct,w,x)
609 call add_source_janhunen(qdt,ixi^
l,ixo^
l,wct,w,x)
612 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
613 case (divb_lindejanhunen)
615 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
616 call add_source_janhunen(qdt,ixi^
l,ixo^
l,wct,w,x)
617 case (divb_lindepowel)
619 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
620 call add_source_powel(qdt,ixi^
l,ixo^
l,wct,w,x)
623 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
624 call add_source_glm(qdt,ixi^
l,ixo^
l,wct,w,x)
627 case (divb_multigrid)
630 call mpistop(
'Unknown divB fix')
635 end subroutine mf_add_source
637 subroutine frictional_velocity(w,x,ixI^L,ixO^L)
640 integer,
intent(in) :: ixi^
l, ixo^
l
641 double precision,
intent(in) :: x(ixi^s,1:
ndim)
642 double precision,
intent(inout) :: w(ixi^s,1:nw)
644 double precision :: xmin(
ndim),xmax(
ndim)
645 double precision :: decay(ixo^s)
646 double precision :: current(ixi^s,7-2*
ndir:3),tmp(ixo^s)
647 integer :: ix^
d, idirmin,idir,jdir,kdir
653 if(
block%is_physical_boundary(2*^
d-1))
then
656 if(2*^
d-1==5.and.
ndim==3)
then
658 current(ixomin^
d^
d%ixO^s,:)=current(ixomin^
d+1^
d%ixO^s,:)
663 current(ixomin^
d^
d%ixO^s,:)=current(ixomin^
d+1^
d%ixO^s,:)
667 if(
block%is_physical_boundary(2*^
d))
then
668 current(ixomax^
d^
d%ixO^s,:)=current(ixomax^
d-1^
d%ixO^s,:)
673 do idir=1,
ndir;
do jdir=idirmin,3;
do kdir=1,
ndir
674 if(
lvc(idir,jdir,kdir)/=0)
then
675 if(
lvc(idir,jdir,kdir)==1)
then
676 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))+current(ixo^s,jdir)*w(ixo^s,mag(kdir))
678 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))-current(ixo^s,jdir)*w(ixo^s,mag(kdir))
681 end do;
end do;
end do
683 tmp(ixo^s)=sum(w(ixo^s,mag(:))**2,dim=ndim+1)
685 where(tmp(ixo^s)/=0.d0)
686 tmp(ixo^s)=1.d0/(tmp(ixo^s)*
mf_nu)
690 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))*tmp(ixo^s)
694 ^d&xmin(^d)=xprobmin^d\
695 ^d&xmax(^d)=xprobmax^d\
705 tmp(ixo^s)=sqrt(sum(w(ixo^s,
mom(:))**2,dim=ndim+1))/
mf_vmax+1.d-12
706 tmp(ixo^s)=dtanh(tmp(ixo^s))/tmp(ixo^s)
708 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))*tmp(ixo^s)*decay(ixo^s)
711 end subroutine frictional_velocity
717 subroutine add_source_res1(qdt,ixI^L,ixO^L,wCT,w,x)
722 integer,
intent(in) :: ixi^
l, ixo^
l
723 double precision,
intent(in) :: qdt
724 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
725 double precision,
intent(inout) :: w(ixi^s,1:nw)
728 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s)
729 double precision :: gradeta(ixi^s,1:
ndim), bf(ixi^s,1:
ndir)
730 double precision :: tmp(ixi^s),tmp2(ixi^s)
731 integer :: ixa^
l,idir,jdir,kdir,idirmin,idim,jxo^
l,hxo^
l,ix
732 integer :: lxo^
l, kxo^
l
741 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
742 call mpistop(
"Error in add_source_res1: Non-conforming input limits")
749 gradeta(ixo^s,1:
ndim)=zero
755 gradeta(ixo^s,idim)=tmp(ixo^s)
759 bf(ixi^s,1:
ndir)=wct(ixi^s,mag(1:
ndir))
765 tmp2(ixi^s)=bf(ixi^s,idir)
767 lxo^
l=ixo^
l+2*
kr(idim,^
d);
768 jxo^
l=ixo^
l+
kr(idim,^
d);
769 hxo^
l=ixo^
l-
kr(idim,^
d);
770 kxo^
l=ixo^
l-2*
kr(idim,^
d);
771 tmp(ixo^s)=tmp(ixo^s)+&
772 (-tmp2(lxo^s)+16.0d0*tmp2(jxo^s)-30.0d0*tmp2(ixo^s)+16.0d0*tmp2(hxo^s)-tmp2(kxo^s)) &
777 tmp2(ixi^s)=bf(ixi^s,idir)
779 jxo^
l=ixo^
l+
kr(idim,^
d);
780 hxo^
l=ixo^
l-
kr(idim,^
d);
781 tmp(ixo^s)=tmp(ixo^s)+&
782 (tmp2(jxo^s)-2.0d0*tmp2(ixo^s)+tmp2(hxo^s))/
dxlevel(idim)**2
787 tmp(ixo^s)=tmp(ixo^s)*eta(ixo^s)
791 do jdir=1,
ndim;
do kdir=idirmin,3
792 if (
lvc(idir,jdir,kdir)/=0)
then
793 if (
lvc(idir,jdir,kdir)==1)
then
794 tmp(ixo^s)=tmp(ixo^s)-gradeta(ixo^s,jdir)*current(ixo^s,kdir)
796 tmp(ixo^s)=tmp(ixo^s)+gradeta(ixo^s,jdir)*current(ixo^s,kdir)
803 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))+qdt*tmp(ixo^s)
807 end subroutine add_source_res1
811 subroutine add_source_res2(qdt,ixI^L,ixO^L,wCT,w,x)
816 integer,
intent(in) :: ixi^
l, ixo^
l
817 double precision,
intent(in) :: qdt
818 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
819 double precision,
intent(inout) :: w(ixi^s,1:nw)
822 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s),curlj(ixi^s,1:3)
823 double precision :: tmpvec(ixi^s,1:3)
824 integer :: ixa^
l,idir,idirmin,idirmin1
831 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
832 call mpistop(
"Error in add_source_res2: Non-conforming input limits")
846 tmpvec(ixa^s,1:
ndir)=zero
848 tmpvec(ixa^s,idir)=current(ixa^s,idir)*eta(ixa^s)
855 w(ixo^s,mag(
ndir)) = w(ixo^s,mag(
ndir))-qdt*curlj(ixo^s,
ndir)
858 w(ixo^s,mag(1:
ndir)) = w(ixo^s,mag(1:
ndir))-qdt*curlj(ixo^s,1:
ndir)
861 end subroutine add_source_res2
865 subroutine add_source_hyperres(qdt,ixI^L,ixO^L,wCT,w,x)
869 integer,
intent(in) :: ixi^
l, ixo^
l
870 double precision,
intent(in) :: qdt
871 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
872 double precision,
intent(inout) :: w(ixi^s,1:nw)
874 double precision :: current(ixi^s,7-2*
ndir:3)
875 double precision :: tmpvec(ixi^s,1:3),tmpvec2(ixi^s,1:3),tmp(ixi^s),ehyper(ixi^s,1:3)
876 integer :: ixa^
l,idir,jdir,kdir,idirmin,idirmin1
879 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
880 call mpistop(
"Error in add_source_hyperres: Non-conforming input limits")
883 tmpvec(ixa^s,1:
ndir)=zero
885 tmpvec(ixa^s,jdir)=current(ixa^s,jdir)
889 call curlvector(tmpvec,ixi^
l,ixa^
l,tmpvec2,idirmin1,1,3)
892 tmpvec(ixa^s,1:
ndir)=zero
893 call curlvector(tmpvec2,ixi^
l,ixa^
l,tmpvec,idirmin1,1,3)
897 tmpvec2(ixa^s,1:
ndir)=zero
898 call curlvector(ehyper,ixi^
l,ixa^
l,tmpvec2,idirmin1,1,3)
901 w(ixo^s,mag(idir)) = w(ixo^s,mag(idir))-tmpvec2(ixo^s,idir)*qdt
904 end subroutine add_source_hyperres
906 subroutine add_source_glm(qdt,ixI^L,ixO^L,wCT,w,x)
913 integer,
intent(in) :: ixi^
l, ixo^
l
914 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
915 double precision,
intent(inout) :: w(ixi^s,1:nw)
916 double precision:: divb(ixi^s)
917 double precision :: gradpsi(ixi^s)
945 end subroutine add_source_glm
948 subroutine add_source_powel(qdt,ixI^L,ixO^L,wCT,w,x)
951 integer,
intent(in) :: ixi^
l, ixo^
l
952 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
953 double precision,
intent(inout) :: w(ixi^s,1:nw)
955 double precision :: divb(ixi^s)
963 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*wct(ixo^s,
mom(idir))*divb(ixo^s)
966 end subroutine add_source_powel
968 subroutine add_source_janhunen(qdt,ixI^L,ixO^L,wCT,w,x)
973 integer,
intent(in) :: ixi^
l, ixo^
l
974 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
975 double precision,
intent(inout) :: w(ixi^s,1:nw)
976 double precision :: divb(ixi^s)
984 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*wct(ixo^s,
mom(idir))*divb(ixo^s)
987 end subroutine add_source_janhunen
989 subroutine add_source_linde(qdt,ixI^L,ixO^L,wCT,w,x)
994 integer,
intent(in) :: ixi^
l, ixo^
l
995 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
996 double precision,
intent(inout) :: w(ixi^s,1:nw)
997 double precision :: divb(ixi^s),graddivb(ixi^s)
998 integer :: idim, idir, ixp^
l, i^
d, iside
999 logical,
dimension(-1:1^D&) :: leveljump
1007 if(i^
d==0|.and.) cycle
1008 if(neighbor_type(i^
d,
block%igrid)==2 .or. neighbor_type(i^
d,
block%igrid)==4)
then
1009 leveljump(i^
d)=.true.
1011 leveljump(i^
d)=.false.
1020 i^dd=kr(^dd,^d)*(2*iside-3);
1021 if (leveljump(i^dd))
then
1023 ixpmin^d=ixomin^d-i^d
1025 ixpmax^d=ixomax^d-i^d
1036 select case(typegrad)
1038 call gradient(divb,ixi^l,ixp^l,idim,graddivb)
1040 call gradientl(divb,ixi^l,ixp^l,idim,graddivb)
1044 if (slab_uniform)
then
1045 graddivb(ixp^s)=graddivb(ixp^s)*divbdiff/(^d&1.0d0/dxlevel(^d)**2+)
1047 graddivb(ixp^s)=graddivb(ixp^s)*divbdiff &
1048 /(^d&1.0d0/block%ds(ixp^s,^d)**2+)
1051 w(ixp^s,mag(idim))=w(ixp^s,mag(idim))+graddivb(ixp^s)
1054 end subroutine add_source_linde
1062 integer,
intent(in) :: ixi^
l, ixo^
l
1063 double precision,
intent(in) :: w(ixi^s,1:nw)
1064 double precision :: divb(ixi^s), dsurface(ixi^s)
1066 double precision :: invb(ixo^s)
1067 integer :: ixa^
l,idims
1069 call get_divb(w,ixi^
l,ixo^
l,divb)
1070 invb(ixo^s)=sqrt(sum(w(ixo^s, mag(:))**2, dim=
ndim+1))
1071 where(invb(ixo^s)/=0.d0)
1072 invb(ixo^s)=1.d0/invb(ixo^s)
1075 divb(ixo^s)=0.5d0*abs(divb(ixo^s))*invb(ixo^s)/sum(1.d0/
dxlevel(:))
1077 ixamin^
d=ixomin^
d-1;
1078 ixamax^
d=ixomax^
d-1;
1079 dsurface(ixo^s)= sum(
block%surfaceC(ixo^s,:),dim=
ndim+1)
1081 ixa^
l=ixo^
l-
kr(idims,^
d);
1082 dsurface(ixo^s)=dsurface(ixo^s)+
block%surfaceC(ixa^s,idims)
1084 divb(ixo^s)=abs(divb(ixo^s))*invb(ixo^s)*&
1085 block%dvolume(ixo^s)/dsurface(ixo^s)
1096 integer,
intent(in) :: ixo^
l, ixi^
l
1097 double precision,
intent(in) :: w(ixi^s,1:nw)
1098 integer,
intent(out) :: idirmin
1099 logical,
intent(in),
optional :: fourthorder
1102 double precision :: current(ixi^s,7-2*
ndir:3)
1103 integer :: idir, idirmin0
1107 if(
present(fourthorder))
then
1116 subroutine mf_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
1120 integer,
intent(in) :: ixi^
l, ixo^
l
1121 double precision,
intent(inout) :: dtnew
1122 double precision,
intent(in) ::
dx^
d
1123 double precision,
intent(in) :: w(ixi^s,1:nw)
1124 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1126 double precision :: dxarr(
ndim)
1127 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s)
1128 integer :: idirmin,idim
1135 else if (
mf_eta<zero)
then
1142 dtdiffpar/(smalldouble+maxval(eta(ixo^s)/dxarr(idim)**2)))
1145 dtdiffpar/(smalldouble+maxval(eta(ixo^s)/
block%ds(ixo^s,idim)**2)))
1157 end subroutine mf_get_dt
1160 subroutine mf_add_source_geom(qdt,dtfactor, ixI^L,ixO^L,wCT,wprim,w,x)
1164 integer,
intent(in) :: ixi^
l, ixo^
l
1165 double precision,
intent(in) :: qdt, dtfactor, x(ixi^s,1:
ndim)
1166 double precision,
intent(inout) :: wct(ixi^s,1:nw), wprim(ixi^s,1:nw), w(ixi^s,1:nw)
1168 double precision :: tmp,invr,cs2
1169 integer :: iw,idir,ix^
d
1171 integer :: mr_,mphi_
1172 integer :: br_,bphi_
1175 br_=mag(1); bphi_=mag(1)-1+
phi_
1181 {
do ix^db=ixomin^db,ixomax^db\}
1182 w(ix^
d,bphi_)=w(ix^
d,bphi_)+qdt/x(ix^
d,1)*&
1183 (wct(ix^
d,bphi_)*wct(ix^
d,mr_) &
1184 -wct(ix^
d,br_)*wct(ix^
d,mphi_))
1188 if(
mf_glm) w(ixo^s,br_)=w(ixo^s,br_)+qdt*wct(ixo^s,
psi_)/x(ixo^s,1)
1190 {
do ix^db=ixomin^db,ixomax^db\}
1194 w(ix^d,mag(1))=w(ix^d,mag(1))+invr*2.0d0*wct(ix^d,
psi_)
1199 if(.not.stagger_grid)
then
1200 tmp=wct(ix^d,
mom(1))*wct(ix^d,mag(2))-wct(ix^d,
mom(2))*wct(ix^d,mag(1))
1201 cs2=1.d0/tan(x(ix^d,2))
1203 tmp=tmp+cs2*wct(ix^d,
psi_)
1205 w(ix^d,mag(2))=w(ix^d,mag(2))+tmp*invr
1212 if(.not.stagger_grid)
then
1213 w(ix^d,mag(3))=w(ix^d,mag(3))+invr*&
1214 (wct(ix^d,
mom(1))*wct(ix^d,mag(3)) &
1215 -wct(ix^d,
mom(3))*wct(ix^d,mag(1)))
1220 if(.not.stagger_grid)
then
1221 w(ix^d,mag(3))=w(ix^d,mag(3))+invr*&
1222 (wct(ix^d,
mom(1))*wct(ix^d,mag(3)) &
1223 -wct(ix^d,
mom(3))*wct(ix^d,mag(1)) &
1224 -(wct(ix^d,
mom(3))*wct(ix^d,mag(2)) &
1225 -wct(ix^d,
mom(2))*wct(ix^d,mag(3)))*cs2)
1232 end subroutine mf_add_source_geom
1234 subroutine mf_modify_wlr(ixI^L,ixO^L,qt,wLC,wRC,wLp,wRp,s,idir)
1237 integer,
intent(in) :: ixi^
l, ixo^
l, idir
1238 double precision,
intent(in) :: qt
1239 double precision,
intent(inout) :: wlc(ixi^s,1:nw), wrc(ixi^s,1:nw)
1240 double precision,
intent(inout) :: wlp(ixi^s,1:nw), wrp(ixi^s,1:nw)
1242 double precision :: db(ixi^s), dpsi(ixi^s)
1250 db(ixo^s) = wrp(ixo^s,mag(idir)) - wlp(ixo^s,mag(idir))
1251 dpsi(ixo^s) = wrp(ixo^s,
psi_) - wlp(ixo^s,
psi_)
1253 wlp(ixo^s,mag(idir)) = 0.5d0 * (wrp(ixo^s,mag(idir)) + wlp(ixo^s,mag(idir))) &
1255 wlp(ixo^s,
psi_) = 0.5d0 * (wrp(ixo^s,
psi_) + wlp(ixo^s,
psi_)) &
1258 wrp(ixo^s,mag(idir)) = wlp(ixo^s,mag(idir))
1261 end subroutine mf_modify_wlr
1263 subroutine mf_boundary_adjust(igrid,psb)
1265 integer,
intent(in) :: igrid
1268 integer :: ib, idims, iside, ixo^
l, i^
d
1277 i^
d=
kr(^
d,idims)*(2*iside-3);
1278 if (neighbor_type(i^
d,igrid)/=1) cycle
1279 ib=(idims-1)*2+iside
1297 call fixdivb_boundary(ixg^
ll,ixo^
l,psb(igrid)%w,psb(igrid)%x,ib)
1302 end subroutine mf_boundary_adjust
1304 subroutine fixdivb_boundary(ixG^L,ixO^L,w,x,iB)
1307 integer,
intent(in) :: ixg^
l,ixo^
l,ib
1308 double precision,
intent(inout) :: w(ixg^s,1:nw)
1309 double precision,
intent(in) :: x(ixg^s,1:
ndim)
1311 double precision :: dx1x2,dx1x3,dx2x1,dx2x3,dx3x1,dx3x2
1312 integer :: ix^
d,ixf^
l
1324 do ix1=ixfmax1,ixfmin1,-1
1325 w(ix1-1,ixfmin2:ixfmax2,mag(1))=w(ix1+1,ixfmin2:ixfmax2,mag(1)) &
1326 +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
1327 w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
1330 do ix1=ixfmax1,ixfmin1,-1
1331 w(ix1-1,ixfmin2:ixfmax2,mag(1))=( (w(ix1+1,ixfmin2:ixfmax2,mag(1))+&
1332 w(ix1,ixfmin2:ixfmax2,mag(1)))*
block%surfaceC(ix1,ixfmin2:ixfmax2,1)&
1333 +(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
1334 block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
1335 -(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
1336 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
1337 /
block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
1351 do ix1=ixfmax1,ixfmin1,-1
1352 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1353 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
1354 +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
1355 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
1356 +dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
1357 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
1360 do ix1=ixfmax1,ixfmin1,-1
1361 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1362 ( (w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
1363 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
1364 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
1365 +(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
1366 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
1367 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
1368 -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
1369 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
1370 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
1371 +(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
1372 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
1373 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
1374 -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
1375 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1376 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
1377 /
block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
1378 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
1390 do ix1=ixfmin1,ixfmax1
1391 w(ix1+1,ixfmin2:ixfmax2,mag(1))=w(ix1-1,ixfmin2:ixfmax2,mag(1)) &
1392 -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
1393 w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
1396 do ix1=ixfmin1,ixfmax1
1397 w(ix1+1,ixfmin2:ixfmax2,mag(1))=( (w(ix1-1,ixfmin2:ixfmax2,mag(1))+&
1398 w(ix1,ixfmin2:ixfmax2,mag(1)))*
block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)&
1399 -(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
1400 block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
1401 +(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
1402 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
1403 /
block%surfaceC(ix1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
1417 do ix1=ixfmin1,ixfmax1
1418 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1419 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
1420 -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
1421 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
1422 -dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
1423 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
1426 do ix1=ixfmin1,ixfmax1
1427 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1428 ( (w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
1429 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
1430 block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
1431 -(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
1432 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
1433 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
1434 +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
1435 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
1436 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
1437 -(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
1438 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
1439 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
1440 +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
1441 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1442 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
1443 /
block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
1444 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
1456 do ix2=ixfmax2,ixfmin2,-1
1457 w(ixfmin1:ixfmax1,ix2-1,mag(2))=w(ixfmin1:ixfmax1,ix2+1,mag(2)) &
1458 +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
1459 w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
1462 do ix2=ixfmax2,ixfmin2,-1
1463 w(ixfmin1:ixfmax1,ix2-1,mag(2))=( (w(ixfmin1:ixfmax1,ix2+1,mag(2))+&
1464 w(ixfmin1:ixfmax1,ix2,mag(2)))*
block%surfaceC(ixfmin1:ixfmax1,ix2,2)&
1465 +(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
1466 block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
1467 -(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
1468 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
1469 /
block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
1483 do ix2=ixfmax2,ixfmin2,-1
1484 w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
1485 ix2+1,ixfmin3:ixfmax3,mag(2)) &
1486 +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
1487 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
1488 +dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
1489 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
1492 do ix2=ixfmax2,ixfmin2,-1
1493 w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=&
1494 ( (w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))+&
1495 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
1496 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)&
1497 +(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
1498 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1499 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
1500 -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
1501 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1502 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
1503 +(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
1504 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
1505 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
1506 -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
1507 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1508 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
1509 /
block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)-&
1510 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
1522 do ix2=ixfmin2,ixfmax2
1523 w(ixfmin1:ixfmax1,ix2+1,mag(2))=w(ixfmin1:ixfmax1,ix2-1,mag(2)) &
1524 -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
1525 w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
1528 do ix2=ixfmin2,ixfmax2
1529 w(ixfmin1:ixfmax1,ix2+1,mag(2))=( (w(ixfmin1:ixfmax1,ix2-1,mag(2))+&
1530 w(ixfmin1:ixfmax1,ix2,mag(2)))*
block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)&
1531 -(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
1532 block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
1533 +(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
1534 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
1535 /
block%surfaceC(ixfmin1:ixfmax1,ix2,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
1549 do ix2=ixfmin2,ixfmax2
1550 w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
1551 ix2-1,ixfmin3:ixfmax3,mag(2)) &
1552 -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
1553 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
1554 -dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
1555 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
1558 do ix2=ixfmin2,ixfmax2
1559 w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=&
1560 ( (w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))+&
1561 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
1562 block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)&
1563 -(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
1564 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1565 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
1566 +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
1567 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1568 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
1569 -(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
1570 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
1571 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
1572 +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
1573 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1574 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
1575 /
block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)-&
1576 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
1591 do ix3=ixfmax3,ixfmin3,-1
1592 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=w(ixfmin1:ixfmax1,&
1593 ixfmin2:ixfmax2,ix3+1,mag(3)) &
1594 +dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
1595 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
1596 +dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
1597 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
1600 do ix3=ixfmax3,ixfmin3,-1
1601 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=&
1602 ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))+&
1603 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
1604 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)&
1605 +(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
1606 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1607 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
1608 -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
1609 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1610 block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
1611 +(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
1612 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
1613 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
1614 -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
1615 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
1616 block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
1617 /
block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)-&
1618 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
1631 do ix3=ixfmin3,ixfmax3
1632 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=w(ixfmin1:ixfmax1,&
1633 ixfmin2:ixfmax2,ix3-1,mag(3)) &
1634 -dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
1635 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
1636 -dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
1637 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
1640 do ix3=ixfmin3,ixfmax3
1641 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=&
1642 ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))+&
1643 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
1644 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)&
1645 -(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
1646 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1647 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
1648 +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
1649 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1650 block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
1651 -(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
1652 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
1653 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
1654 +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
1655 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
1656 block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
1657 /
block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)-&
1658 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
1663 call mpistop(
"Special boundary is not defined for this region")
1666 end subroutine fixdivb_boundary
1675 double precision,
intent(in) :: qdt
1676 double precision,
intent(in) :: qt
1677 logical,
intent(inout) :: active
1679 double precision :: tmp(ixg^t), grad(ixg^t,
ndim)
1680 double precision :: res
1681 double precision,
parameter :: max_residual = 1
d-3
1682 double precision,
parameter :: residual_reduction = 1
d-10
1684 integer,
parameter :: max_its = 50
1685 double precision :: residual_it(max_its), max_divb
1686 integer :: iigrid, igrid
1687 integer :: n, nc, lvl, ix^
l, ixc^
l, idim
1690 mg%operator_type = mg_laplacian
1698 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1699 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1702 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
1703 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1705 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1706 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1709 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
1710 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1714 write(*,*)
"mf_clean_divb_multigrid warning: unknown boundary type"
1715 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1716 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1724 do iigrid = 1, igridstail
1725 igrid = igrids(iigrid);
1728 lvl =
mg%boxes(id)%lvl
1729 nc =
mg%box_size_lvl(lvl)
1735 call get_divb(ps(igrid)%w(ixg^t, 1:nw), ixg^
ll,
ixm^
ll, tmp, &
1737 mg%boxes(id)%cc({1:nc}, mg_irhs) = tmp(
ixm^t)
1738 max_divb = max(max_divb, maxval(abs(tmp(
ixm^t))))
1743 call mpi_allreduce(mpi_in_place, max_divb, 1, mpi_double_precision, &
1746 if (
mype == 0) print *,
"Performing multigrid divB cleaning"
1747 if (
mype == 0) print *,
"iteration vs residual"
1750 call mg_fas_fmg(
mg, n>1, max_res=residual_it(n))
1751 if (
mype == 0)
write(*,
"(I4,E11.3)") n, residual_it(n)
1752 if (residual_it(n) < residual_reduction * max_divb)
exit
1754 if (
mype == 0 .and. n > max_its)
then
1755 print *,
"divb_multigrid warning: not fully converged"
1756 print *,
"current amplitude of divb: ", residual_it(max_its)
1757 print *,
"multigrid smallest grid: ", &
1758 mg%domain_size_lvl(:,
mg%lowest_lvl)
1759 print *,
"note: smallest grid ideally has <= 8 cells"
1760 print *,
"multigrid dx/dy/dz ratio: ",
mg%dr(:, 1)/
mg%dr(1, 1)
1761 print *,
"note: dx/dy/dz should be similar"
1765 call mg_fas_vcycle(
mg, max_res=res)
1766 if (res < max_residual)
exit
1768 if (res > max_residual)
call mpistop(
"divb_multigrid: no convergence")
1773 do iigrid = 1, igridstail
1774 igrid = igrids(iigrid);
1783 tmp(ix^s) =
mg%boxes(id)%cc({:,}, mg_iphi)
1787 ixcmin^
d=ixmlo^
d-
kr(idim,^
d);
1789 call gradientf(tmp,ps(igrid)%x,ixg^
ll,ixc^
l,idim,grad(ixg^t,idim))
1790 ps(igrid)%ws(ixc^s,idim)=ps(igrid)%ws(ixc^s,idim)-grad(ixc^s,idim)
1798 ps(igrid)%w(
ixm^t, mag(1:
ndim)) = &
1799 ps(igrid)%w(
ixm^t, mag(1:
ndim)) - grad(
ixm^t, :)
1809 subroutine mf_update_faces(ixI^L,ixO^L,qt,qdt,wprim,fC,fE,sCT,s,vcts)
1812 integer,
intent(in) :: ixi^
l, ixo^
l
1813 double precision,
intent(in) :: qt, qdt
1815 double precision,
intent(in) :: wprim(ixi^s,1:nw)
1816 type(state) :: sct, s
1817 type(ct_velocity) :: vcts
1818 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
1819 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
1823 call update_faces_average(ixi^
l,ixo^
l,qt,qdt,fc,fe,sct,s)
1825 call update_faces_contact(ixi^
l,ixo^
l,qt,qdt,wprim,fc,fe,sct,s,vcts)
1827 call update_faces_hll(ixi^
l,ixo^
l,qt,qdt,fe,sct,s,vcts)
1829 call mpistop(
'choose average, uct_contact,or uct_hll for type_ct!')
1832 end subroutine mf_update_faces
1835 subroutine update_faces_average(ixI^L,ixO^L,qt,qdt,fC,fE,sCT,s)
1839 integer,
intent(in) :: ixi^
l, ixo^
l
1840 double precision,
intent(in) :: qt, qdt
1841 type(state) :: sct, s
1842 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
1843 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
1845 double precision :: circ(ixi^s,1:
ndim)
1846 double precision :: e_resi(ixi^s,
sdim:3)
1847 integer :: ix^
d,ixc^
l,ixa^
l,i1kr^
d,i2kr^
d
1848 integer :: idim1,idim2,idir,iwdim1,iwdim2
1850 associate(bfaces=>s%ws,x=>s%x)
1857 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,e_resi)
1861 i1kr^
d=
kr(idim1,^
d);
1864 i2kr^
d=
kr(idim2,^
d);
1867 if (
lvc(idim1,idim2,idir)==1)
then
1869 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
1871 {
do ix^db=ixcmin^db,ixcmax^db\}
1872 fe(ix^
d,idir)=quarter*&
1873 (fc(ix^
d,iwdim1,idim2)+fc({ix^
d+i1kr^
d},iwdim1,idim2)&
1874 -fc(ix^
d,iwdim2,idim1)-fc({ix^
d+i2kr^
d},iwdim2,idim1))
1876 if(
mf_eta/=zero) fe(ix^
d,idir)=fe(ix^
d,idir)+e_resi(ix^
d,idir)
1879 fe(ix^
d,idir)=fe(ix^
d,idir)*qdt*s%dsC(ix^
d,idir)
1887 if(
associated(usr_set_electric_field)) &
1888 call usr_set_electric_field(ixi^l,ixo^l,qt,qdt,fe,sct)
1890 circ(ixi^s,1:ndim)=zero
1896 ixcmin^d=ixomin^d-kr(idim1,^d);
1898 ixa^l=ixc^l-kr(idim2,^d);
1901 if(lvc(idim1,idim2,idir)==1)
then
1903 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
1906 else if(lvc(idim1,idim2,idir)==-1)
then
1908 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
1915 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
1917 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
1922 end subroutine update_faces_average
1925 subroutine update_faces_contact(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
1929 integer,
intent(in) :: ixi^
l, ixo^
l
1930 double precision,
intent(in) :: qt, qdt
1932 double precision,
intent(in) :: wp(ixi^s,1:nw)
1933 type(state) :: sct, s
1934 type(ct_velocity) :: vcts
1935 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
1936 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
1938 double precision :: circ(ixi^s,1:
ndim)
1940 double precision :: ecc(ixi^s,
sdim:3)
1942 double precision :: el(ixi^s),er(ixi^s)
1944 double precision :: elc(ixi^s),erc(ixi^s)
1946 double precision :: jce(ixi^s,
sdim:3)
1947 integer :: hxc^
l,ixc^
l,jxc^
l,ixa^
l,ixb^
l
1948 integer :: idim1,idim2,idir,iwdim1,iwdim2
1950 associate(bfaces=>s%ws,x=>s%x,w=>s%w,vnorm=>vcts%vnorm)
1955 if(
lvc(idim1,idim2,idir)==1)
then
1956 ecc(ixi^s,idir)=ecc(ixi^s,idir)+wp(ixi^s,mag(idim1))*wp(ixi^s,
mom(idim2))
1957 else if(
lvc(idim1,idim2,idir)==-1)
then
1958 ecc(ixi^s,idir)=ecc(ixi^s,idir)-wp(ixi^s,mag(idim1))*wp(ixi^s,
mom(idim2))
1963 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,jce)
1975 if (
lvc(idim1,idim2,idir)==1)
then
1977 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
1979 jxc^
l=ixc^
l+
kr(idim1,^
d);
1980 hxc^
l=ixc^
l+
kr(idim2,^
d);
1982 fe(ixc^s,idir)=quarter*&
1983 (fc(ixc^s,iwdim1,idim2)+fc(jxc^s,iwdim1,idim2)&
1984 -fc(ixc^s,iwdim2,idim1)-fc(hxc^s,iwdim2,idim1))
1988 ixamax^
d=ixcmax^
d+
kr(idim1,^
d);
1989 el(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(ixa^s,idir)
1990 hxc^
l=ixa^
l+
kr(idim2,^
d);
1991 er(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(hxc^s,idir)
1992 where(vnorm(ixc^s,idim1)>0.d0)
1993 elc(ixc^s)=el(ixc^s)
1994 else where(vnorm(ixc^s,idim1)<0.d0)
1995 elc(ixc^s)=el(jxc^s)
1997 elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
1999 hxc^
l=ixc^
l+
kr(idim2,^
d);
2000 where(vnorm(hxc^s,idim1)>0.d0)
2001 erc(ixc^s)=er(ixc^s)
2002 else where(vnorm(hxc^s,idim1)<0.d0)
2003 erc(ixc^s)=er(jxc^s)
2005 erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
2007 fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
2010 jxc^
l=ixc^
l+
kr(idim2,^
d);
2012 ixamax^
d=ixcmax^
d+
kr(idim2,^
d);
2013 el(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(ixa^s,idir)
2014 hxc^
l=ixa^
l+
kr(idim1,^
d);
2015 er(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(hxc^s,idir)
2016 where(vnorm(ixc^s,idim2)>0.d0)
2017 elc(ixc^s)=el(ixc^s)
2018 else where(vnorm(ixc^s,idim2)<0.d0)
2019 elc(ixc^s)=el(jxc^s)
2021 elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
2023 hxc^
l=ixc^
l+
kr(idim1,^
d);
2024 where(vnorm(hxc^s,idim2)>0.d0)
2025 erc(ixc^s)=er(ixc^s)
2026 else where(vnorm(hxc^s,idim2)<0.d0)
2027 erc(ixc^s)=er(jxc^s)
2029 erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
2031 fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
2034 if(
mf_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+jce(ixc^s,idir)
2038 fe(ixc^s,idir)=fe(ixc^s,idir)*qdt*s%dsC(ixc^s,idir)
2053 circ(ixi^s,1:
ndim)=zero
2058 ixcmin^
d=ixomin^
d-
kr(idim1,^
d);
2062 if(
lvc(idim1,idim2,idir)/=0)
then
2063 hxc^
l=ixc^
l-
kr(idim2,^
d);
2065 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2066 +
lvc(idim1,idim2,idir)&
2073 where(s%surfaceC(ixc^s,idim1) > 1.0
d-9*s%dvolume(ixc^s))
2074 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2076 circ(ixc^s,idim1)=zero
2079 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2084 end subroutine update_faces_contact
2087 subroutine update_faces_hll(ixI^L,ixO^L,qt,qdt,fE,sCT,s,vcts)
2092 integer,
intent(in) :: ixi^
l, ixo^
l
2093 double precision,
intent(in) :: qt, qdt
2094 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
2095 type(state) :: sct, s
2096 type(ct_velocity) :: vcts
2098 double precision :: vtill(ixi^s,2)
2099 double precision :: vtilr(ixi^s,2)
2100 double precision :: btill(ixi^s,
ndim)
2101 double precision :: btilr(ixi^s,
ndim)
2102 double precision :: cp(ixi^s,2)
2103 double precision :: cm(ixi^s,2)
2104 double precision :: circ(ixi^s,1:
ndim)
2106 double precision :: jce(ixi^s,
sdim:3)
2107 integer :: hxc^
l,ixc^
l,ixcp^
l,jxc^
l,ixcm^
l
2108 integer :: idim1,idim2,idir
2110 associate(bfaces=>s%ws,bfacesct=>sct%ws,x=>s%x,vbarc=>vcts%vbarC,cbarmin=>vcts%cbarmin,&
2111 cbarmax=>vcts%cbarmax)
2124 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,jce)
2137 ixcmin^
d=ixomin^
d-1+
kr(idir,^
d);
2141 idim2=mod(idir+1,3)+1
2143 jxc^
l=ixc^
l+
kr(idim1,^
d);
2144 ixcp^
l=ixc^
l+
kr(idim2,^
d);
2148 vtill(ixi^s,2),vtilr(ixi^s,2))
2151 vtill(ixi^s,1),vtilr(ixi^s,1))
2157 btill(ixi^s,idim1),btilr(ixi^s,idim1))
2160 btill(ixi^s,idim2),btilr(ixi^s,idim2))
2164 cm(ixc^s,1)=max(cbarmin(ixcp^s,idim1),cbarmin(ixc^s,idim1))
2165 cp(ixc^s,1)=max(cbarmax(ixcp^s,idim1),cbarmax(ixc^s,idim1))
2167 cm(ixc^s,2)=max(cbarmin(jxc^s,idim2),cbarmin(ixc^s,idim2))
2168 cp(ixc^s,2)=max(cbarmax(jxc^s,idim2),cbarmax(ixc^s,idim2))
2172 fe(ixc^s,idir)=-(cp(ixc^s,1)*vtill(ixc^s,1)*btill(ixc^s,idim2) &
2173 + cm(ixc^s,1)*vtilr(ixc^s,1)*btilr(ixc^s,idim2) &
2174 - cp(ixc^s,1)*cm(ixc^s,1)*(btilr(ixc^s,idim2)-btill(ixc^s,idim2)))&
2175 /(cp(ixc^s,1)+cm(ixc^s,1)) &
2176 +(cp(ixc^s,2)*vtill(ixc^s,2)*btill(ixc^s,idim1) &
2177 + cm(ixc^s,2)*vtilr(ixc^s,2)*btilr(ixc^s,idim1) &
2178 - cp(ixc^s,2)*cm(ixc^s,2)*(btilr(ixc^s,idim1)-btill(ixc^s,idim1)))&
2179 /(cp(ixc^s,2)+cm(ixc^s,2))
2182 if(
mf_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+jce(ixc^s,idir)
2186 fe(ixc^s,idir)=qdt*s%dsC(ixc^s,idir)*fe(ixc^s,idir)
2200 circ(ixi^s,1:
ndim)=zero
2206 ixcmin^
d=ixomin^
d-
kr(idim1,^
d);
2210 if(
lvc(idim1,idim2,idir)/=0)
then
2211 hxc^
l=ixc^
l-
kr(idim2,^
d);
2213 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2214 +
lvc(idim1,idim2,idir)&
2221 where(s%surfaceC(ixc^s,idim1) > 1.0
d-9*s%dvolume(ixc^s))
2222 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2224 circ(ixc^s,idim1)=zero
2227 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2231 end subroutine update_faces_hll
2234 subroutine get_resistive_electric_field(ixI^L,ixO^L,sCT,s,jce)
2239 integer,
intent(in) :: ixi^
l, ixo^
l
2240 type(state),
intent(in) :: sct, s
2242 double precision :: jce(ixi^s,
sdim:3)
2245 double precision :: jcc(ixi^s,7-2*
ndir:3)
2247 double precision :: xs(ixgs^t,1:
ndim)
2249 double precision :: eta(ixi^s)
2250 double precision :: gradi(ixgs^t)
2251 integer :: ix^
d,ixc^
l,ixa^
l,ixb^
l,idir,idirmin,idim1,idim2
2253 associate(x=>s%x,
dx=>s%dx,w=>s%w,wct=>sct%w,wcts=>sct%ws)
2259 if (
lvc(idim1,idim2,idir)==0) cycle
2260 ixcmax^
d=ixomax^
d+1;
2261 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-2;
2262 ixbmax^
d=ixcmax^
d-
kr(idir,^
d)+1;
2265 xs(ixb^s,:)=x(ixb^s,:)
2266 xs(ixb^s,idim2)=x(ixb^s,idim2)+half*
dx(ixb^s,idim2)
2267 call gradientf(wcts(ixgs^t,idim2),xs,ixgs^
ll,ixc^
l,idim1,gradi)
2268 if (
lvc(idim1,idim2,idir)==1)
then
2269 jce(ixc^s,idir)=jce(ixc^s,idir)+gradi(ixc^s)
2271 jce(ixc^s,idir)=jce(ixc^s,idir)-gradi(ixc^s)
2278 jce(ixi^s,:)=jce(ixi^s,:)*
mf_eta
2286 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
2287 jcc(ixc^s,idir)=0.d0
2289 if({ ix^
d==1 .and. ^
d==idir | .or.}) cycle
2290 ixamin^
d=ixcmin^
d+ix^
d;
2291 ixamax^
d=ixcmax^
d+ix^
d;
2292 jcc(ixc^s,idir)=jcc(ixc^s,idir)+eta(ixa^s)
2294 jcc(ixc^s,idir)=jcc(ixc^s,idir)*0.25d0
2295 jce(ixc^s,idir)=jce(ixc^s,idir)*jcc(ixc^s,idir)
2300 end subroutine get_resistive_electric_field
2306 integer,
intent(in) :: ixo^
l
2313 do ix^db=ixomin^db,ixomax^db\}
2315 s%w(ix^
d,mag(1))=half/s%surface(ix^
d,1)*(s%ws(ix^
d,1)*s%surfaceC(ix^
d,1)&
2316 +s%ws(ix1-1,ix2,ix3,1)*s%surfaceC(ix1-1,ix2,ix3,1))
2317 s%w(ix^
d,mag(2))=half/s%surface(ix^
d,2)*(s%ws(ix^
d,2)*s%surfaceC(ix^
d,2)&
2318 +s%ws(ix1,ix2-1,ix3,2)*s%surfaceC(ix1,ix2-1,ix3,2))
2319 s%w(ix^
d,mag(3))=half/s%surface(ix^
d,3)*(s%ws(ix^
d,3)*s%surfaceC(ix^
d,3)&
2320 +s%ws(ix1,ix2,ix3-1,3)*s%surfaceC(ix1,ix2,ix3-1,3))
2323 s%w(ix^
d,mag(1))=half/s%surface(ix^
d,1)*(s%ws(ix^
d,1)*s%surfaceC(ix^
d,1)&
2324 +s%ws(ix1-1,ix2,1)*s%surfaceC(ix1-1,ix2,1))
2325 s%w(ix^
d,mag(2))=half/s%surface(ix^
d,2)*(s%ws(ix^
d,2)*s%surfaceC(ix^
d,2)&
2326 +s%ws(ix1,ix2-1,2)*s%surfaceC(ix1,ix2-1,2))
2369 integer,
intent(in) :: ixis^
l, ixi^
l, ixo^
l
2370 double precision,
intent(inout) :: ws(ixis^s,1:nws)
2371 double precision,
intent(in) :: x(ixi^s,1:
ndim)
2373 double precision :: adummy(ixis^s,1:3)
2382 double precision :: sum_jbb_ipe, sum_j_ipe, sum_l_ipe, f_i_ipe, volume_pe
2383 double precision :: sum_jbb, sum_j, sum_l, f_i, volume, cw_sin_theta
2384 integer :: iigrid, igrid, ix^
d
2385 integer :: amode, istatus(mpi_status_size)
2386 integer,
save :: fhmf
2387 logical :: patchwi(ixg^t)
2388 logical,
save :: logmfopened=.false.
2389 character(len=800) :: filename,filehead
2390 character(len=800) :: line,datastr
2397 do iigrid=1,igridstail; igrid=igrids(iigrid);
2400 call mask_inner(ixg^
ll,
ixm^
ll,ps(igrid)%w,ps(igrid)%x,patchwi,volume_pe)
2401 sum_jbb_ipe = sum_jbb_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2402 ps(igrid)%x,1,patchwi)
2403 sum_j_ipe = sum_j_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2404 ps(igrid)%x,2,patchwi)
2405 f_i_ipe=f_i_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2406 ps(igrid)%x,3,patchwi)
2407 sum_l_ipe = sum_l_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2408 ps(igrid)%x,4,patchwi)
2410 call mpi_reduce(sum_jbb_ipe,sum_jbb,1,mpi_double_precision,&
2412 call mpi_reduce(sum_j_ipe,sum_j,1,mpi_double_precision,mpi_sum,0,&
2414 call mpi_reduce(f_i_ipe,f_i,1,mpi_double_precision,mpi_sum,0,&
2416 call mpi_reduce(sum_l_ipe,sum_l,1,mpi_double_precision,mpi_sum,0,&
2418 call mpi_reduce(volume_pe,volume,1,mpi_double_precision,mpi_sum,0,&
2424 cw_sin_theta = sum_jbb/sum_j
2430 if(.not.logmfopened)
then
2432 write(filename,
"(a,a)") trim(
base_filename),
"_mf_metrics.csv"
2436 open(unit=20,file=trim(filename),status=
'replace')
2437 close(20, status=
'delete')
2440 amode=ior(mpi_mode_create,mpi_mode_wronly)
2441 amode=ior(amode,mpi_mode_append)
2442 call mpi_file_open(mpi_comm_self,filename,amode,mpi_info_null,fhmf,
ierrmpi)
2444 filehead=
" it,time,CW_sin_theta,current,Lorenz_force,f_i"
2446 call mpi_file_write(fhmf,filehead,len_trim(filehead), &
2447 mpi_character,istatus,
ierrmpi)
2448 call mpi_file_write(fhmf,achar(10),1,mpi_character,istatus,
ierrmpi)
2452 write(datastr,
'(i6,a)')
it,
','
2453 line=trim(line)//trim(datastr)
2455 line=trim(line)//trim(datastr)
2456 write(datastr,
'(es13.6,a)') cw_sin_theta,
','
2457 line=trim(line)//trim(datastr)
2458 write(datastr,
'(es13.6,a)') sum_j,
','
2459 line=trim(line)//trim(datastr)
2460 write(datastr,
'(es13.6,a)') sum_l,
','
2461 line=trim(line)//trim(datastr)
2462 write(datastr,
'(es13.6)') f_i
2463 line=trim(line)//trim(datastr)//new_line(
'A')
2464 call mpi_file_write(fhmf,line,len_trim(line),mpi_character,istatus,
ierrmpi)
2466 call mpi_file_close(fhmf,
ierrmpi)
2473 subroutine mask_inner(ixI^L,ixO^L,w,x,patchwi,volume_pe)
2476 integer,
intent(in) :: ixi^
l,ixo^
l
2477 double precision,
intent(in):: w(ixi^s,nw),x(ixi^s,1:
ndim)
2478 double precision,
intent(inout) :: volume_pe
2479 logical,
intent(out) :: patchwi(ixi^s)
2481 double precision :: xo^
l
2484 {xomin^
d = xprobmin^
d + 0.05d0*(xprobmax^
d-xprobmin^
d)\}
2485 {xomax^
d = xprobmax^
d - 0.05d0*(xprobmax^
d-xprobmin^
d)\}
2487 xomin^nd = xprobmin^nd
2492 {
do ix^db=ixomin^db,ixomax^db\}
2493 if({ x(ix^dd,^
d) > xomin^
d .and. x(ix^dd,^
d) < xomax^
d | .and. })
then
2494 patchwi(ix^
d)=.true.
2495 volume_pe=volume_pe+
block%dvolume(ix^
d)
2497 patchwi(ix^
d)=.false.
2501 end subroutine mask_inner
2503 function integral_grid_mf(ixI^L,ixO^L,w,x,iw,patchwi)
2506 integer,
intent(in) :: ixi^
l,ixo^
l,iw
2507 double precision,
intent(in) :: x(ixi^s,1:
ndim)
2508 double precision :: w(ixi^s,nw+
nwauxio)
2509 logical,
intent(in) :: patchwi(ixi^s)
2511 double precision,
dimension(ixI^S,7-2*ndir:3) :: current
2512 double precision,
dimension(ixI^S,1:ndir) :: bvec,qvec
2513 double precision :: integral_grid_mf,tmp(ixi^s),bm2
2514 integer :: ix^
d,idirmin0,idirmin,idir,jdir,kdir
2516 integral_grid_mf=0.d0
2520 bvec(ixo^s,:)=w(ixo^s,mag(:))
2523 qvec(ixo^s,1:
ndir)=zero
2524 do idir=1,
ndir;
do jdir=idirmin,3;
do kdir=1,
ndir
2525 if(
lvc(idir,jdir,kdir)/=0)
then
2526 if(
lvc(idir,jdir,kdir)==1)
then
2527 qvec(ixo^s,idir)=qvec(ixo^s,idir)+current(ixo^s,jdir)*bvec(ixo^s,kdir)
2529 qvec(ixo^s,idir)=qvec(ixo^s,idir)-current(ixo^s,jdir)*bvec(ixo^s,kdir)
2532 end do;
end do;
end do
2534 {
do ix^db=ixomin^db,ixomax^db\}
2535 if(patchwi(ix^d))
then
2536 bm2=sum(bvec(ix^d,:)**2)
2537 if(bm2/=0.d0) bm2=1.d0/bm2
2538 integral_grid_mf=integral_grid_mf+sqrt(sum(qvec(ix^d,:)**2)*&
2539 bm2)*block%dvolume(ix^d)
2545 {
do ix^db=ixomin^db,ixomax^db\}
2546 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+sqrt(sum(current(ix^d,:)**2))*&
2553 {
do ix^db=ixomin^db,ixomax^db\}
2554 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+tmp(ix^d)*block%dvolume(ix^d)
2558 bvec(ixo^s,:)=w(ixo^s,mag(:))
2561 qvec(ixo^s,1:ndir)=zero
2562 do idir=1,ndir;
do jdir=idirmin,3;
do kdir=1,ndir
2563 if(lvc(idir,jdir,kdir)/=0)
then
2564 if(lvc(idir,jdir,kdir)==1)
then
2565 qvec(ixo^s,idir)=qvec(ixo^s,idir)+current(ixo^s,jdir)*bvec(ixo^s,kdir)
2567 qvec(ixo^s,idir)=qvec(ixo^s,idir)-current(ixo^s,jdir)*bvec(ixo^s,kdir)
2570 end do;
end do;
end do
2572 {
do ix^db=ixomin^db,ixomax^db\}
2573 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+&
2574 sqrt(sum(qvec(ix^d,:)**2))*block%dvolume(ix^d)
2578 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
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)
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...
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.
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, 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.