13 double precision,
public ::
mf_nu = 1.
d-15
16 double precision,
public ::
mf_vmax = 3.d6
26 double precision,
public ::
mf_eta = 0.0d0
32 double precision :: divbdiff = 0.8d0
41 integer,
allocatable,
public,
protected ::
mom(:)
44 integer,
public,
protected :: ^
c&m^C_
47 integer,
public,
protected :: ^
c&b^C_
50 integer,
public,
protected ::
psi_
56 integer,
parameter :: divb_none = 0
57 integer,
parameter :: divb_multigrid = -1
58 integer,
parameter :: divb_glm = 1
59 integer,
parameter :: divb_powel = 2
60 integer,
parameter :: divb_janhunen = 3
61 integer,
parameter :: divb_linde = 4
62 integer,
parameter :: divb_lindejanhunen = 5
63 integer,
parameter :: divb_lindepowel = 6
64 integer,
parameter :: divb_lindeglm = 7
65 integer,
parameter :: divb_ct = 8
71 logical,
public,
protected ::
mf_glm = .false.
86 logical :: compactres = .false.
95 character(len=std_len),
public,
protected ::
typedivbfix =
'ct'
98 character(len=std_len),
public,
protected ::
type_ct =
'average'
101 character(len=std_len) :: typedivbdiff =
'all'
121 subroutine mf_read_params(files)
124 character(len=*),
intent(in) :: files(:)
135 do n = 1,
size(files)
136 open(
unitpar, file=trim(files(n)), status=
"old")
137 read(
unitpar, mf_list,
end=111)
141 end subroutine mf_read_params
144 subroutine mf_write_info(fh)
146 integer,
intent(in) :: fh
147 integer,
parameter :: n_par = 1
148 double precision :: values(n_par)
149 character(len=name_len) :: names(n_par)
150 integer,
dimension(MPI_STATUS_SIZE) :: st
153 call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
157 call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
158 call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
159 end subroutine mf_write_info
172 phys_energy = .false.
178 type_divb = divb_none
181 type_divb = divb_multigrid
183 mg%operator_type = mg_laplacian
190 case (
'powel',
'powell')
191 type_divb = divb_powel
193 type_divb = divb_janhunen
195 type_divb = divb_linde
196 case (
'lindejanhunen')
197 type_divb = divb_lindejanhunen
199 type_divb = divb_lindepowel
203 type_divb = divb_lindeglm
208 call mpistop(
'Unknown divB fix')
213 mom(:) = var_set_momentum(
ndir)
218 mag(:) = var_set_bfield(
ndir)
223 allocate(start_indices(number_species),stop_indices(number_species))
225 start_indices(1)=mag(1)
228 psi_ = var_set_fluxvar(
'psi',
'psi', need_bc=.false.)
237 stop_indices(1)=nwflux
243 allocate(iw_vector(nvector))
244 iw_vector(1) =
mom(1) - 1
245 iw_vector(2) = mag(1) - 1
248 if (.not.
allocated(flux_type))
then
249 allocate(flux_type(
ndir, nw))
250 flux_type = flux_default
251 else if (any(shape(flux_type) /= [
ndir, nw]))
then
252 call mpistop(
"phys_check error: flux_type has wrong shape")
257 flux_type(:,
psi_)=flux_special
259 flux_type(idir,mag(idir))=flux_special
263 flux_type(idir,mag(idir))=flux_tvdlf
268 phys_get_dt => mf_get_dt
269 phys_get_cmax => mf_get_cmax
270 phys_get_cbounds => mf_get_cbounds
271 phys_get_flux => mf_get_flux
272 phys_add_source_geom => mf_add_source_geom
273 phys_add_source => mf_add_source
276 phys_check_params => mf_check_params
277 phys_write_info => mf_write_info
278 phys_special_advance => mf_velocity_update
280 if(type_divb==divb_glm)
then
281 phys_modify_wlr => mf_modify_wlr
293 transverse_ghost_cells = 1
294 phys_get_ct_velocity => mf_get_ct_velocity_average
295 phys_update_faces => mf_update_faces_average
297 transverse_ghost_cells = 1
298 phys_get_ct_velocity => mf_get_ct_velocity_contact
299 phys_update_faces => mf_update_faces_contact
301 transverse_ghost_cells = 2
302 phys_get_ct_velocity => mf_get_ct_velocity_hll
303 phys_update_faces => mf_update_faces_hll
305 call mpistop(
'choose average, uct_contact,or uct_hll for type_ct!')
308 phys_boundary_adjust => mf_boundary_adjust
317 call mf_physical_units()
321 subroutine mf_check_params
326 ngridvars,num_particles,physics_type_particles
336 write(*,*)
'====MF run with settings===================='
337 write(*,*)
'Using mod_mf_phys with settings:'
339 write(*,*)
'Dimensionality :',
ndim
340 write(*,*)
'vector components:',
ndir
342 write(*,*)
'number of variables nw=',nw
343 write(*,*)
' start index iwstart=',iwstart
344 write(*,*)
'number of vector variables=',nvector
345 write(*,*)
'number of stagger variables nws=',nws
346 write(*,*)
'number of variables with BCs=',nwgc
347 write(*,*)
'number of vars with fluxes=',nwflux
348 write(*,*)
'number of vars with flux + BC=',nwfluxbc
349 write(*,*)
'number of auxiliary variables=',nwaux
350 write(*,*)
'number of extra vars without flux=',nwextra
351 write(*,*)
'number of extra vars for wextra=',nw_extra
352 write(*,*)
'number of auxiliary I/O variables=',
nwauxio
353 write(*,*)
' mf_eta=',
mf_eta,
' nonzero implies resistivity'
358 write(*,*)
'*****Using particles: particles_eta, particles_etah :', particles_eta, particles_etah
359 write(*,*)
'*****Using particles: npayload,ngridvars :', npayload,ngridvars
360 write(*,*)
'*****Using particles: nusrpayload :', nusrpayload
361 write(*,*)
'*****Using particles: num_particles :', num_particles
362 write(*,*)
'*****Using particles: physics_type_particles=',physics_type_particles
365 write(*,*)
'number due to phys_wider_stencil=',phys_wider_stencil
366 write(*,*)
'==========================================='
370 end subroutine mf_check_params
372 subroutine mf_physical_units()
374 double precision :: mp,kb,miu0,c_lightspeed
375 double precision :: a,
b
511 end subroutine mf_physical_units
516 integer,
intent(in) :: ixi^
l, ixo^
l
517 double precision,
intent(inout) :: w(ixi^s, nw)
518 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
526 integer,
intent(in) :: ixi^
l, ixo^
l
527 double precision,
intent(inout) :: w(ixi^s, nw)
528 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
534 subroutine mf_get_cmax(w,x,ixI^L,ixO^L,idim,cmax)
537 integer,
intent(in) :: ixi^
l, ixo^
l, idim
538 double precision,
intent(in) :: w(ixi^s, nw), x(ixi^s,1:
ndim)
539 double precision,
intent(inout) :: cmax(ixi^s)
541 cmax(ixo^s)=abs(w(ixo^s,
mom(idim)))+one
543 end subroutine mf_get_cmax
546 subroutine mf_get_cbounds(wLC,wRC,wLp,wRp,x,ixI^L,ixO^L,idim,Hspeed,cmax,cmin)
550 integer,
intent(in) :: ixi^
l, ixo^
l, idim
551 double precision,
intent(in) :: wlc(ixi^s,
nw), wrc(ixi^s,
nw)
552 double precision,
intent(in) :: wlp(ixi^s,
nw), wrp(ixi^s,
nw)
553 double precision,
intent(in) :: x(ixi^s,1:
ndim)
555 double precision,
intent(inout),
optional :: cmin(ixi^s,1:
number_species)
558 double precision,
dimension(ixI^S) :: tmp1
560 tmp1(ixo^s)=0.5d0*(wlc(ixo^s,
mom(idim))+wrc(ixo^s,
mom(idim)))
561 if(
present(cmin))
then
562 cmax(ixo^s,1)=max(tmp1(ixo^s)+one,zero)
563 cmin(ixo^s,1)=min(tmp1(ixo^s)-one,zero)
565 cmax(ixo^s,1)=abs(tmp1(ixo^s))+one
568 end subroutine mf_get_cbounds
571 subroutine mf_get_ct_velocity_average(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
574 integer,
intent(in) :: ixi^
l, ixo^
l, idim
575 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
576 double precision,
intent(in) :: cmax(ixi^s)
577 double precision,
intent(in),
optional :: cmin(ixi^s)
578 type(ct_velocity),
intent(inout):: vcts
580 end subroutine mf_get_ct_velocity_average
582 subroutine mf_get_ct_velocity_contact(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
585 integer,
intent(in) :: ixi^
l, ixo^
l, idim
586 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
587 double precision,
intent(in) :: cmax(ixi^s)
588 double precision,
intent(in),
optional :: cmin(ixi^s)
589 type(ct_velocity),
intent(inout):: vcts
592 if(.not.
allocated(vcts%vnorm))
allocate(vcts%vnorm(ixi^s,1:
ndim))
594 vcts%vnorm(ixo^s,idim)=0.5d0*(wlp(ixo^s,
mom(idim))+wrp(ixo^s,
mom(idim)))
596 end subroutine mf_get_ct_velocity_contact
598 subroutine mf_get_ct_velocity_hll(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
601 integer,
intent(in) :: ixi^
l, ixo^
l, idim
602 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
603 double precision,
intent(in) :: cmax(ixi^s)
604 double precision,
intent(in),
optional :: cmin(ixi^s)
605 type(ct_velocity),
intent(inout):: vcts
607 integer :: idime,idimn
609 if(.not.
allocated(vcts%vbarC))
then
610 allocate(vcts%vbarC(ixi^s,1:
ndir,2),vcts%vbarLC(ixi^s,1:
ndir,2),vcts%vbarRC(ixi^s,1:
ndir,2))
611 allocate(vcts%cbarmin(ixi^s,1:
ndim),vcts%cbarmax(ixi^s,1:
ndim))
614 if(
present(cmin))
then
615 vcts%cbarmin(ixo^s,idim)=max(-cmin(ixo^s),zero)
616 vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
618 vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
619 vcts%cbarmin(ixo^s,idim)=vcts%cbarmax(ixo^s,idim)
622 idimn=mod(idim,
ndir)+1
623 idime=mod(idim+1,
ndir)+1
625 vcts%vbarLC(ixo^s,idim,1)=wlp(ixo^s,
mom(idimn))
626 vcts%vbarRC(ixo^s,idim,1)=wrp(ixo^s,
mom(idimn))
627 vcts%vbarC(ixo^s,idim,1)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,1) &
628 +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
629 /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
631 vcts%vbarLC(ixo^s,idim,2)=wlp(ixo^s,
mom(idime))
632 vcts%vbarRC(ixo^s,idim,2)=wrp(ixo^s,
mom(idime))
633 vcts%vbarC(ixo^s,idim,2)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,2) &
634 +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,2))&
635 /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
637 end subroutine mf_get_ct_velocity_hll
640 subroutine mf_get_flux(wC,w,x,ixI^L,ixO^L,idim,f)
645 integer,
intent(in) :: ixi^
l, ixo^
l, idim
647 double precision,
intent(in) :: wc(ixi^s,nw)
649 double precision,
intent(in) :: w(ixi^s,nw)
650 double precision,
intent(in) :: x(ixi^s,1:
ndim)
651 double precision,
intent(out) :: f(ixi^s,nwflux)
655 {
do ix^db=ixomin^db,ixomax^db\}
661 {
do ix^db=ixomin^db,ixomax^db\}
662 f(ix^d,mag(idim))=w(ix^d,
psi_)
664 f(ix^d,
psi_)=cmax_global**2*w(ix^d,mag(idim))
668 end subroutine mf_get_flux
671 subroutine mf_velocity_update(qt,psa)
674 double precision,
intent(in) :: qt
677 integer :: iigrid,igrid
678 logical :: stagger_flag
679 logical :: firstmf=.true.
694 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
696 call frictional_velocity(psa(igrid)%w,psa(igrid)%x,ixg^
ll,
ixm^
ll)
720 end subroutine mf_velocity_update
723 subroutine mf_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
726 integer,
intent(in) :: ixi^
l, ixo^
l
727 double precision,
intent(in) :: qdt, dtfactor
728 double precision,
intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw), x(ixi^s,1:
ndim)
729 double precision,
intent(inout) :: w(ixi^s,1:nw)
730 logical,
intent(in) :: qsourcesplit
731 logical,
intent(inout) :: active
733 if (.not. qsourcesplit)
then
736 if (abs(
mf_eta)>smalldouble)
then
738 call add_source_res2(qdt,ixi^
l,ixo^
l,wct,w,x)
743 call add_source_hyperres(qdt,ixi^
l,ixo^
l,wct,w,x)
751 select case (type_divb)
756 call add_source_glm(qdt,ixi^
l,ixo^
l,wct,w,x)
759 call add_source_powel(qdt,ixi^
l,ixo^
l,wct,w,x)
762 call add_source_janhunen(qdt,ixi^
l,ixo^
l,wct,w,x)
765 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
766 case (divb_lindejanhunen)
768 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
769 call add_source_janhunen(qdt,ixi^
l,ixo^
l,wct,w,x)
770 case (divb_lindepowel)
772 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
773 call add_source_powel(qdt,ixi^
l,ixo^
l,wct,w,x)
776 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
777 call add_source_glm(qdt,ixi^
l,ixo^
l,wct,w,x)
780 case (divb_multigrid)
783 call mpistop(
'Unknown divB fix')
788 end subroutine mf_add_source
790 subroutine frictional_velocity(w,x,ixI^L,ixO^L)
793 integer,
intent(in) :: ixi^
l, ixo^
l
794 double precision,
intent(in) :: x(ixi^s,1:
ndim)
795 double precision,
intent(inout) :: w(ixi^s,1:nw)
797 double precision :: xmin(
ndim),xmax(
ndim)
798 double precision :: decay(ixo^s)
799 double precision :: current(ixi^s,7-2*
ndir:3),tmp(ixo^s)
800 integer :: ix^
d, idirmin,idir,jdir,kdir
806 if(
block%is_physical_boundary(2*^
d-1))
then
809 if(2*^
d-1==5.and.
ndim==3)
then
811 current(ixomin^
d^
d%ixO^s,:)=current(ixomin^
d+1^
d%ixO^s,:)
816 current(ixomin^
d^
d%ixO^s,:)=current(ixomin^
d+1^
d%ixO^s,:)
820 if(
block%is_physical_boundary(2*^
d))
then
821 current(ixomax^
d^
d%ixO^s,:)=current(ixomax^
d-1^
d%ixO^s,:)
826 do idir=1,
ndir;
do jdir=idirmin,3;
do kdir=1,
ndir
827 if(
lvc(idir,jdir,kdir)/=0)
then
828 if(
lvc(idir,jdir,kdir)==1)
then
829 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))+current(ixo^s,jdir)*w(ixo^s,mag(kdir))
831 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))-current(ixo^s,jdir)*w(ixo^s,mag(kdir))
834 end do;
end do;
end do
836 tmp(ixo^s)=sum(w(ixo^s,mag(:))**2,dim=ndim+1)
838 where(tmp(ixo^s)/=0.d0)
839 tmp(ixo^s)=1.d0/(tmp(ixo^s)*
mf_nu)
843 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))*tmp(ixo^s)
847 ^d&xmin(^d)=xprobmin^d\
848 ^d&xmax(^d)=xprobmax^d\
858 tmp(ixo^s)=sqrt(sum(w(ixo^s,
mom(:))**2,dim=ndim+1))/
mf_vmax+1.d-12
859 tmp(ixo^s)=dtanh(tmp(ixo^s))/tmp(ixo^s)
861 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))*tmp(ixo^s)*decay(ixo^s)
864 end subroutine frictional_velocity
870 subroutine add_source_res1(qdt,ixI^L,ixO^L,wCT,w,x)
875 integer,
intent(in) :: ixi^
l, ixo^
l
876 double precision,
intent(in) :: qdt
877 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
878 double precision,
intent(inout) :: w(ixi^s,1:nw)
881 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s)
882 double precision :: gradeta(ixi^s,1:
ndim), bf(ixi^s,1:
ndir)
883 double precision :: tmp(ixi^s),tmp2(ixi^s)
884 integer :: ixa^
l,idir,jdir,kdir,idirmin,idim,jxo^
l,hxo^
l,ix
885 integer :: lxo^
l, kxo^
l
890 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
891 call mpistop(
"Error in add_source_res1: Non-conforming input limits")
898 gradeta(ixo^s,1:
ndim)=zero
904 gradeta(ixo^s,idim)=tmp(ixo^s)
908 bf(ixi^s,1:
ndir)=wct(ixi^s,mag(1:
ndir))
913 tmp2(ixi^s)=bf(ixi^s,idir)
915 lxo^
l=ixo^
l+2*
kr(idim,^
d);
916 jxo^
l=ixo^
l+
kr(idim,^
d);
917 hxo^
l=ixo^
l-
kr(idim,^
d);
918 kxo^
l=ixo^
l-2*
kr(idim,^
d);
919 tmp(ixo^s)=tmp(ixo^s)+&
920 (-tmp2(lxo^s)+16.0d0*tmp2(jxo^s)-30.0d0*tmp2(ixo^s)+16.0d0*tmp2(hxo^s)-tmp2(kxo^s)) &
925 tmp(ixo^s)=tmp(ixo^s)*eta(ixo^s)
929 do jdir=1,
ndim;
do kdir=idirmin,3
930 if (
lvc(idir,jdir,kdir)/=0)
then
931 if (
lvc(idir,jdir,kdir)==1)
then
932 tmp(ixo^s)=tmp(ixo^s)-gradeta(ixo^s,jdir)*current(ixo^s,kdir)
934 tmp(ixo^s)=tmp(ixo^s)+gradeta(ixo^s,jdir)*current(ixo^s,kdir)
941 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))+qdt*tmp(ixo^s)
945 end subroutine add_source_res1
949 subroutine add_source_res2(qdt,ixI^L,ixO^L,wCT,w,x)
954 integer,
intent(in) :: ixi^
l, ixo^
l
955 double precision,
intent(in) :: qdt
956 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
957 double precision,
intent(inout) :: w(ixi^s,1:nw)
960 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s),curlj(ixi^s,1:3)
961 double precision :: tmpvec(ixi^s,1:3)
962 integer :: ixa^
l,idir,idirmin,idirmin1
969 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
970 call mpistop(
"Error in add_source_res2: Non-conforming input limits")
984 tmpvec(ixa^s,1:
ndir)=zero
986 tmpvec(ixa^s,idir)=current(ixa^s,idir)*eta(ixa^s)
993 w(ixo^s,mag(
ndir)) = w(ixo^s,mag(
ndir))-qdt*curlj(ixo^s,
ndir)
996 w(ixo^s,mag(1:
ndir)) = w(ixo^s,mag(1:
ndir))-qdt*curlj(ixo^s,1:
ndir)
999 end subroutine add_source_res2
1003 subroutine add_source_hyperres(qdt,ixI^L,ixO^L,wCT,w,x)
1007 integer,
intent(in) :: ixi^
l, ixo^
l
1008 double precision,
intent(in) :: qdt
1009 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1010 double precision,
intent(inout) :: w(ixi^s,1:nw)
1012 double precision :: current(ixi^s,7-2*
ndir:3)
1013 double precision :: tmpvec(ixi^s,1:3),tmpvec2(ixi^s,1:3),tmp(ixi^s),ehyper(ixi^s,1:3)
1014 integer :: ixa^
l,idir,jdir,kdir,idirmin,idirmin1
1017 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
1018 call mpistop(
"Error in add_source_hyperres: Non-conforming input limits")
1021 tmpvec(ixa^s,1:
ndir)=zero
1023 tmpvec(ixa^s,jdir)=current(ixa^s,jdir)
1027 call curlvector(tmpvec,ixi^
l,ixa^
l,tmpvec2,idirmin1,1,3)
1030 tmpvec(ixa^s,1:
ndir)=zero
1031 call curlvector(tmpvec2,ixi^
l,ixa^
l,tmpvec,idirmin1,1,3)
1035 tmpvec2(ixa^s,1:
ndir)=zero
1036 call curlvector(ehyper,ixi^
l,ixa^
l,tmpvec2,idirmin1,1,3)
1039 w(ixo^s,mag(idir)) = w(ixo^s,mag(idir))-tmpvec2(ixo^s,idir)*qdt
1042 end subroutine add_source_hyperres
1044 subroutine add_source_glm(qdt,ixI^L,ixO^L,wCT,w,x)
1051 integer,
intent(in) :: ixi^
l, ixo^
l
1052 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1053 double precision,
intent(inout) :: w(ixi^s,1:nw)
1054 double precision:: divb(ixi^s)
1055 double precision :: gradpsi(ixi^s)
1056 integer :: idim,idir
1083 end subroutine add_source_glm
1086 subroutine add_source_powel(qdt,ixI^L,ixO^L,wCT,w,x)
1089 integer,
intent(in) :: ixi^
l, ixo^
l
1090 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1091 double precision,
intent(inout) :: w(ixi^s,1:nw)
1093 double precision :: divb(ixi^s)
1101 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*wct(ixo^s,
mom(idir))*divb(ixo^s)
1104 end subroutine add_source_powel
1106 subroutine add_source_janhunen(qdt,ixI^L,ixO^L,wCT,w,x)
1111 integer,
intent(in) :: ixi^
l, ixo^
l
1112 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1113 double precision,
intent(inout) :: w(ixi^s,1:nw)
1114 double precision :: divb(ixi^s)
1122 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*wct(ixo^s,
mom(idir))*divb(ixo^s)
1125 end subroutine add_source_janhunen
1127 subroutine add_source_linde(qdt,ixI^L,ixO^L,wCT,w,x)
1132 integer,
intent(in) :: ixi^
l, ixo^
l
1133 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1134 double precision,
intent(inout) :: w(ixi^s,1:nw)
1135 double precision :: divb(ixi^s),graddivb(ixi^s)
1136 integer :: idim, idir, ixp^
l, i^
d, iside
1137 logical,
dimension(-1:1^D&) :: leveljump
1145 if(i^
d==0|.and.) cycle
1146 if(neighbor_type(i^
d,
block%igrid)==2 .or. neighbor_type(i^
d,
block%igrid)==4)
then
1147 leveljump(i^
d)=.true.
1149 leveljump(i^
d)=.false.
1158 i^dd=kr(^dd,^d)*(2*iside-3);
1159 if (leveljump(i^dd))
then
1161 ixpmin^d=ixomin^d-i^d
1163 ixpmax^d=ixomax^d-i^d
1174 select case(typegrad)
1176 call gradient(divb,ixi^l,ixp^l,idim,graddivb)
1178 call gradientl(divb,ixi^l,ixp^l,idim,graddivb)
1182 if (slab_uniform)
then
1183 graddivb(ixp^s)=graddivb(ixp^s)*divbdiff/(^d&1.0d0/dxlevel(^d)**2+)
1185 graddivb(ixp^s)=graddivb(ixp^s)*divbdiff &
1186 /(^d&1.0d0/block%ds(ixp^s,^d)**2+)
1189 w(ixp^s,mag(idim))=w(ixp^s,mag(idim))+graddivb(ixp^s)
1192 end subroutine add_source_linde
1200 integer,
intent(in) :: ixi^
l, ixo^
l
1201 double precision,
intent(in) :: w(ixi^s,1:nw)
1202 double precision :: divb(ixi^s), dsurface(ixi^s)
1204 double precision :: invb(ixo^s)
1205 integer :: ixa^
l,idims
1207 call get_divb(w,ixi^
l,ixo^
l,divb)
1208 invb(ixo^s)=sqrt(sum(w(ixo^s, mag(:))**2, dim=
ndim+1))
1209 where(invb(ixo^s)/=0.d0)
1210 invb(ixo^s)=1.d0/invb(ixo^s)
1213 divb(ixo^s)=0.5d0*abs(divb(ixo^s))*invb(ixo^s)/sum(1.d0/
dxlevel(:))
1215 ixamin^
d=ixomin^
d-1;
1216 ixamax^
d=ixomax^
d-1;
1217 dsurface(ixo^s)= sum(
block%surfaceC(ixo^s,:),dim=
ndim+1)
1219 ixa^
l=ixo^
l-
kr(idims,^
d);
1220 dsurface(ixo^s)=dsurface(ixo^s)+
block%surfaceC(ixa^s,idims)
1222 divb(ixo^s)=abs(divb(ixo^s))*invb(ixo^s)*&
1223 block%dvolume(ixo^s)/dsurface(ixo^s)
1234 integer,
intent(in) :: ixo^
l, ixi^
l
1235 double precision,
intent(in) :: w(ixi^s,1:nw)
1236 integer,
intent(out) :: idirmin
1237 logical,
intent(in),
optional :: fourthorder
1240 double precision :: current(ixi^s,7-2*
ndir:3)
1241 integer :: idir, idirmin0
1245 if(
present(fourthorder))
then
1254 subroutine mf_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
1258 integer,
intent(in) :: ixi^
l, ixo^
l
1259 double precision,
intent(inout) :: dtnew
1260 double precision,
intent(in) ::
dx^
d
1261 double precision,
intent(in) :: w(ixi^s,1:nw)
1262 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1264 double precision :: dxarr(
ndim)
1265 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s)
1266 integer :: idirmin,idim
1273 else if (
mf_eta<zero)
then
1280 dtdiffpar/(smalldouble+maxval(eta(ixo^s)/dxarr(idim)**2)))
1283 dtdiffpar/(smalldouble+maxval(eta(ixo^s)/
block%ds(ixo^s,idim)**2)))
1295 end subroutine mf_get_dt
1298 subroutine mf_add_source_geom(qdt,dtfactor, ixI^L,ixO^L,wCT,wprim,w,x)
1302 integer,
intent(in) :: ixi^
l, ixo^
l
1303 double precision,
intent(in) :: qdt, dtfactor, x(ixi^s,1:
ndim)
1304 double precision,
intent(inout) :: wct(ixi^s,1:nw), wprim(ixi^s,1:nw), w(ixi^s,1:nw)
1306 double precision :: tmp,invr,cs2
1307 integer :: iw,idir,ix^
d
1309 integer :: mr_,mphi_
1310 integer :: br_,bphi_
1313 br_=mag(1); bphi_=mag(1)-1+
phi_
1319 {
do ix^db=ixomin^db,ixomax^db\}
1320 w(ix^
d,bphi_)=w(ix^
d,bphi_)+qdt/x(ix^
d,1)*&
1321 (wct(ix^
d,bphi_)*wct(ix^
d,mr_) &
1322 -wct(ix^
d,br_)*wct(ix^
d,mphi_))
1326 if(
mf_glm) w(ixo^s,br_)=w(ixo^s,br_)+qdt*wct(ixo^s,
psi_)/x(ixo^s,1)
1328 {
do ix^db=ixomin^db,ixomax^db\}
1332 w(ix^d,mag(1))=w(ix^d,mag(1))+invr*2.0d0*wct(ix^d,
psi_)
1337 if(.not.stagger_grid)
then
1338 tmp=wct(ix^d,
mom(1))*wct(ix^d,mag(2))-wct(ix^d,
mom(2))*wct(ix^d,mag(1))
1339 cs2=1.d0/tan(x(ix^d,2))
1341 tmp=tmp+cs2*wct(ix^d,
psi_)
1343 w(ix^d,mag(2))=w(ix^d,mag(2))+tmp*invr
1350 if(.not.stagger_grid)
then
1351 w(ix^d,mag(3))=w(ix^d,mag(3))+invr*&
1352 (wct(ix^d,
mom(1))*wct(ix^d,mag(3)) &
1353 -wct(ix^d,
mom(3))*wct(ix^d,mag(1)))
1358 if(.not.stagger_grid)
then
1359 w(ix^d,mag(3))=w(ix^d,mag(3))+invr*&
1360 (wct(ix^d,
mom(1))*wct(ix^d,mag(3)) &
1361 -wct(ix^d,
mom(3))*wct(ix^d,mag(1)) &
1362 -(wct(ix^d,
mom(3))*wct(ix^d,mag(2)) &
1363 -wct(ix^d,
mom(2))*wct(ix^d,mag(3)))*cs2)
1370 end subroutine mf_add_source_geom
1372 subroutine mf_modify_wlr(ixI^L,ixO^L,qt,wLC,wRC,wLp,wRp,s,idir)
1375 integer,
intent(in) :: ixi^
l, ixo^
l, idir
1376 double precision,
intent(in) :: qt
1377 double precision,
intent(inout) :: wlc(ixi^s,1:nw), wrc(ixi^s,1:nw)
1378 double precision,
intent(inout) :: wlp(ixi^s,1:nw), wrp(ixi^s,1:nw)
1381 double precision :: db
1389 {
do ix^db=ixomin^db,ixomax^db\}
1390 db=wrp(ix^
d,mag(idir))-wlp(ix^
d,mag(idir))
1391 wlp(ix^
d,mag(idir))=half*(wrp(ix^
d,mag(idir))+wlp(ix^
d,mag(idir))-&
1394 wrp(ix^
d,mag(idir))=wlp(ix^
d,mag(idir))
1396 wrc(ix^
d,mag(idir))=wlp(ix^
d,mag(idir))
1398 wlc(ix^
d,mag(idir))=wlp(ix^
d,mag(idir))
1402 end subroutine mf_modify_wlr
1404 subroutine mf_boundary_adjust(igrid,psb)
1406 integer,
intent(in) :: igrid
1409 integer :: ib, idims, iside, ixo^
l, i^
d
1418 i^
d=
kr(^
d,idims)*(2*iside-3);
1419 if (neighbor_type(i^
d,igrid)/=1) cycle
1420 ib=(idims-1)*2+iside
1438 call fixdivb_boundary(ixg^
ll,ixo^
l,psb(igrid)%w,psb(igrid)%x,ib)
1443 end subroutine mf_boundary_adjust
1445 subroutine fixdivb_boundary(ixG^L,ixO^L,w,x,iB)
1448 integer,
intent(in) :: ixg^
l,ixo^
l,ib
1449 double precision,
intent(inout) :: w(ixg^s,1:nw)
1450 double precision,
intent(in) :: x(ixg^s,1:
ndim)
1452 double precision :: dx1x2,dx1x3,dx2x1,dx2x3,dx3x1,dx3x2
1453 integer :: ix^
d,ixf^
l
1465 do ix1=ixfmax1,ixfmin1,-1
1466 w(ix1-1,ixfmin2:ixfmax2,mag(1))=w(ix1+1,ixfmin2:ixfmax2,mag(1)) &
1467 +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
1468 w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
1471 do ix1=ixfmax1,ixfmin1,-1
1472 w(ix1-1,ixfmin2:ixfmax2,mag(1))=( (w(ix1+1,ixfmin2:ixfmax2,mag(1))+&
1473 w(ix1,ixfmin2:ixfmax2,mag(1)))*
block%surfaceC(ix1,ixfmin2:ixfmax2,1)&
1474 +(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
1475 block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
1476 -(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
1477 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
1478 /
block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
1492 do ix1=ixfmax1,ixfmin1,-1
1493 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1494 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
1495 +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
1496 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
1497 +dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
1498 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
1501 do ix1=ixfmax1,ixfmin1,-1
1502 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1503 ( (w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
1504 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
1505 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
1506 +(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
1507 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
1508 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
1509 -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
1510 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
1511 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
1512 +(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
1513 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
1514 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
1515 -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
1516 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1517 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
1518 /
block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
1519 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
1531 do ix1=ixfmin1,ixfmax1
1532 w(ix1+1,ixfmin2:ixfmax2,mag(1))=w(ix1-1,ixfmin2:ixfmax2,mag(1)) &
1533 -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
1534 w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
1537 do ix1=ixfmin1,ixfmax1
1538 w(ix1+1,ixfmin2:ixfmax2,mag(1))=( (w(ix1-1,ixfmin2:ixfmax2,mag(1))+&
1539 w(ix1,ixfmin2:ixfmax2,mag(1)))*
block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)&
1540 -(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
1541 block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
1542 +(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
1543 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
1544 /
block%surfaceC(ix1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
1558 do ix1=ixfmin1,ixfmax1
1559 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1560 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
1561 -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
1562 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
1563 -dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
1564 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
1567 do ix1=ixfmin1,ixfmax1
1568 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1569 ( (w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
1570 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
1571 block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
1572 -(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
1573 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
1574 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
1575 +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
1576 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
1577 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
1578 -(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
1579 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
1580 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
1581 +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
1582 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1583 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
1584 /
block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
1585 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
1597 do ix2=ixfmax2,ixfmin2,-1
1598 w(ixfmin1:ixfmax1,ix2-1,mag(2))=w(ixfmin1:ixfmax1,ix2+1,mag(2)) &
1599 +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
1600 w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
1603 do ix2=ixfmax2,ixfmin2,-1
1604 w(ixfmin1:ixfmax1,ix2-1,mag(2))=( (w(ixfmin1:ixfmax1,ix2+1,mag(2))+&
1605 w(ixfmin1:ixfmax1,ix2,mag(2)))*
block%surfaceC(ixfmin1:ixfmax1,ix2,2)&
1606 +(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
1607 block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
1608 -(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
1609 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
1610 /
block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
1624 do ix2=ixfmax2,ixfmin2,-1
1625 w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
1626 ix2+1,ixfmin3:ixfmax3,mag(2)) &
1627 +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
1628 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
1629 +dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
1630 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
1633 do ix2=ixfmax2,ixfmin2,-1
1634 w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=&
1635 ( (w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))+&
1636 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
1637 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)&
1638 +(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
1639 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1640 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
1641 -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
1642 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1643 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
1644 +(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
1645 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
1646 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
1647 -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
1648 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1649 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
1650 /
block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)-&
1651 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
1663 do ix2=ixfmin2,ixfmax2
1664 w(ixfmin1:ixfmax1,ix2+1,mag(2))=w(ixfmin1:ixfmax1,ix2-1,mag(2)) &
1665 -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
1666 w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
1669 do ix2=ixfmin2,ixfmax2
1670 w(ixfmin1:ixfmax1,ix2+1,mag(2))=( (w(ixfmin1:ixfmax1,ix2-1,mag(2))+&
1671 w(ixfmin1:ixfmax1,ix2,mag(2)))*
block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)&
1672 -(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
1673 block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
1674 +(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
1675 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
1676 /
block%surfaceC(ixfmin1:ixfmax1,ix2,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
1690 do ix2=ixfmin2,ixfmax2
1691 w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
1692 ix2-1,ixfmin3:ixfmax3,mag(2)) &
1693 -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
1694 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
1695 -dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
1696 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
1699 do ix2=ixfmin2,ixfmax2
1700 w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=&
1701 ( (w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))+&
1702 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
1703 block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)&
1704 -(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
1705 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1706 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
1707 +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
1708 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1709 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
1710 -(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
1711 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
1712 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
1713 +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
1714 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1715 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
1716 /
block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)-&
1717 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
1732 do ix3=ixfmax3,ixfmin3,-1
1733 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=w(ixfmin1:ixfmax1,&
1734 ixfmin2:ixfmax2,ix3+1,mag(3)) &
1735 +dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
1736 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
1737 +dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
1738 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
1741 do ix3=ixfmax3,ixfmin3,-1
1742 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=&
1743 ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))+&
1744 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
1745 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)&
1746 +(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
1747 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1748 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
1749 -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
1750 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1751 block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
1752 +(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
1753 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
1754 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
1755 -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
1756 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
1757 block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
1758 /
block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)-&
1759 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
1772 do ix3=ixfmin3,ixfmax3
1773 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=w(ixfmin1:ixfmax1,&
1774 ixfmin2:ixfmax2,ix3-1,mag(3)) &
1775 -dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
1776 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
1777 -dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
1778 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
1781 do ix3=ixfmin3,ixfmax3
1782 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=&
1783 ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))+&
1784 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
1785 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)&
1786 -(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
1787 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1788 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
1789 +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
1790 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1791 block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
1792 -(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
1793 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
1794 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
1795 +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
1796 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
1797 block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
1798 /
block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)-&
1799 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
1804 call mpistop(
"Special boundary is not defined for this region")
1807 end subroutine fixdivb_boundary
1816 double precision,
intent(in) :: qdt
1817 double precision,
intent(in) :: qt
1818 logical,
intent(inout) :: active
1820 double precision :: tmp(ixg^t), grad(ixg^t,
ndim)
1821 double precision :: res
1822 double precision,
parameter :: max_residual = 1
d-3
1823 double precision,
parameter :: residual_reduction = 1
d-10
1825 integer,
parameter :: max_its = 50
1826 double precision :: residual_it(max_its), max_divb
1827 integer :: iigrid, igrid
1828 integer :: n, nc, lvl, ix^
l, ixc^
l, idim
1831 mg%operator_type = mg_laplacian
1839 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1840 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1843 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
1844 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1846 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1847 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1850 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
1851 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1855 write(*,*)
"mf_clean_divb_multigrid warning: unknown boundary type"
1856 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1857 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1865 do iigrid = 1, igridstail
1866 igrid = igrids(iigrid);
1869 lvl =
mg%boxes(id)%lvl
1870 nc =
mg%box_size_lvl(lvl)
1876 call get_divb(ps(igrid)%w(ixg^t, 1:nw), ixg^
ll,
ixm^
ll, tmp, &
1878 mg%boxes(id)%cc({1:nc}, mg_irhs) = tmp(
ixm^t)
1879 max_divb = max(max_divb, maxval(abs(tmp(
ixm^t))))
1884 call mpi_allreduce(mpi_in_place, max_divb, 1, mpi_double_precision, &
1887 if (
mype == 0) print *,
"Performing multigrid divB cleaning"
1888 if (
mype == 0) print *,
"iteration vs residual"
1891 call mg_fas_fmg(
mg, n>1, max_res=residual_it(n))
1892 if (
mype == 0)
write(*,
"(I4,E11.3)") n, residual_it(n)
1893 if (residual_it(n) < residual_reduction * max_divb)
exit
1895 if (
mype == 0 .and. n > max_its)
then
1896 print *,
"divb_multigrid warning: not fully converged"
1897 print *,
"current amplitude of divb: ", residual_it(max_its)
1898 print *,
"multigrid smallest grid: ", &
1899 mg%domain_size_lvl(:,
mg%lowest_lvl)
1900 print *,
"note: smallest grid ideally has <= 8 cells"
1901 print *,
"multigrid dx/dy/dz ratio: ",
mg%dr(:, 1)/
mg%dr(1, 1)
1902 print *,
"note: dx/dy/dz should be similar"
1906 call mg_fas_vcycle(
mg, max_res=res)
1907 if (res < max_residual)
exit
1909 if (res > max_residual)
call mpistop(
"divb_multigrid: no convergence")
1914 do iigrid = 1, igridstail
1915 igrid = igrids(iigrid);
1924 tmp(ix^s) =
mg%boxes(id)%cc({:,}, mg_iphi)
1928 ixcmin^
d=ixmlo^
d-
kr(idim,^
d);
1930 call gradientf(tmp,ps(igrid)%x,ixg^
ll,ixc^
l,idim,grad(ixg^t,idim))
1931 ps(igrid)%ws(ixc^s,idim)=ps(igrid)%ws(ixc^s,idim)-grad(ixc^s,idim)
1939 ps(igrid)%w(
ixm^t, mag(1:
ndim)) = &
1940 ps(igrid)%w(
ixm^t, mag(1:
ndim)) - grad(
ixm^t, :)
1951 subroutine mf_update_faces_average(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
1955 integer,
intent(in) :: ixi^
l, ixo^
l
1956 double precision,
intent(in) :: qt, qdt
1958 double precision,
intent(in) :: wp(ixi^s,1:nw)
1959 type(state) :: sct, s
1960 type(ct_velocity) :: vcts
1961 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
1962 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
1964 double precision :: circ(ixi^s,1:
ndim)
1965 double precision :: e_resi(ixi^s,
sdim:3)
1966 integer :: ix^
d,ixc^
l,ixa^
l,i1kr^
d,i2kr^
d
1967 integer :: idim1,idim2,idir,iwdim1,iwdim2
1969 associate(bfaces=>s%ws,x=>s%x)
1976 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,e_resi)
1980 i1kr^
d=
kr(idim1,^
d);
1983 i2kr^
d=
kr(idim2,^
d);
1986 if (
lvc(idim1,idim2,idir)==1)
then
1988 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
1990 {
do ix^db=ixcmin^db,ixcmax^db\}
1991 fe(ix^
d,idir)=quarter*&
1992 (fc(ix^
d,iwdim1,idim2)+fc({ix^
d+i1kr^
d},iwdim1,idim2)&
1993 -fc(ix^
d,iwdim2,idim1)-fc({ix^
d+i2kr^
d},iwdim2,idim1))
1995 if(
mf_eta/=zero) fe(ix^
d,idir)=fe(ix^
d,idir)+e_resi(ix^
d,idir)
1998 fe(ix^
d,idir)=fe(ix^
d,idir)*qdt*s%dsC(ix^
d,idir)
2006 if(
associated(usr_set_electric_field)) &
2007 call usr_set_electric_field(ixi^l,ixo^l,qt,qdt,fe,sct)
2009 circ(ixi^s,1:ndim)=zero
2015 ixcmin^d=ixomin^d-kr(idim1,^d);
2017 ixa^l=ixc^l-kr(idim2,^d);
2020 if(lvc(idim1,idim2,idir)==1)
then
2022 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2025 else if(lvc(idim1,idim2,idir)==-1)
then
2027 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2034 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2036 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2041 end subroutine mf_update_faces_average
2044 subroutine mf_update_faces_contact(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
2048 integer,
intent(in) :: ixi^
l, ixo^
l
2049 double precision,
intent(in) :: qt, qdt
2051 double precision,
intent(in) :: wp(ixi^s,1:nw)
2052 type(state) :: sct, s
2053 type(ct_velocity) :: vcts
2054 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
2055 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
2057 double precision :: circ(ixi^s,1:
ndim)
2059 double precision :: ecc(ixi^s,
sdim:3)
2061 double precision :: el(ixi^s),er(ixi^s)
2063 double precision :: elc(ixi^s),erc(ixi^s)
2065 double precision :: jce(ixi^s,
sdim:3)
2066 integer :: hxc^
l,ixc^
l,jxc^
l,ixa^
l,ixb^
l
2067 integer :: idim1,idim2,idir,iwdim1,iwdim2
2069 associate(bfaces=>s%ws,x=>s%x,w=>s%w,vnorm=>vcts%vnorm)
2074 if(
lvc(idim1,idim2,idir)==1)
then
2075 ecc(ixi^s,idir)=ecc(ixi^s,idir)+wp(ixi^s,mag(idim1))*wp(ixi^s,
mom(idim2))
2076 else if(
lvc(idim1,idim2,idir)==-1)
then
2077 ecc(ixi^s,idir)=ecc(ixi^s,idir)-wp(ixi^s,mag(idim1))*wp(ixi^s,
mom(idim2))
2082 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,jce)
2094 if (
lvc(idim1,idim2,idir)==1)
then
2096 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
2098 jxc^
l=ixc^
l+
kr(idim1,^
d);
2099 hxc^
l=ixc^
l+
kr(idim2,^
d);
2101 fe(ixc^s,idir)=quarter*&
2102 (fc(ixc^s,iwdim1,idim2)+fc(jxc^s,iwdim1,idim2)&
2103 -fc(ixc^s,iwdim2,idim1)-fc(hxc^s,iwdim2,idim1))
2107 ixamax^
d=ixcmax^
d+
kr(idim1,^
d);
2108 el(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(ixa^s,idir)
2109 hxc^
l=ixa^
l+
kr(idim2,^
d);
2110 er(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(hxc^s,idir)
2111 where(vnorm(ixc^s,idim1)>0.d0)
2112 elc(ixc^s)=el(ixc^s)
2113 else where(vnorm(ixc^s,idim1)<0.d0)
2114 elc(ixc^s)=el(jxc^s)
2116 elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
2118 hxc^
l=ixc^
l+
kr(idim2,^
d);
2119 where(vnorm(hxc^s,idim1)>0.d0)
2120 erc(ixc^s)=er(ixc^s)
2121 else where(vnorm(hxc^s,idim1)<0.d0)
2122 erc(ixc^s)=er(jxc^s)
2124 erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
2126 fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
2129 jxc^
l=ixc^
l+
kr(idim2,^
d);
2131 ixamax^
d=ixcmax^
d+
kr(idim2,^
d);
2132 el(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(ixa^s,idir)
2133 hxc^
l=ixa^
l+
kr(idim1,^
d);
2134 er(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(hxc^s,idir)
2135 where(vnorm(ixc^s,idim2)>0.d0)
2136 elc(ixc^s)=el(ixc^s)
2137 else where(vnorm(ixc^s,idim2)<0.d0)
2138 elc(ixc^s)=el(jxc^s)
2140 elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
2142 hxc^
l=ixc^
l+
kr(idim1,^
d);
2143 where(vnorm(hxc^s,idim2)>0.d0)
2144 erc(ixc^s)=er(ixc^s)
2145 else where(vnorm(hxc^s,idim2)<0.d0)
2146 erc(ixc^s)=er(jxc^s)
2148 erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
2150 fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
2153 if(
mf_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+jce(ixc^s,idir)
2157 fe(ixc^s,idir)=fe(ixc^s,idir)*qdt*s%dsC(ixc^s,idir)
2172 circ(ixi^s,1:
ndim)=zero
2177 ixcmin^
d=ixomin^
d-
kr(idim1,^
d);
2181 if(
lvc(idim1,idim2,idir)/=0)
then
2182 hxc^
l=ixc^
l-
kr(idim2,^
d);
2184 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2185 +
lvc(idim1,idim2,idir)&
2192 where(s%surfaceC(ixc^s,idim1) > 1.0
d-9*s%dvolume(ixc^s))
2193 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2195 circ(ixc^s,idim1)=zero
2198 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2203 end subroutine mf_update_faces_contact
2206 subroutine mf_update_faces_hll(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
2211 integer,
intent(in) :: ixi^
l, ixo^
l
2212 double precision,
intent(in) :: qt, qdt
2214 double precision,
intent(in) :: wp(ixi^s,1:nw)
2215 type(state) :: sct, s
2216 type(ct_velocity) :: vcts
2217 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
2218 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
2220 double precision :: vtill(ixi^s,2)
2221 double precision :: vtilr(ixi^s,2)
2222 double precision :: btill(ixi^s,
ndim)
2223 double precision :: btilr(ixi^s,
ndim)
2224 double precision :: cp(ixi^s,2)
2225 double precision :: cm(ixi^s,2)
2226 double precision :: circ(ixi^s,1:
ndim)
2228 double precision :: jce(ixi^s,
sdim:3)
2229 integer :: hxc^
l,ixc^
l,ixcp^
l,jxc^
l,ixcm^
l
2230 integer :: idim1,idim2,idir
2232 associate(bfaces=>s%ws,bfacesct=>sct%ws,x=>s%x,vbarc=>vcts%vbarC,cbarmin=>vcts%cbarmin,&
2233 cbarmax=>vcts%cbarmax)
2246 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,jce)
2259 ixcmin^
d=ixomin^
d-1+
kr(idir,^
d);
2263 idim2=mod(idir+1,3)+1
2265 jxc^
l=ixc^
l+
kr(idim1,^
d);
2266 ixcp^
l=ixc^
l+
kr(idim2,^
d);
2270 vtill(ixi^s,2),vtilr(ixi^s,2))
2273 vtill(ixi^s,1),vtilr(ixi^s,1))
2279 btill(ixi^s,idim1),btilr(ixi^s,idim1))
2282 btill(ixi^s,idim2),btilr(ixi^s,idim2))
2286 cm(ixc^s,1)=max(cbarmin(ixcp^s,idim1),cbarmin(ixc^s,idim1))
2287 cp(ixc^s,1)=max(cbarmax(ixcp^s,idim1),cbarmax(ixc^s,idim1))
2289 cm(ixc^s,2)=max(cbarmin(jxc^s,idim2),cbarmin(ixc^s,idim2))
2290 cp(ixc^s,2)=max(cbarmax(jxc^s,idim2),cbarmax(ixc^s,idim2))
2294 fe(ixc^s,idir)=-(cp(ixc^s,1)*vtill(ixc^s,1)*btill(ixc^s,idim2) &
2295 + cm(ixc^s,1)*vtilr(ixc^s,1)*btilr(ixc^s,idim2) &
2296 - cp(ixc^s,1)*cm(ixc^s,1)*(btilr(ixc^s,idim2)-btill(ixc^s,idim2)))&
2297 /(cp(ixc^s,1)+cm(ixc^s,1)) &
2298 +(cp(ixc^s,2)*vtill(ixc^s,2)*btill(ixc^s,idim1) &
2299 + cm(ixc^s,2)*vtilr(ixc^s,2)*btilr(ixc^s,idim1) &
2300 - cp(ixc^s,2)*cm(ixc^s,2)*(btilr(ixc^s,idim1)-btill(ixc^s,idim1)))&
2301 /(cp(ixc^s,2)+cm(ixc^s,2))
2304 if(
mf_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+jce(ixc^s,idir)
2308 fe(ixc^s,idir)=qdt*s%dsC(ixc^s,idir)*fe(ixc^s,idir)
2322 circ(ixi^s,1:
ndim)=zero
2328 ixcmin^
d=ixomin^
d-
kr(idim1,^
d);
2332 if(
lvc(idim1,idim2,idir)/=0)
then
2333 hxc^
l=ixc^
l-
kr(idim2,^
d);
2335 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2336 +
lvc(idim1,idim2,idir)&
2343 where(s%surfaceC(ixc^s,idim1) > 1.0
d-9*s%dvolume(ixc^s))
2344 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2346 circ(ixc^s,idim1)=zero
2349 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2353 end subroutine mf_update_faces_hll
2356 subroutine get_resistive_electric_field(ixI^L,ixO^L,sCT,s,jce)
2361 integer,
intent(in) :: ixi^
l, ixo^
l
2362 type(state),
intent(in) :: sct, s
2364 double precision :: jce(ixi^s,
sdim:3)
2367 double precision :: jcc(ixi^s,7-2*
ndir:3)
2369 double precision :: xs(ixgs^t,1:
ndim)
2371 double precision :: eta(ixi^s)
2372 double precision :: gradi(ixgs^t)
2373 integer :: ix^
d,ixc^
l,ixa^
l,ixb^
l,idir,idirmin,idim1,idim2
2375 associate(x=>s%x,
dx=>s%dx,w=>s%w,wct=>sct%w,wcts=>sct%ws)
2381 if (
lvc(idim1,idim2,idir)==0) cycle
2382 ixcmax^
d=ixomax^
d+1;
2383 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-2;
2384 ixbmax^
d=ixcmax^
d-
kr(idir,^
d)+1;
2387 xs(ixb^s,:)=x(ixb^s,:)
2388 xs(ixb^s,idim2)=x(ixb^s,idim2)+half*
dx(ixb^s,idim2)
2389 call gradientf(wcts(ixgs^t,idim2),xs,ixgs^
ll,ixc^
l,idim1,gradi)
2390 if (
lvc(idim1,idim2,idir)==1)
then
2391 jce(ixc^s,idir)=jce(ixc^s,idir)+gradi(ixc^s)
2393 jce(ixc^s,idir)=jce(ixc^s,idir)-gradi(ixc^s)
2400 jce(ixi^s,:)=jce(ixi^s,:)*
mf_eta
2408 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
2409 jcc(ixc^s,idir)=0.d0
2411 if({ ix^
d==1 .and. ^
d==idir | .or.}) cycle
2412 ixamin^
d=ixcmin^
d+ix^
d;
2413 ixamax^
d=ixcmax^
d+ix^
d;
2414 jcc(ixc^s,idir)=jcc(ixc^s,idir)+eta(ixa^s)
2416 jcc(ixc^s,idir)=jcc(ixc^s,idir)*0.25d0
2417 jce(ixc^s,idir)=jce(ixc^s,idir)*jcc(ixc^s,idir)
2422 end subroutine get_resistive_electric_field
2428 integer,
intent(in) :: ixo^
l
2435 do ix^db=ixomin^db,ixomax^db\}
2437 s%w(ix^
d,mag(1))=half/s%surface(ix^
d,1)*(s%ws(ix^
d,1)*s%surfaceC(ix^
d,1)&
2438 +s%ws(ix1-1,ix2,ix3,1)*s%surfaceC(ix1-1,ix2,ix3,1))
2439 s%w(ix^
d,mag(2))=half/s%surface(ix^
d,2)*(s%ws(ix^
d,2)*s%surfaceC(ix^
d,2)&
2440 +s%ws(ix1,ix2-1,ix3,2)*s%surfaceC(ix1,ix2-1,ix3,2))
2441 s%w(ix^
d,mag(3))=half/s%surface(ix^
d,3)*(s%ws(ix^
d,3)*s%surfaceC(ix^
d,3)&
2442 +s%ws(ix1,ix2,ix3-1,3)*s%surfaceC(ix1,ix2,ix3-1,3))
2445 s%w(ix^
d,mag(1))=half/s%surface(ix^
d,1)*(s%ws(ix^
d,1)*s%surfaceC(ix^
d,1)&
2446 +s%ws(ix1-1,ix2,1)*s%surfaceC(ix1-1,ix2,1))
2447 s%w(ix^
d,mag(2))=half/s%surface(ix^
d,2)*(s%ws(ix^
d,2)*s%surfaceC(ix^
d,2)&
2448 +s%ws(ix1,ix2-1,2)*s%surfaceC(ix1,ix2-1,2))
2491 integer,
intent(in) :: ixis^
l, ixi^
l, ixo^
l
2492 double precision,
intent(inout) :: ws(ixis^s,1:nws)
2493 double precision,
intent(in) :: x(ixi^s,1:
ndim)
2495 double precision :: adummy(ixis^s,1:3)
2504 double precision :: sum_jbb_ipe, sum_j_ipe, sum_l_ipe, f_i_ipe, volume_pe
2505 double precision :: sum_jbb, sum_j, sum_l, f_i, volume, cw_sin_theta
2506 integer :: iigrid, igrid, ix^
d
2507 integer :: amode, istatus(mpi_status_size)
2508 integer,
save :: fhmf
2509 logical :: patchwi(ixg^t)
2510 logical,
save :: logmfopened=.false.
2511 character(len=800) :: filename,filehead
2512 character(len=800) :: line,datastr
2519 do iigrid=1,igridstail; igrid=igrids(iigrid);
2522 call mask_inner(ixg^
ll,
ixm^
ll,ps(igrid)%w,ps(igrid)%x,patchwi,volume_pe)
2523 sum_jbb_ipe = sum_jbb_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2524 ps(igrid)%x,1,patchwi)
2525 sum_j_ipe = sum_j_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2526 ps(igrid)%x,2,patchwi)
2527 f_i_ipe=f_i_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2528 ps(igrid)%x,3,patchwi)
2529 sum_l_ipe = sum_l_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2530 ps(igrid)%x,4,patchwi)
2532 call mpi_reduce(sum_jbb_ipe,sum_jbb,1,mpi_double_precision,&
2534 call mpi_reduce(sum_j_ipe,sum_j,1,mpi_double_precision,mpi_sum,0,&
2536 call mpi_reduce(f_i_ipe,f_i,1,mpi_double_precision,mpi_sum,0,&
2538 call mpi_reduce(sum_l_ipe,sum_l,1,mpi_double_precision,mpi_sum,0,&
2540 call mpi_reduce(volume_pe,volume,1,mpi_double_precision,mpi_sum,0,&
2546 cw_sin_theta = sum_jbb/sum_j
2552 if(.not.logmfopened)
then
2554 write(filename,
"(a,a)") trim(
base_filename),
"_mf_metrics.csv"
2558 open(unit=20,file=trim(filename),status=
'replace')
2559 close(20, status=
'delete')
2562 amode=ior(mpi_mode_create,mpi_mode_wronly)
2563 amode=ior(amode,mpi_mode_append)
2564 call mpi_file_open(mpi_comm_self,filename,amode,mpi_info_null,fhmf,
ierrmpi)
2566 filehead=
" it, time, CW_sin_theta, current, Lorenz_force, f_i"
2568 call mpi_file_write(fhmf,filehead,len_trim(filehead), &
2569 mpi_character,istatus,
ierrmpi)
2570 call mpi_file_write(fhmf,achar(10),1,mpi_character,istatus,
ierrmpi)
2574 write(datastr,
'(i8,a)')
it,
','
2575 line=trim(line)//trim(datastr)
2577 line=trim(line)//trim(datastr)
2578 write(datastr,
'(es13.6,a)') cw_sin_theta,
','
2579 line=trim(line)//trim(datastr)
2580 write(datastr,
'(es13.6,a)') sum_j,
','
2581 line=trim(line)//trim(datastr)
2582 write(datastr,
'(es13.6,a)') sum_l,
','
2583 line=trim(line)//trim(datastr)
2584 write(datastr,
'(es13.6)') f_i
2585 line=trim(line)//trim(datastr)//new_line(
'A')
2586 call mpi_file_write(fhmf,line,len_trim(line),mpi_character,istatus,
ierrmpi)
2588 call mpi_file_close(fhmf,
ierrmpi)
2595 subroutine mask_inner(ixI^L,ixO^L,w,x,patchwi,volume_pe)
2598 integer,
intent(in) :: ixi^
l,ixo^
l
2599 double precision,
intent(in):: w(ixi^s,nw),x(ixi^s,1:
ndim)
2600 double precision,
intent(inout) :: volume_pe
2601 logical,
intent(out) :: patchwi(ixi^s)
2603 double precision :: xo^
l
2606 {xomin^
d = xprobmin^
d + 0.05d0*(xprobmax^
d-xprobmin^
d)\}
2607 {xomax^
d = xprobmax^
d - 0.05d0*(xprobmax^
d-xprobmin^
d)\}
2609 xomin^nd = xprobmin^nd
2614 {
do ix^db=ixomin^db,ixomax^db\}
2615 if({ x(ix^dd,^
d) > xomin^
d .and. x(ix^dd,^
d) < xomax^
d | .and. })
then
2616 patchwi(ix^
d)=.true.
2617 volume_pe=volume_pe+
block%dvolume(ix^
d)
2619 patchwi(ix^
d)=.false.
2623 end subroutine mask_inner
2625 function integral_grid_mf(ixI^L,ixO^L,w,x,iw,patchwi)
2628 integer,
intent(in) :: ixi^
l,ixo^
l,iw
2629 double precision,
intent(in) :: x(ixi^s,1:
ndim)
2630 double precision :: w(ixi^s,nw+
nwauxio)
2631 logical,
intent(in) :: patchwi(ixi^s)
2633 double precision,
dimension(ixI^S,7-2*ndir:3) :: current
2634 double precision,
dimension(ixI^S,1:ndir) :: bvec,qvec
2635 double precision :: integral_grid_mf,tmp(ixi^s),bm2
2636 integer :: ix^
d,idirmin0,idirmin,idir,jdir,kdir
2638 integral_grid_mf=0.d0
2642 bvec(ixo^s,:)=w(ixo^s,mag(:))
2645 qvec(ixo^s,1:
ndir)=zero
2646 do idir=1,
ndir;
do jdir=idirmin,3;
do kdir=1,
ndir
2647 if(
lvc(idir,jdir,kdir)/=0)
then
2648 if(
lvc(idir,jdir,kdir)==1)
then
2649 qvec(ixo^s,idir)=qvec(ixo^s,idir)+current(ixo^s,jdir)*bvec(ixo^s,kdir)
2651 qvec(ixo^s,idir)=qvec(ixo^s,idir)-current(ixo^s,jdir)*bvec(ixo^s,kdir)
2654 end do;
end do;
end do
2656 {
do ix^db=ixomin^db,ixomax^db\}
2657 if(patchwi(ix^d))
then
2658 bm2=sum(bvec(ix^d,:)**2)
2659 if(bm2/=0.d0) bm2=1.d0/bm2
2660 integral_grid_mf=integral_grid_mf+sqrt(sum(qvec(ix^d,:)**2)*&
2661 bm2)*block%dvolume(ix^d)
2667 {
do ix^db=ixomin^db,ixomax^db\}
2668 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+sqrt(sum(current(ix^d,:)**2))*&
2675 {
do ix^db=ixomin^db,ixomax^db\}
2676 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+tmp(ix^d)*block%dvolume(ix^d)
2680 bvec(ixo^s,:)=w(ixo^s,mag(:))
2683 qvec(ixo^s,1:ndir)=zero
2684 do idir=1,ndir;
do jdir=idirmin,3;
do kdir=1,ndir
2685 if(lvc(idir,jdir,kdir)/=0)
then
2686 if(lvc(idir,jdir,kdir)==1)
then
2687 qvec(ixo^s,idir)=qvec(ixo^s,idir)+current(ixo^s,jdir)*bvec(ixo^s,kdir)
2689 qvec(ixo^s,idir)=qvec(ixo^s,idir)-current(ixo^s,jdir)*bvec(ixo^s,kdir)
2692 end do;
end do;
end do
2694 {
do ix^db=ixomin^db,ixomax^db\}
2695 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+&
2696 sqrt(sum(qvec(ix^d,:)**2))*block%dvolume(ix^d)
2700 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
subroutine create_bc_mpi_datatype(nwstart, nwbc, nwfull)
integer, dimension( :^d &), pointer type_send_p
integer, dimension( :^d &), pointer type_send_srl
integer, dimension(-1:1^d &), target type_send_r_p1
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.
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.
double precision, dimension(:), allocatable, parameter d
logical slab
Cartesian geometry or not.
integer, parameter bc_periodic
integer, parameter bc_special
boundary condition types
double precision unit_magneticfield
Physical scaling factor for magnetic field.
integer nwauxio
Number of auxiliary variables that are only included in output.
double precision unit_velocity
Physical scaling factor for velocity.
logical time_advance
do time evolving
character(len=std_len) restart_from_file
If not 'unavailable', resume from snapshot with this base file name.
double precision c_norm
Normalised speed of light.
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
double precision unit_temperature
Physical scaling factor for temperature.
integer, parameter bc_cont
logical si_unit
Use SI units (.true.) or use cgs units (.false.).
double precision, dimension(:,:), allocatable dx
spatial steps for all dimensions at all levels
integer nghostcells
Number of ghost cells surrounding a grid.
integer, parameter sdim
starting dimension for electric field
integer, parameter bc_symm
character(len= *), parameter undefined
logical need_global_cmax
need global maximal wave speed
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
logical use_multigrid
Use multigrid (only available in 2D and 3D).
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
character(len=std_len) base_filename
Base file name for simulation output, which will be followed by a number.
integer max_blocks
The maximum number of grid blocks in a processor.
integer r_
Indices for cylindrical coordinates FOR TESTS, negative value when not used:
logical record_electric_field
True for record electric field.
integer, parameter ixglo
Lower index of grid block arrays (always 1).
integer, public, protected b
double precision, public mf_nu
viscosity coefficient in s cm^-2 for solar corona (Cheung 2012 ApJ)
subroutine, public mf_phys_init()
integer, public, protected mf_divb_nth
Whether divB is computed with a fourth order approximation.
subroutine, public b_from_vector_potential(ixisl, ixil, ixol, ws, x)
calculate magnetic field from vector potential
logical, public, protected mf_record_electric_field
set to true if need to record electric field on cell edges
logical, public, protected clean_initial_divb
clean divb in the initial condition
logical, public divbwave
Add divB wave in Roe solver.
subroutine, public mf_face_to_center(ixol, s)
calculate cell-center values from face-center values
double precision, public mf_vmax
maximal limit of magnetofrictional velocity in cm s^-1 (Pomoell 2019 A&A)
logical, public, protected mf_glm
Whether GLM-MHD is used.
double precision, public mf_eta_hyper
The hyper-resistivity.
double precision, public mf_glm_alpha
GLM-MHD parameter: ratio of the diffusive and advective time scales for div b taking values within [0...
integer, public, protected c
Indices of the momentum density for the form of better vectorization.
integer, public, protected c_
logical, dimension(2 *^nd), public, protected boundary_divbfix
To control divB=0 fix for boundary.
character(len=std_len), public, protected type_ct
Method type of constrained transport.
character(len=std_len), public, protected typedivbfix
Method type to clean divergence of B.
subroutine, public get_normalized_divb(w, ixil, ixol, divb)
get dimensionless div B = |divB| * volume / area / |B|
integer, dimension(2 *^nd), public, protected boundary_divbfix_skip
To skip * layer of ghost cells during divB=0 fix for boundary.
double precision, dimension(2 *^nd), public mf_decay_scale
decay scale of frictional velocity near boundaries
subroutine, public record_force_free_metrics()
subroutine, public mf_to_conserved(ixil, ixol, w, x)
Transform primitive variables into conservative ones.
subroutine, public get_current(w, ixil, ixol, idirmin, current, fourthorder)
Calculate idirmin and the idirmin:3 components of the common current array make sure that dxlevel(^D)...
integer, public, protected psi_
Indices of the GLM psi.
integer, dimension(:), allocatable, public, protected mom
Indices of the momentum density.
subroutine, public mf_clean_divb_multigrid(qdt, qt, active)
logical, public, protected mf_particles
Whether particles module is added.
integer, public, protected m
subroutine, public mf_to_primitive(ixil, ixol, w, x)
Transform conservative variables into primitive ones.
double precision, public mf_eta
The resistivity.
logical, public, protected source_split_divb
Whether divB cleaning sources are added splitting from fluid solver.
double precision, public, protected he_abundance
Helium abundance over Hydrogen.
Module to couple the octree-mg library to AMRVAC. This file uses the VACPP preprocessor,...
type(mg_t) mg
Data structure containing the multigrid tree.
Module containing all the particle routines.
subroutine particles_init()
Initialize particle data and parameters.
This module defines the procedures of a physics module. It contains function pointers for the various...
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.