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")
255 if(
ndim>1) flux_type(idir,mag(idir))=flux_tvdlf
259 phys_get_dt => mf_get_dt
260 phys_get_cmax => mf_get_cmax
261 phys_get_cbounds => mf_get_cbounds
262 phys_get_flux => mf_get_flux
263 phys_add_source_geom => mf_add_source_geom
264 phys_add_source => mf_add_source
267 phys_check_params => mf_check_params
268 phys_write_info => mf_write_info
269 phys_special_advance => mf_velocity_update
271 if(type_divb==divb_glm)
then
272 phys_modify_wlr => mf_modify_wlr
284 transverse_ghost_cells = 1
285 phys_get_ct_velocity => mf_get_ct_velocity_average
286 phys_update_faces => mf_update_faces_average
288 transverse_ghost_cells = 1
289 phys_get_ct_velocity => mf_get_ct_velocity_contact
290 phys_update_faces => mf_update_faces_contact
292 transverse_ghost_cells = 2
293 phys_get_ct_velocity => mf_get_ct_velocity_hll
294 phys_update_faces => mf_update_faces_hll
296 call mpistop(
'choose average, uct_contact,or uct_hll for type_ct!')
299 phys_boundary_adjust => mf_boundary_adjust
308 call mf_physical_units()
312 subroutine mf_check_params
317 ngridvars,num_particles,physics_type_particles
327 write(*,*)
'====MF run with settings===================='
328 write(*,*)
'Using mod_mf_phys with settings:'
330 write(*,*)
'Dimensionality :',
ndim
331 write(*,*)
'vector components:',
ndir
333 write(*,*)
'number of variables nw=',nw
334 write(*,*)
' start index iwstart=',iwstart
335 write(*,*)
'number of vector variables=',nvector
336 write(*,*)
'number of stagger variables nws=',nws
337 write(*,*)
'number of variables with BCs=',nwgc
338 write(*,*)
'number of vars with fluxes=',nwflux
339 write(*,*)
'number of vars with flux + BC=',nwfluxbc
340 write(*,*)
'number of auxiliary variables=',nwaux
341 write(*,*)
'number of extra vars without flux=',nwextra
342 write(*,*)
'number of extra vars for wextra=',nw_extra
343 write(*,*)
'number of auxiliary I/O variables=',
nwauxio
344 write(*,*)
' mf_eta=',
mf_eta,
' nonzero implies resistivity'
349 write(*,*)
'*****Using particles: particles_eta, particles_etah :', particles_eta, particles_etah
350 write(*,*)
'*****Using particles: npayload,ngridvars :', npayload,ngridvars
351 write(*,*)
'*****Using particles: nusrpayload :', nusrpayload
352 write(*,*)
'*****Using particles: num_particles :', num_particles
353 write(*,*)
'*****Using particles: physics_type_particles=',physics_type_particles
356 write(*,*)
'number due to phys_wider_stencil=',phys_wider_stencil
357 write(*,*)
'==========================================='
361 end subroutine mf_check_params
363 subroutine mf_physical_units()
365 double precision :: mp,kb,miu0,c_lightspeed
366 double precision :: a,
b
502 end subroutine mf_physical_units
507 integer,
intent(in) :: ixi^
l, ixo^
l
508 double precision,
intent(inout) :: w(ixi^s, nw)
509 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
517 integer,
intent(in) :: ixi^
l, ixo^
l
518 double precision,
intent(inout) :: w(ixi^s, nw)
519 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
525 subroutine mf_get_cmax(w,x,ixI^L,ixO^L,idim,cmax)
528 integer,
intent(in) :: ixi^
l, ixo^
l, idim
529 double precision,
intent(in) :: w(ixi^s, nw), x(ixi^s,1:
ndim)
530 double precision,
intent(inout) :: cmax(ixi^s)
532 cmax(ixo^s)=abs(w(ixo^s,
mom(idim)))+one
534 end subroutine mf_get_cmax
537 subroutine mf_get_cbounds(wLC,wRC,wLp,wRp,x,ixI^L,ixO^L,idim,Hspeed,cmax,cmin)
541 integer,
intent(in) :: ixi^
l, ixo^
l, idim
542 double precision,
intent(in) :: wlc(ixi^s,
nw), wrc(ixi^s,
nw)
543 double precision,
intent(in) :: wlp(ixi^s,
nw), wrp(ixi^s,
nw)
544 double precision,
intent(in) :: x(ixi^s,1:
ndim)
546 double precision,
intent(inout),
optional :: cmin(ixi^s,1:
number_species)
549 double precision,
dimension(ixI^S) :: tmp1
551 tmp1(ixo^s)=0.5d0*(wlc(ixo^s,
mom(idim))+wrc(ixo^s,
mom(idim)))
552 if(
present(cmin))
then
553 cmax(ixo^s,1)=max(tmp1(ixo^s)+one,zero)
554 cmin(ixo^s,1)=min(tmp1(ixo^s)-one,zero)
556 cmax(ixo^s,1)=abs(tmp1(ixo^s))+one
559 end subroutine mf_get_cbounds
562 subroutine mf_get_ct_velocity_average(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
565 integer,
intent(in) :: ixi^
l, ixo^
l, idim
566 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
567 double precision,
intent(in) :: cmax(ixi^s)
568 double precision,
intent(in),
optional :: cmin(ixi^s)
569 type(ct_velocity),
intent(inout):: vcts
571 end subroutine mf_get_ct_velocity_average
573 subroutine mf_get_ct_velocity_contact(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
576 integer,
intent(in) :: ixi^
l, ixo^
l, idim
577 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
578 double precision,
intent(in) :: cmax(ixi^s)
579 double precision,
intent(in),
optional :: cmin(ixi^s)
580 type(ct_velocity),
intent(inout):: vcts
583 if(.not.
allocated(vcts%vnorm))
allocate(vcts%vnorm(ixi^s,1:
ndim))
585 vcts%vnorm(ixo^s,idim)=0.5d0*(wlp(ixo^s,
mom(idim))+wrp(ixo^s,
mom(idim)))
587 end subroutine mf_get_ct_velocity_contact
589 subroutine mf_get_ct_velocity_hll(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
592 integer,
intent(in) :: ixi^
l, ixo^
l, idim
593 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
594 double precision,
intent(in) :: cmax(ixi^s)
595 double precision,
intent(in),
optional :: cmin(ixi^s)
596 type(ct_velocity),
intent(inout):: vcts
598 integer :: idime,idimn
600 if(.not.
allocated(vcts%vbarC))
then
601 allocate(vcts%vbarC(ixi^s,1:
ndir,2),vcts%vbarLC(ixi^s,1:
ndir,2),vcts%vbarRC(ixi^s,1:
ndir,2))
602 allocate(vcts%cbarmin(ixi^s,1:
ndim),vcts%cbarmax(ixi^s,1:
ndim))
605 if(
present(cmin))
then
606 vcts%cbarmin(ixo^s,idim)=max(-cmin(ixo^s),zero)
607 vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
609 vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
610 vcts%cbarmin(ixo^s,idim)=vcts%cbarmax(ixo^s,idim)
613 idimn=mod(idim,
ndir)+1
614 idime=mod(idim+1,
ndir)+1
616 vcts%vbarLC(ixo^s,idim,1)=wlp(ixo^s,
mom(idimn))
617 vcts%vbarRC(ixo^s,idim,1)=wrp(ixo^s,
mom(idimn))
618 vcts%vbarC(ixo^s,idim,1)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,1) &
619 +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
620 /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
622 vcts%vbarLC(ixo^s,idim,2)=wlp(ixo^s,
mom(idime))
623 vcts%vbarRC(ixo^s,idim,2)=wrp(ixo^s,
mom(idime))
624 vcts%vbarC(ixo^s,idim,2)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,2) &
625 +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
626 /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
628 end subroutine mf_get_ct_velocity_hll
631 subroutine mf_get_flux(wC,w,x,ixI^L,ixO^L,idim,f)
636 integer,
intent(in) :: ixi^
l, ixo^
l, idim
638 double precision,
intent(in) :: wc(ixi^s,nw)
640 double precision,
intent(in) :: w(ixi^s,nw)
641 double precision,
intent(in) :: x(ixi^s,1:
ndim)
642 double precision,
intent(out) :: f(ixi^s,nwflux)
646 {
do ix^db=ixomin^db,ixomax^db\}
652 {
do ix^db=ixomin^db,ixomax^db\}
653 f(ix^d,mag(idim))=w(ix^d,
psi_)
655 f(ix^d,
psi_)=cmax_global**2*w(ix^d,mag(idim))
659 end subroutine mf_get_flux
662 subroutine mf_velocity_update(qt,psa)
665 double precision,
intent(in) :: qt
668 integer :: iigrid,igrid
669 logical :: stagger_flag
670 logical :: firstmf=.true.
685 do iigrid=1,igridstail_active; igrid=igrids_active(iigrid);
687 call frictional_velocity(psa(igrid)%w,psa(igrid)%x,ixg^
ll,
ixm^
ll)
711 end subroutine mf_velocity_update
714 subroutine mf_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
717 integer,
intent(in) :: ixi^
l, ixo^
l
718 double precision,
intent(in) :: qdt, dtfactor
719 double precision,
intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw), x(ixi^s,1:
ndim)
720 double precision,
intent(inout) :: w(ixi^s,1:nw)
721 logical,
intent(in) :: qsourcesplit
722 logical,
intent(inout) :: active
724 if (.not. qsourcesplit)
then
727 if (abs(
mf_eta)>smalldouble)
then
729 call add_source_res2(qdt,ixi^
l,ixo^
l,wct,w,x)
734 call add_source_hyperres(qdt,ixi^
l,ixo^
l,wct,w,x)
742 select case (type_divb)
747 call add_source_glm(qdt,ixi^
l,ixo^
l,wct,w,x)
750 call add_source_powel(qdt,ixi^
l,ixo^
l,wct,w,x)
753 call add_source_janhunen(qdt,ixi^
l,ixo^
l,wct,w,x)
756 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
757 case (divb_lindejanhunen)
759 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
760 call add_source_janhunen(qdt,ixi^
l,ixo^
l,wct,w,x)
761 case (divb_lindepowel)
763 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
764 call add_source_powel(qdt,ixi^
l,ixo^
l,wct,w,x)
767 call add_source_linde(qdt,ixi^
l,ixo^
l,wct,w,x)
768 call add_source_glm(qdt,ixi^
l,ixo^
l,wct,w,x)
771 case (divb_multigrid)
774 call mpistop(
'Unknown divB fix')
779 end subroutine mf_add_source
781 subroutine frictional_velocity(w,x,ixI^L,ixO^L)
784 integer,
intent(in) :: ixi^
l, ixo^
l
785 double precision,
intent(in) :: x(ixi^s,1:
ndim)
786 double precision,
intent(inout) :: w(ixi^s,1:nw)
788 double precision :: xmin(
ndim),xmax(
ndim)
789 double precision :: decay(ixo^s)
790 double precision :: current(ixi^s,7-2*
ndir:3),tmp(ixo^s)
791 integer :: ix^
d, idirmin,idir,jdir,kdir
797 if(
block%is_physical_boundary(2*^
d-1))
then
800 if(2*^
d-1==5.and.
ndim==3)
then
802 current(ixomin^
d^
d%ixO^s,:)=current(ixomin^
d+1^
d%ixO^s,:)
807 current(ixomin^
d^
d%ixO^s,:)=current(ixomin^
d+1^
d%ixO^s,:)
811 if(
block%is_physical_boundary(2*^
d))
then
812 current(ixomax^
d^
d%ixO^s,:)=current(ixomax^
d-1^
d%ixO^s,:)
817 do idir=1,
ndir;
do jdir=idirmin,3;
do kdir=1,
ndir
818 if(
lvc(idir,jdir,kdir)/=0)
then
819 if(
lvc(idir,jdir,kdir)==1)
then
820 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))+current(ixo^s,jdir)*w(ixo^s,mag(kdir))
822 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))-current(ixo^s,jdir)*w(ixo^s,mag(kdir))
825 end do;
end do;
end do
827 tmp(ixo^s)=sum(w(ixo^s,mag(:))**2,dim=ndim+1)
829 where(tmp(ixo^s)/=0.d0)
830 tmp(ixo^s)=1.d0/(tmp(ixo^s)*
mf_nu)
834 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))*tmp(ixo^s)
838 ^d&xmin(^d)=xprobmin^d\
839 ^d&xmax(^d)=xprobmax^d\
849 tmp(ixo^s)=sqrt(sum(w(ixo^s,
mom(:))**2,dim=ndim+1))/
mf_vmax+1.d-12
850 tmp(ixo^s)=dtanh(tmp(ixo^s))/tmp(ixo^s)
852 w(ixo^s,
mom(idir))=w(ixo^s,
mom(idir))*tmp(ixo^s)*decay(ixo^s)
855 end subroutine frictional_velocity
861 subroutine add_source_res1(qdt,ixI^L,ixO^L,wCT,w,x)
866 integer,
intent(in) :: ixi^
l, ixo^
l
867 double precision,
intent(in) :: qdt
868 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
869 double precision,
intent(inout) :: w(ixi^s,1:nw)
872 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s)
873 double precision :: gradeta(ixi^s,1:
ndim), bf(ixi^s,1:
ndir)
874 double precision :: tmp(ixi^s),tmp2(ixi^s)
875 integer :: ixa^
l,idir,jdir,kdir,idirmin,idim,jxo^
l,hxo^
l,ix
876 integer :: lxo^
l, kxo^
l
881 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
882 call mpistop(
"Error in add_source_res1: Non-conforming input limits")
889 gradeta(ixo^s,1:
ndim)=zero
895 gradeta(ixo^s,idim)=tmp(ixo^s)
899 bf(ixi^s,1:
ndir)=wct(ixi^s,mag(1:
ndir))
904 tmp2(ixi^s)=bf(ixi^s,idir)
906 lxo^
l=ixo^
l+2*
kr(idim,^
d);
907 jxo^
l=ixo^
l+
kr(idim,^
d);
908 hxo^
l=ixo^
l-
kr(idim,^
d);
909 kxo^
l=ixo^
l-2*
kr(idim,^
d);
910 tmp(ixo^s)=tmp(ixo^s)+&
911 (-tmp2(lxo^s)+16.0d0*tmp2(jxo^s)-30.0d0*tmp2(ixo^s)+16.0d0*tmp2(hxo^s)-tmp2(kxo^s)) &
916 tmp(ixo^s)=tmp(ixo^s)*eta(ixo^s)
920 do jdir=1,
ndim;
do kdir=idirmin,3
921 if (
lvc(idir,jdir,kdir)/=0)
then
922 if (
lvc(idir,jdir,kdir)==1)
then
923 tmp(ixo^s)=tmp(ixo^s)-gradeta(ixo^s,jdir)*current(ixo^s,kdir)
925 tmp(ixo^s)=tmp(ixo^s)+gradeta(ixo^s,jdir)*current(ixo^s,kdir)
932 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))+qdt*tmp(ixo^s)
936 end subroutine add_source_res1
940 subroutine add_source_res2(qdt,ixI^L,ixO^L,wCT,w,x)
945 integer,
intent(in) :: ixi^
l, ixo^
l
946 double precision,
intent(in) :: qdt
947 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
948 double precision,
intent(inout) :: w(ixi^s,1:nw)
951 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s),curlj(ixi^s,1:3)
952 double precision :: tmpvec(ixi^s,1:3)
953 integer :: ixa^
l,idir,idirmin,idirmin1
960 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
961 call mpistop(
"Error in add_source_res2: Non-conforming input limits")
975 tmpvec(ixa^s,1:
ndir)=zero
977 tmpvec(ixa^s,idir)=current(ixa^s,idir)*eta(ixa^s)
984 w(ixo^s,mag(
ndir)) = w(ixo^s,mag(
ndir))-qdt*curlj(ixo^s,
ndir)
987 w(ixo^s,mag(1:
ndir)) = w(ixo^s,mag(1:
ndir))-qdt*curlj(ixo^s,1:
ndir)
990 end subroutine add_source_res2
994 subroutine add_source_hyperres(qdt,ixI^L,ixO^L,wCT,w,x)
998 integer,
intent(in) :: ixi^
l, ixo^
l
999 double precision,
intent(in) :: qdt
1000 double precision,
intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1001 double precision,
intent(inout) :: w(ixi^s,1:nw)
1003 double precision :: current(ixi^s,7-2*
ndir:3)
1004 double precision :: tmpvec(ixi^s,1:3),tmpvec2(ixi^s,1:3),tmp(ixi^s),ehyper(ixi^s,1:3)
1005 integer :: ixa^
l,idir,jdir,kdir,idirmin,idirmin1
1008 if (iximin^
d>ixamin^
d.or.iximax^
d<ixamax^
d|.or.) &
1009 call mpistop(
"Error in add_source_hyperres: Non-conforming input limits")
1012 tmpvec(ixa^s,1:
ndir)=zero
1014 tmpvec(ixa^s,jdir)=current(ixa^s,jdir)
1018 call curlvector(tmpvec,ixi^
l,ixa^
l,tmpvec2,idirmin1,1,3)
1021 tmpvec(ixa^s,1:
ndir)=zero
1022 call curlvector(tmpvec2,ixi^
l,ixa^
l,tmpvec,idirmin1,1,3)
1026 tmpvec2(ixa^s,1:
ndir)=zero
1027 call curlvector(ehyper,ixi^
l,ixa^
l,tmpvec2,idirmin1,1,3)
1030 w(ixo^s,mag(idir)) = w(ixo^s,mag(idir))-tmpvec2(ixo^s,idir)*qdt
1033 end subroutine add_source_hyperres
1035 subroutine add_source_glm(qdt,ixI^L,ixO^L,wCT,w,x)
1042 integer,
intent(in) :: ixi^
l, ixo^
l
1043 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1044 double precision,
intent(inout) :: w(ixi^s,1:nw)
1045 double precision:: divb(ixi^s)
1046 double precision :: gradpsi(ixi^s)
1047 integer :: idim,idir
1074 end subroutine add_source_glm
1077 subroutine add_source_powel(qdt,ixI^L,ixO^L,wCT,w,x)
1080 integer,
intent(in) :: ixi^
l, ixo^
l
1081 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1082 double precision,
intent(inout) :: w(ixi^s,1:nw)
1084 double precision :: divb(ixi^s)
1092 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*wct(ixo^s,
mom(idir))*divb(ixo^s)
1095 end subroutine add_source_powel
1097 subroutine add_source_janhunen(qdt,ixI^L,ixO^L,wCT,w,x)
1102 integer,
intent(in) :: ixi^
l, ixo^
l
1103 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1104 double precision,
intent(inout) :: w(ixi^s,1:nw)
1105 double precision :: divb(ixi^s)
1113 w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*wct(ixo^s,
mom(idir))*divb(ixo^s)
1116 end subroutine add_source_janhunen
1118 subroutine add_source_linde(qdt,ixI^L,ixO^L,wCT,w,x)
1123 integer,
intent(in) :: ixi^
l, ixo^
l
1124 double precision,
intent(in) :: qdt, wct(ixi^s,1:nw), x(ixi^s,1:
ndim)
1125 double precision,
intent(inout) :: w(ixi^s,1:nw)
1126 double precision :: divb(ixi^s),graddivb(ixi^s)
1127 integer :: idim, idir, ixp^
l, i^
d, iside
1128 logical,
dimension(-1:1^D&) :: leveljump
1136 if(i^
d==0|.and.) cycle
1137 if(neighbor_type(i^
d,
block%igrid)==2 .or. neighbor_type(i^
d,
block%igrid)==4)
then
1138 leveljump(i^
d)=.true.
1140 leveljump(i^
d)=.false.
1149 i^dd=kr(^dd,^d)*(2*iside-3);
1150 if (leveljump(i^dd))
then
1152 ixpmin^d=ixomin^d-i^d
1154 ixpmax^d=ixomax^d-i^d
1165 select case(typegrad)
1167 call gradient(divb,ixi^l,ixp^l,idim,graddivb)
1169 call gradientl(divb,ixi^l,ixp^l,idim,graddivb)
1173 if (slab_uniform)
then
1174 graddivb(ixp^s)=graddivb(ixp^s)*divbdiff/(^d&1.0d0/dxlevel(^d)**2+)
1176 graddivb(ixp^s)=graddivb(ixp^s)*divbdiff &
1177 /(^d&1.0d0/block%ds(ixp^s,^d)**2+)
1180 w(ixp^s,mag(idim))=w(ixp^s,mag(idim))+graddivb(ixp^s)
1183 end subroutine add_source_linde
1191 integer,
intent(in) :: ixi^
l, ixo^
l
1192 double precision,
intent(in) :: w(ixi^s,1:nw)
1193 double precision :: divb(ixi^s), dsurface(ixi^s)
1195 double precision :: invb(ixo^s)
1196 integer :: ixa^
l,idims
1198 call get_divb(w,ixi^
l,ixo^
l,divb)
1199 invb(ixo^s)=sqrt(sum(w(ixo^s, mag(:))**2, dim=
ndim+1))
1200 where(invb(ixo^s)/=0.d0)
1201 invb(ixo^s)=1.d0/invb(ixo^s)
1204 divb(ixo^s)=0.5d0*abs(divb(ixo^s))*invb(ixo^s)/sum(1.d0/
dxlevel(:))
1206 ixamin^
d=ixomin^
d-1;
1207 ixamax^
d=ixomax^
d-1;
1208 dsurface(ixo^s)= sum(
block%surfaceC(ixo^s,:),dim=
ndim+1)
1210 ixa^
l=ixo^
l-
kr(idims,^
d);
1211 dsurface(ixo^s)=dsurface(ixo^s)+
block%surfaceC(ixa^s,idims)
1213 divb(ixo^s)=abs(divb(ixo^s))*invb(ixo^s)*&
1214 block%dvolume(ixo^s)/dsurface(ixo^s)
1225 integer,
intent(in) :: ixo^
l, ixi^
l
1226 double precision,
intent(in) :: w(ixi^s,1:nw)
1227 integer,
intent(out) :: idirmin
1228 logical,
intent(in),
optional :: fourthorder
1231 double precision :: current(ixi^s,7-2*
ndir:3)
1232 integer :: idir, idirmin0
1236 if(
present(fourthorder))
then
1245 subroutine mf_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
1249 integer,
intent(in) :: ixi^
l, ixo^
l
1250 double precision,
intent(inout) :: dtnew
1251 double precision,
intent(in) ::
dx^
d
1252 double precision,
intent(in) :: w(ixi^s,1:nw)
1253 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1255 double precision :: dxarr(
ndim)
1256 double precision :: current(ixi^s,7-2*
ndir:3),eta(ixi^s)
1257 integer :: idirmin,idim
1264 else if (
mf_eta<zero)
then
1271 dtdiffpar/(smalldouble+maxval(eta(ixo^s)/dxarr(idim)**2)))
1274 dtdiffpar/(smalldouble+maxval(eta(ixo^s)/
block%ds(ixo^s,idim)**2)))
1286 end subroutine mf_get_dt
1289 subroutine mf_add_source_geom(qdt,dtfactor, ixI^L,ixO^L,wCT,wprim,w,x)
1293 integer,
intent(in) :: ixi^
l, ixo^
l
1294 double precision,
intent(in) :: qdt, dtfactor, x(ixi^s,1:
ndim)
1295 double precision,
intent(inout) :: wct(ixi^s,1:nw), wprim(ixi^s,1:nw), w(ixi^s,1:nw)
1297 double precision :: tmp,invr,cs2
1298 integer :: iw,idir,ix^
d
1300 integer :: mr_,mphi_
1301 integer :: br_,bphi_
1304 br_=mag(1); bphi_=mag(1)-1+
phi_
1310 {
do ix^db=ixomin^db,ixomax^db\}
1311 w(ix^
d,bphi_)=w(ix^
d,bphi_)+qdt/x(ix^
d,1)*&
1312 (wct(ix^
d,bphi_)*wct(ix^
d,mr_) &
1313 -wct(ix^
d,br_)*wct(ix^
d,mphi_))
1317 if(
mf_glm) w(ixo^s,br_)=w(ixo^s,br_)+qdt*wct(ixo^s,
psi_)/x(ixo^s,1)
1319 {
do ix^db=ixomin^db,ixomax^db\}
1323 w(ix^d,mag(1))=w(ix^d,mag(1))+invr*2.0d0*wct(ix^d,
psi_)
1328 if(.not.stagger_grid)
then
1329 tmp=wct(ix^d,
mom(1))*wct(ix^d,mag(2))-wct(ix^d,
mom(2))*wct(ix^d,mag(1))
1330 cs2=1.d0/tan(x(ix^d,2))
1332 tmp=tmp+cs2*wct(ix^d,
psi_)
1334 w(ix^d,mag(2))=w(ix^d,mag(2))+tmp*invr
1341 if(.not.stagger_grid)
then
1342 w(ix^d,mag(3))=w(ix^d,mag(3))+invr*&
1343 (wct(ix^d,
mom(1))*wct(ix^d,mag(3)) &
1344 -wct(ix^d,
mom(3))*wct(ix^d,mag(1)))
1349 if(.not.stagger_grid)
then
1350 w(ix^d,mag(3))=w(ix^d,mag(3))+invr*&
1351 (wct(ix^d,
mom(1))*wct(ix^d,mag(3)) &
1352 -wct(ix^d,
mom(3))*wct(ix^d,mag(1)) &
1353 -(wct(ix^d,
mom(3))*wct(ix^d,mag(2)) &
1354 -wct(ix^d,
mom(2))*wct(ix^d,mag(3)))*cs2)
1361 end subroutine mf_add_source_geom
1363 subroutine mf_modify_wlr(ixI^L,ixO^L,qt,wLC,wRC,wLp,wRp,s,idir)
1366 integer,
intent(in) :: ixi^
l, ixo^
l, idir
1367 double precision,
intent(in) :: qt
1368 double precision,
intent(inout) :: wlc(ixi^s,1:nw), wrc(ixi^s,1:nw)
1369 double precision,
intent(inout) :: wlp(ixi^s,1:nw), wrp(ixi^s,1:nw)
1371 double precision :: db(ixi^s), dpsi(ixi^s)
1379 db(ixo^s) = wrp(ixo^s,mag(idir)) - wlp(ixo^s,mag(idir))
1380 dpsi(ixo^s) = wrp(ixo^s,
psi_) - wlp(ixo^s,
psi_)
1382 wlp(ixo^s,mag(idir)) = 0.5d0 * (wrp(ixo^s,mag(idir)) + wlp(ixo^s,mag(idir))) &
1384 wlp(ixo^s,
psi_) = 0.5d0 * (wrp(ixo^s,
psi_) + wlp(ixo^s,
psi_)) &
1387 wrp(ixo^s,mag(idir)) = wlp(ixo^s,mag(idir))
1390 end subroutine mf_modify_wlr
1392 subroutine mf_boundary_adjust(igrid,psb)
1394 integer,
intent(in) :: igrid
1397 integer :: ib, idims, iside, ixo^
l, i^
d
1406 i^
d=
kr(^
d,idims)*(2*iside-3);
1407 if (neighbor_type(i^
d,igrid)/=1) cycle
1408 ib=(idims-1)*2+iside
1426 call fixdivb_boundary(ixg^
ll,ixo^
l,psb(igrid)%w,psb(igrid)%x,ib)
1431 end subroutine mf_boundary_adjust
1433 subroutine fixdivb_boundary(ixG^L,ixO^L,w,x,iB)
1436 integer,
intent(in) :: ixg^
l,ixo^
l,ib
1437 double precision,
intent(inout) :: w(ixg^s,1:nw)
1438 double precision,
intent(in) :: x(ixg^s,1:
ndim)
1440 double precision :: dx1x2,dx1x3,dx2x1,dx2x3,dx3x1,dx3x2
1441 integer :: ix^
d,ixf^
l
1453 do ix1=ixfmax1,ixfmin1,-1
1454 w(ix1-1,ixfmin2:ixfmax2,mag(1))=w(ix1+1,ixfmin2:ixfmax2,mag(1)) &
1455 +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
1456 w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
1459 do ix1=ixfmax1,ixfmin1,-1
1460 w(ix1-1,ixfmin2:ixfmax2,mag(1))=( (w(ix1+1,ixfmin2:ixfmax2,mag(1))+&
1461 w(ix1,ixfmin2:ixfmax2,mag(1)))*
block%surfaceC(ix1,ixfmin2:ixfmax2,1)&
1462 +(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
1463 block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
1464 -(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
1465 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
1466 /
block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
1480 do ix1=ixfmax1,ixfmin1,-1
1481 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1482 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
1483 +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
1484 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
1485 +dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
1486 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
1489 do ix1=ixfmax1,ixfmin1,-1
1490 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1491 ( (w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
1492 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
1493 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
1494 +(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
1495 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
1496 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
1497 -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
1498 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
1499 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
1500 +(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
1501 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
1502 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
1503 -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
1504 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1505 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
1506 /
block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
1507 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
1519 do ix1=ixfmin1,ixfmax1
1520 w(ix1+1,ixfmin2:ixfmax2,mag(1))=w(ix1-1,ixfmin2:ixfmax2,mag(1)) &
1521 -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
1522 w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
1525 do ix1=ixfmin1,ixfmax1
1526 w(ix1+1,ixfmin2:ixfmax2,mag(1))=( (w(ix1-1,ixfmin2:ixfmax2,mag(1))+&
1527 w(ix1,ixfmin2:ixfmax2,mag(1)))*
block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)&
1528 -(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
1529 block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
1530 +(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
1531 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
1532 /
block%surfaceC(ix1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
1546 do ix1=ixfmin1,ixfmax1
1547 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1548 w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
1549 -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
1550 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
1551 -dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
1552 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
1555 do ix1=ixfmin1,ixfmax1
1556 w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
1557 ( (w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
1558 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
1559 block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
1560 -(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
1561 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
1562 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
1563 +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
1564 w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
1565 block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
1566 -(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
1567 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
1568 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
1569 +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
1570 w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1571 block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
1572 /
block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
1573 w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
1585 do ix2=ixfmax2,ixfmin2,-1
1586 w(ixfmin1:ixfmax1,ix2-1,mag(2))=w(ixfmin1:ixfmax1,ix2+1,mag(2)) &
1587 +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
1588 w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
1591 do ix2=ixfmax2,ixfmin2,-1
1592 w(ixfmin1:ixfmax1,ix2-1,mag(2))=( (w(ixfmin1:ixfmax1,ix2+1,mag(2))+&
1593 w(ixfmin1:ixfmax1,ix2,mag(2)))*
block%surfaceC(ixfmin1:ixfmax1,ix2,2)&
1594 +(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
1595 block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
1596 -(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
1597 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
1598 /
block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
1612 do ix2=ixfmax2,ixfmin2,-1
1613 w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
1614 ix2+1,ixfmin3:ixfmax3,mag(2)) &
1615 +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
1616 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
1617 +dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
1618 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
1621 do ix2=ixfmax2,ixfmin2,-1
1622 w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=&
1623 ( (w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))+&
1624 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
1625 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)&
1626 +(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
1627 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1628 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
1629 -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
1630 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1631 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
1632 +(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
1633 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
1634 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
1635 -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
1636 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1637 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
1638 /
block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)-&
1639 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
1651 do ix2=ixfmin2,ixfmax2
1652 w(ixfmin1:ixfmax1,ix2+1,mag(2))=w(ixfmin1:ixfmax1,ix2-1,mag(2)) &
1653 -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
1654 w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
1657 do ix2=ixfmin2,ixfmax2
1658 w(ixfmin1:ixfmax1,ix2+1,mag(2))=( (w(ixfmin1:ixfmax1,ix2-1,mag(2))+&
1659 w(ixfmin1:ixfmax1,ix2,mag(2)))*
block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)&
1660 -(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
1661 block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
1662 +(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
1663 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
1664 /
block%surfaceC(ixfmin1:ixfmax1,ix2,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
1678 do ix2=ixfmin2,ixfmax2
1679 w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
1680 ix2-1,ixfmin3:ixfmax3,mag(2)) &
1681 -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
1682 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
1683 -dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
1684 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
1687 do ix2=ixfmin2,ixfmax2
1688 w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=&
1689 ( (w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))+&
1690 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
1691 block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)&
1692 -(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
1693 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1694 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
1695 +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
1696 w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
1697 block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
1698 -(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
1699 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
1700 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
1701 +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
1702 w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
1703 block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
1704 /
block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)-&
1705 w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
1720 do ix3=ixfmax3,ixfmin3,-1
1721 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=w(ixfmin1:ixfmax1,&
1722 ixfmin2:ixfmax2,ix3+1,mag(3)) &
1723 +dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
1724 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
1725 +dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
1726 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
1729 do ix3=ixfmax3,ixfmin3,-1
1730 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=&
1731 ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))+&
1732 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
1733 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)&
1734 +(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
1735 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1736 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
1737 -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
1738 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1739 block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
1740 +(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
1741 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
1742 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
1743 -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
1744 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
1745 block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
1746 /
block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)-&
1747 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
1760 do ix3=ixfmin3,ixfmax3
1761 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=w(ixfmin1:ixfmax1,&
1762 ixfmin2:ixfmax2,ix3-1,mag(3)) &
1763 -dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
1764 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
1765 -dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
1766 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
1769 do ix3=ixfmin3,ixfmax3
1770 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=&
1771 ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))+&
1772 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
1773 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)&
1774 -(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
1775 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1776 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
1777 +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
1778 w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
1779 block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
1780 -(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
1781 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
1782 block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
1783 +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
1784 w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
1785 block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
1786 /
block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)-&
1787 w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
1792 call mpistop(
"Special boundary is not defined for this region")
1795 end subroutine fixdivb_boundary
1804 double precision,
intent(in) :: qdt
1805 double precision,
intent(in) :: qt
1806 logical,
intent(inout) :: active
1808 double precision :: tmp(ixg^t), grad(ixg^t,
ndim)
1809 double precision :: res
1810 double precision,
parameter :: max_residual = 1
d-3
1811 double precision,
parameter :: residual_reduction = 1
d-10
1813 integer,
parameter :: max_its = 50
1814 double precision :: residual_it(max_its), max_divb
1815 integer :: iigrid, igrid
1816 integer :: n, nc, lvl, ix^
l, ixc^
l, idim
1819 mg%operator_type = mg_laplacian
1827 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1828 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1831 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
1832 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1834 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1835 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1838 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
1839 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1843 write(*,*)
"mf_clean_divb_multigrid warning: unknown boundary type"
1844 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
1845 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
1853 do iigrid = 1, igridstail
1854 igrid = igrids(iigrid);
1857 lvl =
mg%boxes(id)%lvl
1858 nc =
mg%box_size_lvl(lvl)
1864 call get_divb(ps(igrid)%w(ixg^t, 1:nw), ixg^
ll,
ixm^
ll, tmp, &
1866 mg%boxes(id)%cc({1:nc}, mg_irhs) = tmp(
ixm^t)
1867 max_divb = max(max_divb, maxval(abs(tmp(
ixm^t))))
1872 call mpi_allreduce(mpi_in_place, max_divb, 1, mpi_double_precision, &
1875 if (
mype == 0) print *,
"Performing multigrid divB cleaning"
1876 if (
mype == 0) print *,
"iteration vs residual"
1879 call mg_fas_fmg(
mg, n>1, max_res=residual_it(n))
1880 if (
mype == 0)
write(*,
"(I4,E11.3)") n, residual_it(n)
1881 if (residual_it(n) < residual_reduction * max_divb)
exit
1883 if (
mype == 0 .and. n > max_its)
then
1884 print *,
"divb_multigrid warning: not fully converged"
1885 print *,
"current amplitude of divb: ", residual_it(max_its)
1886 print *,
"multigrid smallest grid: ", &
1887 mg%domain_size_lvl(:,
mg%lowest_lvl)
1888 print *,
"note: smallest grid ideally has <= 8 cells"
1889 print *,
"multigrid dx/dy/dz ratio: ",
mg%dr(:, 1)/
mg%dr(1, 1)
1890 print *,
"note: dx/dy/dz should be similar"
1894 call mg_fas_vcycle(
mg, max_res=res)
1895 if (res < max_residual)
exit
1897 if (res > max_residual)
call mpistop(
"divb_multigrid: no convergence")
1902 do iigrid = 1, igridstail
1903 igrid = igrids(iigrid);
1912 tmp(ix^s) =
mg%boxes(id)%cc({:,}, mg_iphi)
1916 ixcmin^
d=ixmlo^
d-
kr(idim,^
d);
1918 call gradientf(tmp,ps(igrid)%x,ixg^
ll,ixc^
l,idim,grad(ixg^t,idim))
1919 ps(igrid)%ws(ixc^s,idim)=ps(igrid)%ws(ixc^s,idim)-grad(ixc^s,idim)
1927 ps(igrid)%w(
ixm^t, mag(1:
ndim)) = &
1928 ps(igrid)%w(
ixm^t, mag(1:
ndim)) - grad(
ixm^t, :)
1939 subroutine mf_update_faces_average(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
1943 integer,
intent(in) :: ixi^
l, ixo^
l
1944 double precision,
intent(in) :: qt, qdt
1946 double precision,
intent(in) :: wp(ixi^s,1:nw)
1947 type(state) :: sct, s
1948 type(ct_velocity) :: vcts
1949 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
1950 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
1952 double precision :: circ(ixi^s,1:
ndim)
1953 double precision :: e_resi(ixi^s,
sdim:3)
1954 integer :: ix^
d,ixc^
l,ixa^
l,i1kr^
d,i2kr^
d
1955 integer :: idim1,idim2,idir,iwdim1,iwdim2
1957 associate(bfaces=>s%ws,x=>s%x)
1964 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,e_resi)
1968 i1kr^
d=
kr(idim1,^
d);
1971 i2kr^
d=
kr(idim2,^
d);
1974 if (
lvc(idim1,idim2,idir)==1)
then
1976 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
1978 {
do ix^db=ixcmin^db,ixcmax^db\}
1979 fe(ix^
d,idir)=quarter*&
1980 (fc(ix^
d,iwdim1,idim2)+fc({ix^
d+i1kr^
d},iwdim1,idim2)&
1981 -fc(ix^
d,iwdim2,idim1)-fc({ix^
d+i2kr^
d},iwdim2,idim1))
1983 if(
mf_eta/=zero) fe(ix^
d,idir)=fe(ix^
d,idir)+e_resi(ix^
d,idir)
1986 fe(ix^
d,idir)=fe(ix^
d,idir)*qdt*s%dsC(ix^
d,idir)
1994 if(
associated(usr_set_electric_field)) &
1995 call usr_set_electric_field(ixi^l,ixo^l,qt,qdt,fe,sct)
1997 circ(ixi^s,1:ndim)=zero
2003 ixcmin^d=ixomin^d-kr(idim1,^d);
2005 ixa^l=ixc^l-kr(idim2,^d);
2008 if(lvc(idim1,idim2,idir)==1)
then
2010 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2013 else if(lvc(idim1,idim2,idir)==-1)
then
2015 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2022 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2024 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2029 end subroutine mf_update_faces_average
2032 subroutine mf_update_faces_contact(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
2036 integer,
intent(in) :: ixi^
l, ixo^
l
2037 double precision,
intent(in) :: qt, qdt
2039 double precision,
intent(in) :: wp(ixi^s,1:nw)
2040 type(state) :: sct, s
2041 type(ct_velocity) :: vcts
2042 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
2043 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
2045 double precision :: circ(ixi^s,1:
ndim)
2047 double precision :: ecc(ixi^s,
sdim:3)
2049 double precision :: el(ixi^s),er(ixi^s)
2051 double precision :: elc(ixi^s),erc(ixi^s)
2053 double precision :: jce(ixi^s,
sdim:3)
2054 integer :: hxc^
l,ixc^
l,jxc^
l,ixa^
l,ixb^
l
2055 integer :: idim1,idim2,idir,iwdim1,iwdim2
2057 associate(bfaces=>s%ws,x=>s%x,w=>s%w,vnorm=>vcts%vnorm)
2062 if(
lvc(idim1,idim2,idir)==1)
then
2063 ecc(ixi^s,idir)=ecc(ixi^s,idir)+wp(ixi^s,mag(idim1))*wp(ixi^s,
mom(idim2))
2064 else if(
lvc(idim1,idim2,idir)==-1)
then
2065 ecc(ixi^s,idir)=ecc(ixi^s,idir)-wp(ixi^s,mag(idim1))*wp(ixi^s,
mom(idim2))
2070 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,jce)
2082 if (
lvc(idim1,idim2,idir)==1)
then
2084 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
2086 jxc^
l=ixc^
l+
kr(idim1,^
d);
2087 hxc^
l=ixc^
l+
kr(idim2,^
d);
2089 fe(ixc^s,idir)=quarter*&
2090 (fc(ixc^s,iwdim1,idim2)+fc(jxc^s,iwdim1,idim2)&
2091 -fc(ixc^s,iwdim2,idim1)-fc(hxc^s,iwdim2,idim1))
2095 ixamax^
d=ixcmax^
d+
kr(idim1,^
d);
2096 el(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(ixa^s,idir)
2097 hxc^
l=ixa^
l+
kr(idim2,^
d);
2098 er(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(hxc^s,idir)
2099 where(vnorm(ixc^s,idim1)>0.d0)
2100 elc(ixc^s)=el(ixc^s)
2101 else where(vnorm(ixc^s,idim1)<0.d0)
2102 elc(ixc^s)=el(jxc^s)
2104 elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
2106 hxc^
l=ixc^
l+
kr(idim2,^
d);
2107 where(vnorm(hxc^s,idim1)>0.d0)
2108 erc(ixc^s)=er(ixc^s)
2109 else where(vnorm(hxc^s,idim1)<0.d0)
2110 erc(ixc^s)=er(jxc^s)
2112 erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
2114 fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
2117 jxc^
l=ixc^
l+
kr(idim2,^
d);
2119 ixamax^
d=ixcmax^
d+
kr(idim2,^
d);
2120 el(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(ixa^s,idir)
2121 hxc^
l=ixa^
l+
kr(idim1,^
d);
2122 er(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(hxc^s,idir)
2123 where(vnorm(ixc^s,idim2)>0.d0)
2124 elc(ixc^s)=el(ixc^s)
2125 else where(vnorm(ixc^s,idim2)<0.d0)
2126 elc(ixc^s)=el(jxc^s)
2128 elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
2130 hxc^
l=ixc^
l+
kr(idim1,^
d);
2131 where(vnorm(hxc^s,idim2)>0.d0)
2132 erc(ixc^s)=er(ixc^s)
2133 else where(vnorm(hxc^s,idim2)<0.d0)
2134 erc(ixc^s)=er(jxc^s)
2136 erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
2138 fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
2141 if(
mf_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+jce(ixc^s,idir)
2145 fe(ixc^s,idir)=fe(ixc^s,idir)*qdt*s%dsC(ixc^s,idir)
2160 circ(ixi^s,1:
ndim)=zero
2165 ixcmin^
d=ixomin^
d-
kr(idim1,^
d);
2169 if(
lvc(idim1,idim2,idir)/=0)
then
2170 hxc^
l=ixc^
l-
kr(idim2,^
d);
2172 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2173 +
lvc(idim1,idim2,idir)&
2180 where(s%surfaceC(ixc^s,idim1) > 1.0
d-9*s%dvolume(ixc^s))
2181 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2183 circ(ixc^s,idim1)=zero
2186 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2191 end subroutine mf_update_faces_contact
2194 subroutine mf_update_faces_hll(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
2199 integer,
intent(in) :: ixi^
l, ixo^
l
2200 double precision,
intent(in) :: qt, qdt
2202 double precision,
intent(in) :: wp(ixi^s,1:nw)
2203 type(state) :: sct, s
2204 type(ct_velocity) :: vcts
2205 double precision,
intent(in) :: fc(ixi^s,1:nwflux,1:
ndim)
2206 double precision,
intent(inout) :: fe(ixi^s,
sdim:3)
2208 double precision :: vtill(ixi^s,2)
2209 double precision :: vtilr(ixi^s,2)
2210 double precision :: btill(ixi^s,
ndim)
2211 double precision :: btilr(ixi^s,
ndim)
2212 double precision :: cp(ixi^s,2)
2213 double precision :: cm(ixi^s,2)
2214 double precision :: circ(ixi^s,1:
ndim)
2216 double precision :: jce(ixi^s,
sdim:3)
2217 integer :: hxc^
l,ixc^
l,ixcp^
l,jxc^
l,ixcm^
l
2218 integer :: idim1,idim2,idir
2220 associate(bfaces=>s%ws,bfacesct=>sct%ws,x=>s%x,vbarc=>vcts%vbarC,cbarmin=>vcts%cbarmin,&
2221 cbarmax=>vcts%cbarmax)
2234 if(
mf_eta/=zero)
call get_resistive_electric_field(ixi^
l,ixo^
l,sct,s,jce)
2247 ixcmin^
d=ixomin^
d-1+
kr(idir,^
d);
2251 idim2=mod(idir+1,3)+1
2253 jxc^
l=ixc^
l+
kr(idim1,^
d);
2254 ixcp^
l=ixc^
l+
kr(idim2,^
d);
2258 vtill(ixi^s,2),vtilr(ixi^s,2))
2261 vtill(ixi^s,1),vtilr(ixi^s,1))
2267 btill(ixi^s,idim1),btilr(ixi^s,idim1))
2270 btill(ixi^s,idim2),btilr(ixi^s,idim2))
2274 cm(ixc^s,1)=max(cbarmin(ixcp^s,idim1),cbarmin(ixc^s,idim1))
2275 cp(ixc^s,1)=max(cbarmax(ixcp^s,idim1),cbarmax(ixc^s,idim1))
2277 cm(ixc^s,2)=max(cbarmin(jxc^s,idim2),cbarmin(ixc^s,idim2))
2278 cp(ixc^s,2)=max(cbarmax(jxc^s,idim2),cbarmax(ixc^s,idim2))
2282 fe(ixc^s,idir)=-(cp(ixc^s,1)*vtill(ixc^s,1)*btill(ixc^s,idim2) &
2283 + cm(ixc^s,1)*vtilr(ixc^s,1)*btilr(ixc^s,idim2) &
2284 - cp(ixc^s,1)*cm(ixc^s,1)*(btilr(ixc^s,idim2)-btill(ixc^s,idim2)))&
2285 /(cp(ixc^s,1)+cm(ixc^s,1)) &
2286 +(cp(ixc^s,2)*vtill(ixc^s,2)*btill(ixc^s,idim1) &
2287 + cm(ixc^s,2)*vtilr(ixc^s,2)*btilr(ixc^s,idim1) &
2288 - cp(ixc^s,2)*cm(ixc^s,2)*(btilr(ixc^s,idim1)-btill(ixc^s,idim1)))&
2289 /(cp(ixc^s,2)+cm(ixc^s,2))
2292 if(
mf_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+jce(ixc^s,idir)
2296 fe(ixc^s,idir)=qdt*s%dsC(ixc^s,idir)*fe(ixc^s,idir)
2310 circ(ixi^s,1:
ndim)=zero
2316 ixcmin^
d=ixomin^
d-
kr(idim1,^
d);
2320 if(
lvc(idim1,idim2,idir)/=0)
then
2321 hxc^
l=ixc^
l-
kr(idim2,^
d);
2323 circ(ixc^s,idim1)=circ(ixc^s,idim1)&
2324 +
lvc(idim1,idim2,idir)&
2331 where(s%surfaceC(ixc^s,idim1) > 1.0
d-9*s%dvolume(ixc^s))
2332 circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
2334 circ(ixc^s,idim1)=zero
2337 bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
2341 end subroutine mf_update_faces_hll
2344 subroutine get_resistive_electric_field(ixI^L,ixO^L,sCT,s,jce)
2349 integer,
intent(in) :: ixi^
l, ixo^
l
2350 type(state),
intent(in) :: sct, s
2352 double precision :: jce(ixi^s,
sdim:3)
2355 double precision :: jcc(ixi^s,7-2*
ndir:3)
2357 double precision :: xs(ixgs^t,1:
ndim)
2359 double precision :: eta(ixi^s)
2360 double precision :: gradi(ixgs^t)
2361 integer :: ix^
d,ixc^
l,ixa^
l,ixb^
l,idir,idirmin,idim1,idim2
2363 associate(x=>s%x,
dx=>s%dx,w=>s%w,wct=>sct%w,wcts=>sct%ws)
2369 if (
lvc(idim1,idim2,idir)==0) cycle
2370 ixcmax^
d=ixomax^
d+1;
2371 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-2;
2372 ixbmax^
d=ixcmax^
d-
kr(idir,^
d)+1;
2375 xs(ixb^s,:)=x(ixb^s,:)
2376 xs(ixb^s,idim2)=x(ixb^s,idim2)+half*
dx(ixb^s,idim2)
2377 call gradientf(wcts(ixgs^t,idim2),xs,ixgs^
ll,ixc^
l,idim1,gradi)
2378 if (
lvc(idim1,idim2,idir)==1)
then
2379 jce(ixc^s,idir)=jce(ixc^s,idir)+gradi(ixc^s)
2381 jce(ixc^s,idir)=jce(ixc^s,idir)-gradi(ixc^s)
2388 jce(ixi^s,:)=jce(ixi^s,:)*
mf_eta
2396 ixcmin^
d=ixomin^
d+
kr(idir,^
d)-1;
2397 jcc(ixc^s,idir)=0.d0
2399 if({ ix^
d==1 .and. ^
d==idir | .or.}) cycle
2400 ixamin^
d=ixcmin^
d+ix^
d;
2401 ixamax^
d=ixcmax^
d+ix^
d;
2402 jcc(ixc^s,idir)=jcc(ixc^s,idir)+eta(ixa^s)
2404 jcc(ixc^s,idir)=jcc(ixc^s,idir)*0.25d0
2405 jce(ixc^s,idir)=jce(ixc^s,idir)*jcc(ixc^s,idir)
2410 end subroutine get_resistive_electric_field
2416 integer,
intent(in) :: ixo^
l
2423 do ix^db=ixomin^db,ixomax^db\}
2425 s%w(ix^
d,mag(1))=half/s%surface(ix^
d,1)*(s%ws(ix^
d,1)*s%surfaceC(ix^
d,1)&
2426 +s%ws(ix1-1,ix2,ix3,1)*s%surfaceC(ix1-1,ix2,ix3,1))
2427 s%w(ix^
d,mag(2))=half/s%surface(ix^
d,2)*(s%ws(ix^
d,2)*s%surfaceC(ix^
d,2)&
2428 +s%ws(ix1,ix2-1,ix3,2)*s%surfaceC(ix1,ix2-1,ix3,2))
2429 s%w(ix^
d,mag(3))=half/s%surface(ix^
d,3)*(s%ws(ix^
d,3)*s%surfaceC(ix^
d,3)&
2430 +s%ws(ix1,ix2,ix3-1,3)*s%surfaceC(ix1,ix2,ix3-1,3))
2433 s%w(ix^
d,mag(1))=half/s%surface(ix^
d,1)*(s%ws(ix^
d,1)*s%surfaceC(ix^
d,1)&
2434 +s%ws(ix1-1,ix2,1)*s%surfaceC(ix1-1,ix2,1))
2435 s%w(ix^
d,mag(2))=half/s%surface(ix^
d,2)*(s%ws(ix^
d,2)*s%surfaceC(ix^
d,2)&
2436 +s%ws(ix1,ix2-1,2)*s%surfaceC(ix1,ix2-1,2))
2479 integer,
intent(in) :: ixis^
l, ixi^
l, ixo^
l
2480 double precision,
intent(inout) :: ws(ixis^s,1:nws)
2481 double precision,
intent(in) :: x(ixi^s,1:
ndim)
2483 double precision :: adummy(ixis^s,1:3)
2492 double precision :: sum_jbb_ipe, sum_j_ipe, sum_l_ipe, f_i_ipe, volume_pe
2493 double precision :: sum_jbb, sum_j, sum_l, f_i, volume, cw_sin_theta
2494 integer :: iigrid, igrid, ix^
d
2495 integer :: amode, istatus(mpi_status_size)
2496 integer,
save :: fhmf
2497 logical :: patchwi(ixg^t)
2498 logical,
save :: logmfopened=.false.
2499 character(len=800) :: filename,filehead
2500 character(len=800) :: line,datastr
2507 do iigrid=1,igridstail; igrid=igrids(iigrid);
2510 call mask_inner(ixg^
ll,
ixm^
ll,ps(igrid)%w,ps(igrid)%x,patchwi,volume_pe)
2511 sum_jbb_ipe = sum_jbb_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2512 ps(igrid)%x,1,patchwi)
2513 sum_j_ipe = sum_j_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2514 ps(igrid)%x,2,patchwi)
2515 f_i_ipe=f_i_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2516 ps(igrid)%x,3,patchwi)
2517 sum_l_ipe = sum_l_ipe+integral_grid_mf(ixg^
ll,
ixm^
ll,ps(igrid)%w,&
2518 ps(igrid)%x,4,patchwi)
2520 call mpi_reduce(sum_jbb_ipe,sum_jbb,1,mpi_double_precision,&
2522 call mpi_reduce(sum_j_ipe,sum_j,1,mpi_double_precision,mpi_sum,0,&
2524 call mpi_reduce(f_i_ipe,f_i,1,mpi_double_precision,mpi_sum,0,&
2526 call mpi_reduce(sum_l_ipe,sum_l,1,mpi_double_precision,mpi_sum,0,&
2528 call mpi_reduce(volume_pe,volume,1,mpi_double_precision,mpi_sum,0,&
2534 cw_sin_theta = sum_jbb/sum_j
2540 if(.not.logmfopened)
then
2542 write(filename,
"(a,a)") trim(
base_filename),
"_mf_metrics.csv"
2546 open(unit=20,file=trim(filename),status=
'replace')
2547 close(20, status=
'delete')
2550 amode=ior(mpi_mode_create,mpi_mode_wronly)
2551 amode=ior(amode,mpi_mode_append)
2552 call mpi_file_open(mpi_comm_self,filename,amode,mpi_info_null,fhmf,
ierrmpi)
2554 filehead=
" it, time, CW_sin_theta, current, Lorenz_force, f_i"
2556 call mpi_file_write(fhmf,filehead,len_trim(filehead), &
2557 mpi_character,istatus,
ierrmpi)
2558 call mpi_file_write(fhmf,achar(10),1,mpi_character,istatus,
ierrmpi)
2562 write(datastr,
'(i8,a)')
it,
','
2563 line=trim(line)//trim(datastr)
2565 line=trim(line)//trim(datastr)
2566 write(datastr,
'(es13.6,a)') cw_sin_theta,
','
2567 line=trim(line)//trim(datastr)
2568 write(datastr,
'(es13.6,a)') sum_j,
','
2569 line=trim(line)//trim(datastr)
2570 write(datastr,
'(es13.6,a)') sum_l,
','
2571 line=trim(line)//trim(datastr)
2572 write(datastr,
'(es13.6)') f_i
2573 line=trim(line)//trim(datastr)//new_line(
'A')
2574 call mpi_file_write(fhmf,line,len_trim(line),mpi_character,istatus,
ierrmpi)
2576 call mpi_file_close(fhmf,
ierrmpi)
2583 subroutine mask_inner(ixI^L,ixO^L,w,x,patchwi,volume_pe)
2586 integer,
intent(in) :: ixi^
l,ixo^
l
2587 double precision,
intent(in):: w(ixi^s,nw),x(ixi^s,1:
ndim)
2588 double precision,
intent(inout) :: volume_pe
2589 logical,
intent(out) :: patchwi(ixi^s)
2591 double precision :: xo^
l
2594 {xomin^
d = xprobmin^
d + 0.05d0*(xprobmax^
d-xprobmin^
d)\}
2595 {xomax^
d = xprobmax^
d - 0.05d0*(xprobmax^
d-xprobmin^
d)\}
2597 xomin^nd = xprobmin^nd
2602 {
do ix^db=ixomin^db,ixomax^db\}
2603 if({ x(ix^dd,^
d) > xomin^
d .and. x(ix^dd,^
d) < xomax^
d | .and. })
then
2604 patchwi(ix^
d)=.true.
2605 volume_pe=volume_pe+
block%dvolume(ix^
d)
2607 patchwi(ix^
d)=.false.
2611 end subroutine mask_inner
2613 function integral_grid_mf(ixI^L,ixO^L,w,x,iw,patchwi)
2616 integer,
intent(in) :: ixi^
l,ixo^
l,iw
2617 double precision,
intent(in) :: x(ixi^s,1:
ndim)
2618 double precision :: w(ixi^s,nw+
nwauxio)
2619 logical,
intent(in) :: patchwi(ixi^s)
2621 double precision,
dimension(ixI^S,7-2*ndir:3) :: current
2622 double precision,
dimension(ixI^S,1:ndir) :: bvec,qvec
2623 double precision :: integral_grid_mf,tmp(ixi^s),bm2
2624 integer :: ix^
d,idirmin0,idirmin,idir,jdir,kdir
2626 integral_grid_mf=0.d0
2630 bvec(ixo^s,:)=w(ixo^s,mag(:))
2633 qvec(ixo^s,1:
ndir)=zero
2634 do idir=1,
ndir;
do jdir=idirmin,3;
do kdir=1,
ndir
2635 if(
lvc(idir,jdir,kdir)/=0)
then
2636 if(
lvc(idir,jdir,kdir)==1)
then
2637 qvec(ixo^s,idir)=qvec(ixo^s,idir)+current(ixo^s,jdir)*bvec(ixo^s,kdir)
2639 qvec(ixo^s,idir)=qvec(ixo^s,idir)-current(ixo^s,jdir)*bvec(ixo^s,kdir)
2642 end do;
end do;
end do
2644 {
do ix^db=ixomin^db,ixomax^db\}
2645 if(patchwi(ix^d))
then
2646 bm2=sum(bvec(ix^d,:)**2)
2647 if(bm2/=0.d0) bm2=1.d0/bm2
2648 integral_grid_mf=integral_grid_mf+sqrt(sum(qvec(ix^d,:)**2)*&
2649 bm2)*block%dvolume(ix^d)
2655 {
do ix^db=ixomin^db,ixomax^db\}
2656 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+sqrt(sum(current(ix^d,:)**2))*&
2663 {
do ix^db=ixomin^db,ixomax^db\}
2664 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+tmp(ix^d)*block%dvolume(ix^d)
2668 bvec(ixo^s,:)=w(ixo^s,mag(:))
2671 qvec(ixo^s,1:ndir)=zero
2672 do idir=1,ndir;
do jdir=idirmin,3;
do kdir=1,ndir
2673 if(lvc(idir,jdir,kdir)/=0)
then
2674 if(lvc(idir,jdir,kdir)==1)
then
2675 qvec(ixo^s,idir)=qvec(ixo^s,idir)+current(ixo^s,jdir)*bvec(ixo^s,kdir)
2677 qvec(ixo^s,idir)=qvec(ixo^s,idir)-current(ixo^s,jdir)*bvec(ixo^s,kdir)
2680 end do;
end do;
end do
2682 {
do ix^db=ixomin^db,ixomax^db\}
2683 if(patchwi(ix^d)) integral_grid_mf=integral_grid_mf+&
2684 sqrt(sum(qvec(ix^d,:)**2))*block%dvolume(ix^d)
2688 end function integral_grid_mf
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
subroutine reconstruct(ixil, ixcl, idir, q, ql, qr)
Reconstruct scalar q within ixO^L to 1/2 dx in direction idir Return both left and right reconstructe...
subroutine b_from_vector_potentiala(ixisl, ixil, ixol, ws, x, a)
calculate magnetic field from vector potential A at cell edges
Module with basic grid data structures.
type(tree_node_ptr), dimension(:,:), allocatable, save igrid_to_node
Array to go from an [igrid, ipe] index to a node pointer.
subroutine, public get_divb(w, ixil, ixol, divb, nth_in)
Calculate div B within ixO.
integer, dimension(:), allocatable, public mag
Indices of the magnetic field.
Module with geometry-related routines (e.g., divergence, curl)
integer, parameter cylindrical
subroutine curlvector(qvec, ixil, ixol, curlvec, idirmin, idirmin0, ndir0, fourthorder)
Calculate curl of a vector qvec within ixL Options to employ standard second order CD evaluations use...
subroutine gradient(q, ixil, ixol, idir, gradq, nth_in)
subroutine gradientf(q, x, ixil, ixol, idir, gradq, nth_in, pm_in)
subroutine gradientl(q, ixil, ixol, idir, gradq)
update ghost cells of all blocks including physical boundaries
integer, dimension(0:3^d &), target type_recv_p_p1
integer, dimension( :^d &), pointer type_recv_r
integer, dimension(-1:1^d &), target type_send_srl_p1
subroutine getbc(time, qdt, psb, nwstart, nwbc)
do update ghost cells of all blocks including physical boundaries
integer, dimension(0:3^d &), target type_send_p_f
integer, dimension( :^d &), pointer type_send_p
integer, dimension( :^d &), pointer type_send_srl
integer, dimension(-1:1^d &), target type_send_r_p1
subroutine create_bc_mpi_datatype(nwstart, nwbc)
integer, dimension(0:3^d &), target type_recv_r_f
integer, dimension(-1:1^d &), target type_recv_srl_f
integer, dimension(-1:1^d &), target type_send_r_f
integer, dimension(-1:1^d &), target type_send_srl_f
integer, dimension(0:3^d &), target type_send_p_p1
integer, dimension( :^d &), pointer type_send_r
integer, dimension(0:3^d &), target type_recv_r_p1
integer, dimension( :^d &), pointer type_recv_p
integer, dimension(-1:1^d &), target type_recv_srl_p1
integer, dimension(0:3^d &), target type_recv_p_f
integer, dimension( :^d &), pointer type_recv_srl
This module contains definitions of global parameters and variables and some generic functions/subrou...
type(state), pointer block
Block pointer for using one block and its previous state.
double precision dtdiffpar
For resistive MHD, the time step is also limited by the diffusion time: .
character(len=std_len) typegrad
double precision unit_charge
Physical scaling factor for charge.
integer ixghi
Upper index of grid block arrays.
integer, dimension(3, 3, 3) lvc
Levi-Civita tensor.
double precision unit_time
Physical scaling factor for time.
double precision unit_density
Physical scaling factor for density.
integer, parameter unitpar
file handle for IO
integer, parameter bc_asymm
double precision global_time
The global simulation time.
double precision unit_mass
Physical scaling factor for mass.
integer, dimension(3, 3) kr
Kronecker delta tensor.
integer it
Number of time steps taken.
integer, dimension(:, :), allocatable typeboundary
Array indicating the type of boundary condition per variable and per physical boundary.
double precision unit_numberdensity
Physical scaling factor for number density.
double precision unit_pressure
Physical scaling factor for pressure.
integer, parameter ndim
Number of spatial dimensions for grid variables.
double precision unit_length
Physical scaling factor for length.
logical stagger_grid
True for using stagger grid.
double precision cmax_global
global fastest wave speed needed in fd scheme and glm method
logical use_particles
Use particles module or not.
character(len=std_len), dimension(:), allocatable par_files
Which par files are used as input.
integer icomm
The MPI communicator.
double precision bdip
amplitude of background dipolar, quadrupolar, octupolar, user's field
integer mype
The rank of the current MPI task.
double precision, dimension(:), allocatable, parameter d
integer ndir
Number of spatial dimensions (components) for vector variables.
integer ixm
the mesh range of a physical block without ghost cells
integer ierrmpi
A global MPI error return code.
logical slab
Cartesian geometry or not.
integer, parameter bc_periodic
integer, parameter bc_special
boundary condition types
double precision unit_magneticfield
Physical scaling factor for magnetic field.
integer nwauxio
Number of auxiliary variables that are only included in output.
double precision unit_velocity
Physical scaling factor for velocity.
logical time_advance
do time evolving
character(len=std_len) restart_from_file
If not 'unavailable', resume from snapshot with this base file name.
double precision c_norm
Normalised speed of light.
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
double precision unit_temperature
Physical scaling factor for temperature.
integer, parameter bc_cont
logical si_unit
Use SI units (.true.) or use cgs units (.false.)
double precision, dimension(:,:), allocatable dx
spatial steps for all dimensions at all levels
integer nghostcells
Number of ghost cells surrounding a grid.
integer, parameter sdim
starting dimension for electric field
integer, parameter bc_symm
character(len= *), parameter undefined
logical need_global_cmax
need global maximal wave speed
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
logical use_multigrid
Use multigrid (only available in 2D and 3D)
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
character(len=std_len) base_filename
Base file name for simulation output, which will be followed by a number.
integer max_blocks
The maximum number of grid blocks in a processor.
integer r_
Indices for cylindrical coordinates FOR TESTS, negative value when not used:
logical record_electric_field
True for record electric field.
integer, parameter ixglo
Lower index of grid block arrays (always 1)
integer, public, protected b
double precision, public mf_nu
viscosity coefficient in s cm^-2 for solar corona (Cheung 2012 ApJ)
subroutine, public mf_phys_init()
integer, public, protected mf_divb_nth
Whether divB is computed with a fourth order approximation.
subroutine, public b_from_vector_potential(ixisl, ixil, ixol, ws, x)
calculate magnetic field from vector potential
logical, public, protected mf_record_electric_field
set to true if need to record electric field on cell edges
logical, public, protected clean_initial_divb
clean divb in the initial condition
logical, public divbwave
Add divB wave in Roe solver.
subroutine, public mf_face_to_center(ixol, s)
calculate cell-center values from face-center values
double precision, public mf_vmax
maximal limit of magnetofrictional velocity in cm s^-1 (Pomoell 2019 A&A)
logical, public, protected mf_glm
Whether GLM-MHD is used.
double precision, public mf_eta_hyper
The hyper-resistivity.
double precision, public mf_glm_alpha
GLM-MHD parameter: ratio of the diffusive and advective time scales for div b taking values within [0...
integer, public, protected c
Indices of the momentum density for the form of better vectorization.
integer, public, protected c_
logical, dimension(2 *^nd), public, protected boundary_divbfix
To control divB=0 fix for boundary.
character(len=std_len), public, protected type_ct
Method type of constrained transport.
character(len=std_len), public, protected typedivbfix
Method type to clean divergence of B.
subroutine, public get_normalized_divb(w, ixil, ixol, divb)
get dimensionless div B = |divB| * volume / area / |B|
integer, dimension(2 *^nd), public, protected boundary_divbfix_skip
To skip * layer of ghost cells during divB=0 fix for boundary.
double precision, dimension(2 *^nd), public mf_decay_scale
decay scale of frictional velocity near boundaries
subroutine, public record_force_free_metrics()
subroutine, public mf_to_conserved(ixil, ixol, w, x)
Transform primitive variables into conservative ones.
subroutine, public get_current(w, ixil, ixol, idirmin, current, fourthorder)
Calculate idirmin and the idirmin:3 components of the common current array make sure that dxlevel(^D)...
integer, public, protected psi_
Indices of the GLM psi.
integer, dimension(:), allocatable, public, protected mom
Indices of the momentum density.
subroutine, public mf_clean_divb_multigrid(qdt, qt, active)
logical, public, protected mf_particles
Whether particles module is added.
integer, public, protected m
subroutine, public mf_to_primitive(ixil, ixol, w, x)
Transform conservative variables into primitive ones.
double precision, public mf_eta
The resistivity.
logical, public, protected source_split_divb
Whether divB cleaning sources are added splitting from fluid solver.
double precision, public, protected he_abundance
Helium abundance over Hydrogen.
Module to couple the octree-mg library to AMRVAC. This file uses the VACPP preprocessor,...
type(mg_t) mg
Data structure containing the multigrid tree.
Module containing all the particle routines.
subroutine particles_init()
Initialize particle data and parameters.
This module defines the procedures of a physics module. It contains function pointers for the various...
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.