MPI-AMRVAC  3.0
The MPI - Adaptive Mesh Refinement - Versatile Advection Code
mod_twofl_phys.t
Go to the documentation of this file.
1 !> Magneto-hydrodynamics module
3 
4 #include "amrvac.h"
5 
6  use mod_physics
7  use mod_global_parameters, only: std_len
11  implicit none
12  private
13  !! E_c = E_kin + E_mag + E_int
14  !! E_n = E_kin + E_int
15  integer, public, parameter :: eq_energy_tot=2
16  !! E_c = E_int
17  !! E_n = E_int
18  integer, public, parameter :: eq_energy_int=1
19  !! E_n, E_c are calculated from density as c_adiab rho^gamma
20  !! No energy equation => no variable assigned for it
21  integer, public, parameter :: eq_energy_none=0
22  !! E_c = E_kin + E_int
23  !! E_n = E_kin + E_int
24  integer, public, parameter :: eq_energy_ki=3
25  !! additional variable for the charges energy at index eaux_
26  !! E_c (index e_) = E_kin + E_mag + E_int, E_c (index eaux_) = E_int
27  !! E_n (index e_) = E_kin + E_int
28  integer, public, parameter :: eq_energy_tot2=4
29 
30  integer, public, protected :: twofl_eq_energy = eq_energy_tot
31 
32  !> Whether hyperdiffusivity is used
33  logical, public, protected :: twofl_hyperdiffusivity = .false.
34  logical, public, protected :: twofl_dump_hyperdiffusivity_coef = .false.
35  double precision, public, protected, allocatable :: c_shk(:)
36  double precision, public, protected, allocatable :: c_hyp(:)
37 
38  !> Whether thermal conduction is used
39  logical, public, protected :: twofl_thermal_conduction_c = .false.
40  !> type of TC used: 1: adapted module (mhd implementation), 2: adapted module (hd implementation)
41  integer, parameter, private :: mhd_tc =1
42  integer, parameter, private :: hd_tc =2
43  integer, protected :: use_twofl_tc_c = mhd_tc
44 
45  !> Whether radiative cooling is added
46  logical, public, protected :: twofl_radiative_cooling_c = .false.
47  type(rc_fluid), allocatable :: rc_fl_c
48 
49  !> Whether viscosity is added
50  logical, public, protected :: twofl_viscosity = .false.
51 
52  !> Whether gravity is added: common flag for charges and neutrals
53  logical, public, protected :: twofl_gravity = .false.
54 
55  !> whether dump full variables (when splitting is used) in a separate dat file
56  logical, public, protected :: twofl_dump_full_vars = .false.
57 
58  !> Whether Hall-MHD is used
59  logical, public, protected :: twofl_hall = .false.
60 
61  type(tc_fluid), public, allocatable :: tc_fl_c
62  type(te_fluid), public, allocatable :: te_fl_c
63 
64  type(tc_fluid), allocatable :: tc_fl_n
65  logical, public, protected :: twofl_thermal_conduction_n = .false.
66  logical, public, protected :: twofl_radiative_cooling_n = .false.
67  type(rc_fluid), allocatable :: rc_fl_n
68 
69  !> Whether TRAC method is used
70  logical, public, protected :: twofl_trac = .false.
71 
72  !> Whether GLM-MHD is used
73  logical, public, protected :: twofl_glm = .false.
74 
75  !> Which TRAC method is used
76  integer, public, protected :: twofl_trac_type=1
77 
78  !> Height of the mask used in the TRAC method
79  double precision, public, protected :: twofl_trac_mask = 0.d0
80 
81  !> Whether divB cleaning sources are added splitting from fluid solver
82  logical, public, protected :: source_split_divb = .false.
83 
84  !> GLM-MHD parameter: ratio of the diffusive and advective time scales for div b
85  !> taking values within [0, 1]
86  double precision, public :: twofl_glm_alpha = 0.5d0
87 
88  !> MHD fourth order
89  logical, public, protected :: twofl_4th_order = .false.
90 
91  !> Index of the density (in the w array)
92  integer, public :: rho_c_
93 
94  !> Indices of the momentum density
95  integer, allocatable, public :: mom_c(:)
96 
97  !> Index of the energy density (-1 if not present)
98  integer, public :: e_c_=-1
99 
100  !> Index of the cutoff temperature for the TRAC method
101  integer, public :: tcoff_c_
102  integer, public :: tweight_c_
103 
104  !> Indices of the GLM psi
105  integer, public, protected :: psi_
106 
107  !> Indices of auxiliary internal energy
108  integer, public :: eaux_c_
109 
110  !> Indices of the magnetic field
111  integer, allocatable, public :: mag(:)
112 
113  !> equi vars flags
114  logical, public :: has_equi_rho_c0 = .false.
115  logical, public :: has_equi_pe_c0 = .false.
116 
117  !> equi vars indices in the state%equi_vars array
118  integer, public :: equi_rho_c0_ = -1
119  integer, public :: equi_pe_c0_ = -1
120  logical, public :: twofl_equi_thermal_c = .false.
121 
122  !neutrals:
123 
124  integer, public :: rho_n_
125  integer, allocatable, public :: mom_n(:)
126  integer, public :: e_n_
127  integer, public :: tcoff_n_
128  integer, public :: tweight_n_
129  logical, public :: has_equi_rho_n0 = .false.
130  logical, public :: has_equi_pe_n0 = .false.
131  integer, public :: equi_rho_n0_ = -1
132  integer, public :: equi_pe_n0_ = -1
133 
134  ! related to collisions:
135  !> collisional alpha
136  double precision, public :: twofl_alpha_coll = 0d0
137  logical, public :: twofl_alpha_coll_constant = .true.
138  !> whether include thermal exchange collisional terms
139  logical, public :: twofl_coll_inc_te = .true.
140  !> whether include ionization/recombination inelastic collisional terms
141  logical, public :: twofl_coll_inc_ionrec = .false.
142  logical, public :: twofl_equi_thermal = .true.
143  logical, public :: twofl_equi_ionrec = .false.
144  logical, public :: twofl_equi_thermal_n = .false.
145  double precision, public :: dtcollpar = -1d0 !negative value does not impose restriction on the timestep
146  !> whether dump collisional terms in a separte dat file
147  logical, public, protected :: twofl_dump_coll_terms = .false.
148 
149  ! TODO Helium abundance not used, radiative cooling init uses it
150  ! not in parameters list anymore
151  double precision, public, protected :: he_abundance = 0d0
152  ! two fluid is only H plasma
153  double precision, public, protected :: rc = 2d0
154  double precision, public, protected :: rn = 1d0
155 
156  !> The adiabatic index
157  double precision, public :: twofl_gamma = 5.d0/3.0d0
158 
159  !> The adiabatic constant
160  double precision, public :: twofl_adiab = 1.0d0
161 
162  !> The MHD resistivity
163  double precision, public :: twofl_eta = 0.0d0
164 
165  !> The MHD hyper-resistivity
166  double precision, public :: twofl_eta_hyper = 0.0d0
167 
168  !> The MHD Hall coefficient
169  double precision, public :: twofl_etah = 0.0d0
170 
171  !> The small_est allowed energy
172  double precision, protected :: small_e
173 
174  !> Method type to clean divergence of B
175  character(len=std_len), public, protected :: typedivbfix = 'linde'
176 
177  !> Method type of constrained transport
178  character(len=std_len), public, protected :: type_ct = 'uct_contact'
179 
180  !> Whether divB is computed with a fourth order approximation
181  logical, public, protected :: twofl_divb_4thorder = .false.
182 
183  !> Method type in a integer for good performance
184  integer :: type_divb
185 
186  !> Coefficient of diffusive divB cleaning
187  double precision :: divbdiff = 0.8d0
188 
189  !> Update all equations due to divB cleaning
190  character(len=std_len) :: typedivbdiff = 'all'
191 
192  !> clean initial divB
193  logical, public :: clean_initial_divb = .false.
194 
195  !> Add divB wave in Roe solver
196  logical, public :: divbwave = .true.
197 
198  !> To control divB=0 fix for boundary
199  logical, public, protected :: boundary_divbfix(2*^nd)=.true.
200 
201  !> To skip * layer of ghost cells during divB=0 fix for boundary
202  integer, public, protected :: boundary_divbfix_skip(2*^nd)=0
203 
204  !> B0 field is force-free
205  logical, public, protected :: b0field_forcefree=.true.
206 
207  logical :: twofl_cbounds_species = .true.
208 
209  !> added from modules: gravity
210  !> source split or not
211  logical :: grav_split= .false.
212 
213  !> gamma minus one and its inverse
214  double precision :: gamma_1, inv_gamma_1
215 
216  ! DivB cleaning methods
217  integer, parameter :: divb_none = 0
218  integer, parameter :: divb_multigrid = -1
219  integer, parameter :: divb_glm = 1
220  integer, parameter :: divb_powel = 2
221  integer, parameter :: divb_janhunen = 3
222  integer, parameter :: divb_linde = 4
223  integer, parameter :: divb_lindejanhunen = 5
224  integer, parameter :: divb_lindepowel = 6
225  integer, parameter :: divb_lindeglm = 7
226  integer, parameter :: divb_ct = 8
227 
228  ! Public methods
229  public :: twofl_phys_init
230  public :: twofl_to_conserved
231  public :: twofl_to_primitive
232  public :: get_divb
233  public :: get_rhoc_tot
234  public :: twofl_get_v_c_idim
235  ! TODO needed for the roe, see if can be used for n
237  public :: get_rhon_tot
238  public :: get_alpha_coll_plasma
239  public :: get_gamma_ion_rec
240  public :: twofl_get_v_n_idim
241  public :: get_current
242  public :: twofl_get_pthermal_c
243  public :: twofl_face_to_center
244  public :: get_normalized_divb
245  public :: b_from_vector_potential
246  {^nooned
248  }
249 
250  abstract interface
251 
252  subroutine implicit_mult_factor_subroutine(ixI^L, ixO^L, step_dt, JJ, res)
253  integer, intent(in) :: ixi^l, ixo^l
254  double precision, intent(in) :: step_dt
255  double precision, intent(in) :: jj(ixi^s)
256  double precision, intent(out) :: res(ixi^s)
257 
258  end subroutine implicit_mult_factor_subroutine
259 
260  end interface
261 
262  procedure(implicit_mult_factor_subroutine), pointer :: calc_mult_factor => null()
263  integer, protected :: twofl_implicit_calc_mult_method = 1
264 
265 contains
266 
267  !> Read this module"s parameters from a file
268  subroutine twofl_read_params(files)
270  character(len=*), intent(in) :: files(:)
271  integer :: n
272 
273  namelist /twofl_list/ twofl_eq_energy, twofl_gamma, twofl_adiab,&
277  typedivbdiff, type_ct, divbwave, si_unit, b0field,&
284  twofl_dump_coll_terms,twofl_implicit_calc_mult_method,&
287  twofl_trac, twofl_trac_type, twofl_trac_mask,twofl_cbounds_species
288 
289  do n = 1, size(files)
290  open(unitpar, file=trim(files(n)), status="old")
291  read(unitpar, twofl_list, end=111)
292 111 close(unitpar)
293  end do
294 
295  end subroutine twofl_read_params
296 
297  subroutine twofl_init_hyper(files)
300  character(len=*), intent(in) :: files(:)
301  integer :: n
302 
303  namelist /hyperdiffusivity_list/ c_shk, c_hyp
304 
305  do n = 1, size(files)
306  open(unitpar, file=trim(files(n)), status="old")
307  read(unitpar, hyperdiffusivity_list, end=113)
308 113 close(unitpar)
309  end do
310 
311  call hyperdiffusivity_init()
312 
313  !!DEBUG
314  if(mype .eq. 0) then
315  print*, "Using Hyperdiffusivity"
316  print*, "C_SHK ", c_shk(:)
317  print*, "C_HYP ", c_hyp(:)
318  endif
319 
320  end subroutine twofl_init_hyper
321 
322  !> Write this module's parameters to a snapsoht
323  subroutine twofl_write_info(fh)
325  integer, intent(in) :: fh
326  integer, parameter :: n_par = 1
327  double precision :: values(n_par)
328  character(len=name_len) :: names(n_par)
329  integer, dimension(MPI_STATUS_SIZE) :: st
330  integer :: er
331 
332  call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
333 
334  names(1) = "gamma"
335  values(1) = twofl_gamma
336  call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
337  call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
338  end subroutine twofl_write_info
339 
340  subroutine twofl_angmomfix(fC,x,wnew,ixI^L,ixO^L,idim)
342  double precision, intent(in) :: x(ixI^S,1:ndim)
343  double precision, intent(inout) :: fC(ixI^S,1:nwflux,1:ndim), wnew(ixI^S,1:nw)
344  integer, intent(in) :: ixI^L, ixO^L
345  integer, intent(in) :: idim
346  integer :: hxO^L, kxC^L, iw
347  double precision :: inv_volume(ixI^S)
348 
349  call mpistop("to do")
350 
351  end subroutine twofl_angmomfix
352 
353  subroutine twofl_phys_init()
357  use mod_viscosity, only: viscosity_init
358  !use mod_gravity, only: gravity_init
361  {^nooned
363  }
364  integer :: itr, idir
365 
366  call twofl_read_params(par_files)
367  physics_type = "twofl"
368  if (twofl_cbounds_species) then
369  number_species = 2
370  endif
371  phys_energy=.true.
372  !> Solve total energy equation or not
373  ! for the two fluid the true value means
374  ! E_charges = E_mag + E_kin_charges + E_int_charges
375  ! E_neutrals = E_kin_neutrals + E_int_neutrals
376  phys_total_energy=.false.
377 
378  !> Solve internal enery instead of total energy
379  ! for the two fluid the true vale means
380  ! E_charges = E_int_charges
381  ! E_neutrals = E_int_neutrals
382  phys_internal_e=.false.
383 
384  ! For the two fluid phys_energy=.true. and phys_internal_e=.false. and phys_total_energy = .false. means
385  ! E_charges = E_kin_charges + E_int_charges
386  ! E_neutrals = E_kin_neutrals + E_int_neutrals
387  phys_gamma = twofl_gamma
388 
389  !> Solve internal energy and total energy equations
390  ! this implies two equations of energy solved
391  phys_solve_eaux=.false.
392 
393  if(twofl_eq_energy == eq_energy_int) then
394  phys_internal_e = .true.
396  phys_total_energy = .true.
397  if(twofl_eq_energy == eq_energy_tot2) then
398  phys_solve_eaux = .true.
399  endif
400  elseif(twofl_eq_energy == eq_energy_none) then
401  phys_energy = .false.
402  endif
403 
406 
407  if(.not. phys_energy) then
410  if(mype==0) write(*,*) 'WARNING: set twofl_thermal_conduction_n=F when twofl_energy=F'
411  end if
414  if(mype==0) write(*,*) 'WARNING: set twofl_radiative_cooling_n=F when twofl_energy=F'
415  end if
418  if(mype==0) write(*,*) 'WARNING: set twofl_thermal_conduction_c=F when twofl_energy=F'
419  end if
422  if(mype==0) write(*,*) 'WARNING: set twofl_radiative_cooling_c=F when twofl_energy=F'
423  end if
424  if(twofl_trac) then
425  twofl_trac=.false.
426  if(mype==0) write(*,*) 'WARNING: set twofl_trac=F when twofl_energy=F'
427  end if
428  end if
429  {^ifoned
430  if(twofl_trac .and. twofl_trac_type .gt. 1) then
432  if(mype==0) write(*,*) 'WARNING: set twofl_trac_type=1 for 1D simulation'
433  end if
434  }
435  if(twofl_trac .and. twofl_trac_type .le. 3) then
436  twofl_trac_mask=bigdouble
437  if(mype==0) write(*,*) 'WARNING: set twofl_trac_mask==bigdouble for global TRAC method'
438  end if
440 
441  if(phys_solve_eaux) prolongprimitive=.true.
442 
443  ! set default gamma for polytropic/isothermal process
444  if(ndim==1) typedivbfix='none'
445  select case (typedivbfix)
446  case ('none')
447  type_divb = divb_none
448  {^nooned
449  case ('multigrid')
450  type_divb = divb_multigrid
451  use_multigrid = .true.
452  mg%operator_type = mg_laplacian
453  phys_global_source_after => twofl_clean_divb_multigrid
454  }
455  case ('glm')
456  twofl_glm = .true.
457  need_global_cmax = .true.
458  type_divb = divb_glm
459  case ('powel', 'powell')
460  type_divb = divb_powel
461  case ('janhunen')
462  type_divb = divb_janhunen
463  case ('linde')
464  type_divb = divb_linde
465  case ('lindejanhunen')
466  type_divb = divb_lindejanhunen
467  case ('lindepowel')
468  type_divb = divb_lindepowel
469  case ('lindeglm')
470  twofl_glm = .true.
471  need_global_cmax = .true.
472  type_divb = divb_lindeglm
473  case ('ct')
474  type_divb = divb_ct
475  stagger_grid = .true.
476  case default
477  call mpistop('Unknown divB fix')
478  end select
479 
480  allocate(start_indices(number_species))
481  allocate(stop_indices(number_species))
482  start_indices(1)=1
483  !allocate charges first and the same order as in mhd module
484  rho_c_ = var_set_fluxvar("rho_c", "rho_c")
485  !set variables from mod_variables to point to charges vars
486  iw_rho = rho_c_
487 
488  allocate(mom_c(ndir))
489  do idir=1,ndir
490  mom_c(idir) = var_set_fluxvar("m_c","v_c",idir)
491  enddo
492 
493  allocate(iw_mom(ndir))
494  iw_mom(1:ndir) = mom_c(1:ndir)
495 
496  ! Set index of energy variable
497  if (phys_energy) then
498  e_c_ = var_set_fluxvar("e_c", "p_c")
499  iw_e = e_c_
500  else
501  e_c_ = -1
502  end if
503 
504  ! ambipolar sts assumes mag and energy charges are continuous
505  allocate(mag(ndir))
506  mag(:) = var_set_bfield(ndir)
507 
508  if (twofl_glm) then
509  psi_ = var_set_fluxvar('psi', 'psi', need_bc=.false.)
510  else
511  psi_ = -1
512  end if
513 
514  ! set auxiliary internal energy variable
515  if(phys_energy .and. phys_solve_eaux) then
516  eaux_c_ = var_set_fluxvar("eaux_c", "paux_c",need_bc=.false.)
517  iw_eaux = eaux_c_
518  else
519  eaux_c_ = -1
520  end if
521 
522  ! set cutoff temperature when using the TRAC method, as well as an auxiliary weight
523  tweight_c_ = -1
524  if(twofl_trac) then
525  tcoff_c_ = var_set_wextra()
526  iw_tcoff = tcoff_c_
527  if(twofl_trac_type > 2) then
528  tweight_c_ = var_set_wextra()
529  endif
530  else
531  tcoff_c_ = -1
532  end if
533 
534  !now allocate neutrals
535 
536  ! TODO so far number_species is only used to treat them differently
537  ! in the solvers (different cbounds)
538  if (twofl_cbounds_species) then
539  stop_indices(1)=nwflux
540  start_indices(2)=nwflux+1
541  endif
542 
543  ! Determine flux variables
544  rho_n_ = var_set_fluxvar("rho_n", "rho_n")
545  allocate(mom_n(ndir))
546  do idir=1,ndir
547  mom_n(idir) = var_set_fluxvar("m_n","v_n",idir)
548  enddo
549  if (phys_energy) then
550  e_n_ = var_set_fluxvar("e_n", "p_n")
551  else
552  e_n_ = -1
553  end if
554 
555  tweight_n_ = -1
556  if(twofl_trac) then
557  tcoff_n_ = var_set_wextra()
558  if(twofl_trac_type > 2) then
559  tweight_n_ = var_set_wextra()
560  endif
561  else
562  tcoff_n_ = -1
563  end if
564 
565  stop_indices(number_species)=nwflux
566 
567  ! set indices of equi vars and update number_equi_vars
568  number_equi_vars = 0
569  if(has_equi_rho_n0) then
572  endif
573  if(has_equi_pe_n0) then
576  endif
577  if(has_equi_rho_c0) then
580  iw_equi_rho = equi_rho_c0_
581  endif
582  if(has_equi_pe_c0) then
585  iw_equi_p = equi_pe_c0_
586  endif
587 
588  ! set number of variables which need update ghostcells
589  nwgc=nwflux
590 
591  ! determine number of stagger variables
592  if(stagger_grid) nws=ndim
593 
594  ! Check whether custom flux types have been defined
595  if (.not. allocated(flux_type)) then
596  allocate(flux_type(ndir, nw))
597  flux_type = flux_default
598  else if (any(shape(flux_type) /= [ndir, nw])) then
599  call mpistop("phys_check error: flux_type has wrong shape")
600  end if
601 
602  if(ndim>1) then
603  if(twofl_glm) then
604  flux_type(:,psi_)=flux_special
605  do idir=1,ndir
606  flux_type(idir,mag(idir))=flux_special
607  end do
608  else
609  do idir=1,ndir
610  flux_type(idir,mag(idir))=flux_tvdlf
611  end do
612  end if
613  end if
614 
615  phys_get_dt => twofl_get_dt
616  phys_get_cmax => twofl_get_cmax
617  phys_get_a2max => twofl_get_a2max
618  !phys_get_tcutoff => twofl_get_tcutoff_c
619  if(twofl_cbounds_species) then
620  if (mype .eq. 0) print*, "Using different cbounds for each species nspecies = ", number_species
621  phys_get_cbounds => twofl_get_cbounds_species
622  phys_get_h_speed => twofl_get_h_speed_species
623  else
624  if (mype .eq. 0) print*, "Using same cbounds for all species"
625  phys_get_cbounds => twofl_get_cbounds_one
626  phys_get_h_speed => twofl_get_h_speed_one
627  endif
628  phys_get_flux => twofl_get_flux
629  phys_add_source_geom => twofl_add_source_geom
630  phys_add_source => twofl_add_source
631  phys_to_conserved => twofl_to_conserved
632  phys_to_primitive => twofl_to_primitive
633  phys_check_params => twofl_check_params
634  phys_check_w => twofl_check_w
635  phys_write_info => twofl_write_info
636  phys_angmomfix => twofl_angmomfix
637  phys_handle_small_values => twofl_handle_small_values
638  phys_energy_synchro => twofl_energy_synchro
639  !set equilibrium variables for the new grid
640  if(number_equi_vars>0) then
641  phys_set_equi_vars => set_equi_vars_grid
642  endif
643  ! convert_type is not known here, so associate the corresp. subroutine in check_params
644  if(type_divb==divb_glm) then
645  phys_modify_wlr => twofl_modify_wlr
646  end if
647 
648  ! if using ct stagger grid, boundary divb=0 is not done here
649  if(stagger_grid) then
650  phys_get_ct_velocity => twofl_get_ct_velocity
651  phys_update_faces => twofl_update_faces
652  phys_face_to_center => twofl_face_to_center
653  phys_modify_wlr => twofl_modify_wlr
654  else if(ndim>1) then
655  phys_boundary_adjust => twofl_boundary_adjust
656  end if
657 
658  {^nooned
659  ! clean initial divb
660  if(clean_initial_divb) phys_clean_divb => twofl_clean_divb_multigrid
661  }
662 
663  ! Whether diagonal ghost cells are required for the physics
664  if(type_divb < divb_linde) phys_req_diagonal = .false.
665 
666  ! derive units from basic units
667  call twofl_physical_units()
668 
669  if(.not. phys_energy .and. (twofl_thermal_conduction_c&
670  .or. twofl_thermal_conduction_n)) then
671  call mpistop("thermal conduction needs twofl_energy=T")
672  end if
673 
674  ! initialize thermal conduction module
676  .or. twofl_thermal_conduction_n) then
677  phys_req_diagonal = .true.
678  call sts_init()
680  endif
682  allocate(tc_fl_c)
683  if(has_equi_pe_c0 .and. has_equi_rho_c0) then
684  tc_fl_c%get_temperature_from_eint => twofl_get_temperature_from_eint_c_with_equi
685  if(phys_internal_e) then
686  tc_fl_c%get_temperature_from_conserved => twofl_get_temperature_from_eint_c_with_equi
687  else
688  if(twofl_eq_energy == eq_energy_ki) then
689  tc_fl_c%get_temperature_from_conserved => twofl_get_temperature_from_eki_c_with_equi
690  else
691  tc_fl_c%get_temperature_from_conserved => twofl_get_temperature_from_etot_c_with_equi
692  endif
693  endif
694  if(twofl_equi_thermal_c) then
695  tc_fl_c%has_equi = .true.
696  tc_fl_c%get_temperature_equi => twofl_get_temperature_c_equi
697  tc_fl_c%get_rho_equi => twofl_get_rho_c_equi
698  else
699  tc_fl_c%has_equi = .false.
700  endif
701  else
702  if(phys_internal_e) then
703  tc_fl_c%get_temperature_from_conserved => twofl_get_temperature_from_eint_c
704  else
705  if(twofl_eq_energy == eq_energy_ki) then
706  tc_fl_c%get_temperature_from_conserved => twofl_get_temperature_from_eki_c
707  else
708  tc_fl_c%get_temperature_from_conserved => twofl_get_temperature_from_etot_c
709  endif
710  endif
711  tc_fl_c%get_temperature_from_eint => twofl_get_temperature_from_eint_c
712  endif
713  if(use_twofl_tc_c .eq. mhd_tc) then
716  else if(use_twofl_tc_c .eq. hd_tc) then
719  endif
720  if(.not. phys_internal_e) then
722  endif
724  tc_fl_c%get_rho => get_rhoc_tot
725  tc_fl_c%e_ = e_c_
726  tc_fl_c%Tcoff_ = tcoff_c_
727  end if
729  allocate(tc_fl_n)
731  if(has_equi_pe_n0 .and. has_equi_rho_n0) then
732  tc_fl_n%get_temperature_from_eint => twofl_get_temperature_from_eint_n_with_equi
733  if(twofl_equi_thermal_n) then
734  tc_fl_n%has_equi = .true.
735  tc_fl_n%get_temperature_equi => twofl_get_temperature_n_equi
736  tc_fl_n%get_rho_equi => twofl_get_rho_n_equi
737  else
738  tc_fl_n%has_equi = .false.
739  endif
740  else
741  tc_fl_n%get_temperature_from_eint => twofl_get_temperature_from_eint_n
742  endif
743  if(phys_internal_e) then
744  if(has_equi_pe_n0 .and. has_equi_rho_n0) then
745  tc_fl_n%get_temperature_from_conserved => twofl_get_temperature_from_eint_n_with_equi
746  else
747  tc_fl_n%get_temperature_from_conserved => twofl_get_temperature_from_eint_n
748  endif
750  else
751  if(has_equi_pe_n0 .and. has_equi_rho_n0) then
752  tc_fl_n%get_temperature_from_conserved => twofl_get_temperature_from_etot_n_with_equi
753  else
754  tc_fl_n%get_temperature_from_conserved => twofl_get_temperature_from_etot_n
755  endif
758  endif
760  tc_fl_n%get_rho => get_rhon_tot
761  tc_fl_n%e_ = e_n_
762  tc_fl_n%Tcoff_ = tcoff_n_
763  end if
764 
765 
766  if(.not. phys_energy .and. (twofl_radiative_cooling_c&
767  .or. twofl_radiative_cooling_n)) then
768  call mpistop("radiative cooling needs twofl_energy=T")
769  end if
770 
771  ! initialize thermal conduction module
773  .or. twofl_radiative_cooling_n) then
774  ! Initialize radiative cooling module
775  call radiative_cooling_init_params(twofl_gamma,he_abundance)
777  allocate(rc_fl_c)
779  rc_fl_c%get_rho => get_rhoc_tot
780  rc_fl_c%get_pthermal => twofl_get_pthermal_c
781  rc_fl_c%Rfactor = rc
782  rc_fl_c%e_ = e_c_
783  rc_fl_c%eaux_ = eaux_c_
784  rc_fl_c%Tcoff_ = tcoff_c_
786  rc_fl_c%has_equi = .true.
787  rc_fl_c%get_rho_equi => twofl_get_rho_c_equi
788  rc_fl_c%get_pthermal_equi => twofl_get_pe_c_equi
789  else
790  rc_fl_c%has_equi = .false.
791  end if
792  end if
793  end if
794  allocate(te_fl_c)
795  te_fl_c%get_rho=> get_rhoc_tot
796  te_fl_c%get_pthermal=> twofl_get_pthermal_c
797  te_fl_c%Rfactor = rc
798 {^ifthreed
799  phys_te_images => twofl_te_images
800 }
801 
802  ! Initialize viscosity module
803  !!TODO
804  !if (twofl_viscosity) call viscosity_init(phys_wider_stencil,phys_req_diagonal)
805 
806  ! Initialize gravity module
807  if(twofl_gravity) then
808  ! call gravity_init()
810  end if
811 
812  ! Initialize particles module
813  ! For Hall, we need one more reconstructed layer since currents are computed
814  ! in getflux: assuming one additional ghost layer (two for FOURTHORDER) was
815  ! added in nghostcells.
816  if (twofl_hall) then
817  phys_req_diagonal = .true.
818  if (twofl_4th_order) then
819  phys_wider_stencil = 2
820  else
821  phys_wider_stencil = 1
822  end if
823  end if
824 
825  if(twofl_hyperdiffusivity) then
826  allocate(c_shk(1:nwflux))
827  allocate(c_hyp(1:nwflux))
829  end if
830 
831  end subroutine twofl_phys_init
832 
833 {^ifthreed
834  subroutine twofl_te_images
837 
838  select case(convert_type)
839  case('EIvtiCCmpi','EIvtuCCmpi')
841  case('ESvtiCCmpi','ESvtuCCmpi')
843  case('SIvtiCCmpi','SIvtuCCmpi')
845  case default
846  call mpistop("Error in synthesize emission: Unknown convert_type")
847  end select
848  end subroutine twofl_te_images
849 }
850 
851  ! wrappers for STS functions in thermal_conductivity module
852  ! which take as argument the tc_fluid (defined in the physics module)
853  subroutine twofl_sts_set_source_tc_c_mhd(ixI^L,ixO^L,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux)
855  use mod_fix_conserve
857  integer, intent(in) :: ixI^L, ixO^L, igrid, nflux
858  double precision, intent(in) :: x(ixI^S,1:ndim)
859  double precision, intent(inout) :: wres(ixI^S,1:nw), w(ixI^S,1:nw)
860  double precision, intent(in) :: my_dt
861  logical, intent(in) :: fix_conserve_at_step
862  call sts_set_source_tc_mhd(ixi^l,ixo^l,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux,tc_fl_c)
863  end subroutine twofl_sts_set_source_tc_c_mhd
864 
865  subroutine twofl_sts_set_source_tc_c_hd(ixI^L,ixO^L,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux)
867  use mod_fix_conserve
869  integer, intent(in) :: ixI^L, ixO^L, igrid, nflux
870  double precision, intent(in) :: x(ixI^S,1:ndim)
871  double precision, intent(inout) :: wres(ixI^S,1:nw), w(ixI^S,1:nw)
872  double precision, intent(in) :: my_dt
873  logical, intent(in) :: fix_conserve_at_step
874  call sts_set_source_tc_hd(ixi^l,ixo^l,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux,tc_fl_c)
875  end subroutine twofl_sts_set_source_tc_c_hd
876 
877  function twofl_get_tc_dt_mhd_c(w,ixI^L,ixO^L,dx^D,x) result(dtnew)
878  !Check diffusion time limit dt < dx_i**2/((gamma-1)*tc_k_para_i/rho)
879  !where tc_k_para_i=tc_k_para*B_i**2/B**2
880  !and T=p/rho
883 
884  integer, intent(in) :: ixi^l, ixo^l
885  double precision, intent(in) :: dx^d, x(ixi^s,1:ndim)
886  double precision, intent(in) :: w(ixi^s,1:nw)
887  double precision :: dtnew
888 
889  dtnew=get_tc_dt_mhd(w,ixi^l,ixo^l,dx^d,x,tc_fl_c)
890  end function twofl_get_tc_dt_mhd_c
891 
892  function twofl_get_tc_dt_hd_c(w,ixI^L,ixO^L,dx^D,x) result(dtnew)
893  !Check diffusion time limit dt < dx_i**2/((gamma-1)*tc_k_para_i/rho)
894  !where tc_k_para_i=tc_k_para*B_i**2/B**2
895  !and T=p/rho
898 
899  integer, intent(in) :: ixi^l, ixo^l
900  double precision, intent(in) :: dx^d, x(ixi^s,1:ndim)
901  double precision, intent(in) :: w(ixi^s,1:nw)
902  double precision :: dtnew
903 
904  dtnew=get_tc_dt_hd(w,ixi^l,ixo^l,dx^d,x,tc_fl_c)
905  end function twofl_get_tc_dt_hd_c
906 
907  subroutine twofl_tc_handle_small_e_c(w, x, ixI^L, ixO^L, step)
909  use mod_small_values
910 
911  integer, intent(in) :: ixI^L,ixO^L
912  double precision, intent(inout) :: w(ixI^S,1:nw)
913  double precision, intent(in) :: x(ixI^S,1:ndim)
914  integer, intent(in) :: step
915 
916  character(len=140) :: error_msg
917 
918  write(error_msg,"(a,i3)") "Charges thermal conduction step ", step
919  call twofl_handle_small_ei_c(w,x,ixi^l,ixo^l,e_c_,error_msg)
920  end subroutine twofl_tc_handle_small_e_c
921 
922  subroutine twofl_sts_set_source_tc_n_hd(ixI^L,ixO^L,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux)
924  use mod_fix_conserve
926  integer, intent(in) :: ixI^L, ixO^L, igrid, nflux
927  double precision, intent(in) :: x(ixI^S,1:ndim)
928  double precision, intent(inout) :: wres(ixI^S,1:nw), w(ixI^S,1:nw)
929  double precision, intent(in) :: my_dt
930  logical, intent(in) :: fix_conserve_at_step
931  call sts_set_source_tc_hd(ixi^l,ixo^l,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux,tc_fl_n)
932  end subroutine twofl_sts_set_source_tc_n_hd
933 
934  subroutine twofl_tc_handle_small_e_n(w, x, ixI^L, ixO^L, step)
936 
937  integer, intent(in) :: ixI^L,ixO^L
938  double precision, intent(inout) :: w(ixI^S,1:nw)
939  double precision, intent(in) :: x(ixI^S,1:ndim)
940  integer, intent(in) :: step
941 
942  character(len=140) :: error_msg
943 
944  write(error_msg,"(a,i3)") "Neutral thermal conduction step ", step
945  call twofl_handle_small_ei_n(w,x,ixi^l,ixo^l,e_n_,error_msg)
946  end subroutine twofl_tc_handle_small_e_n
947 
948  function twofl_get_tc_dt_hd_n(w,ixI^L,ixO^L,dx^D,x) result(dtnew)
949  !Check diffusion time limit dt < dx_i**2/((gamma-1)*tc_k_para_i/rho)
950  !where tc_k_para_i=tc_k_para*B_i**2/B**2
951  !and T=p/rho
954 
955  integer, intent(in) :: ixi^l, ixo^l
956  double precision, intent(in) :: dx^d, x(ixi^s,1:ndim)
957  double precision, intent(in) :: w(ixi^s,1:nw)
958  double precision :: dtnew
959 
960  dtnew=get_tc_dt_hd(w,ixi^l,ixo^l,dx^d,x,tc_fl_n)
961  end function twofl_get_tc_dt_hd_n
962 
963  subroutine tc_n_params_read_hd(fl)
965  use mod_global_parameters, only: unitpar
966  type(tc_fluid), intent(inout) :: fl
967  integer :: n
968  logical :: tc_saturate=.false.
969  double precision :: tc_k_para=0d0
970 
971  namelist /tc_n_list/ tc_saturate, tc_k_para
972 
973  do n = 1, size(par_files)
974  open(unitpar, file=trim(par_files(n)), status="old")
975  read(unitpar, tc_n_list, end=111)
976 111 close(unitpar)
977  end do
978  fl%tc_saturate = tc_saturate
979  fl%tc_k_para = tc_k_para
980 
981  end subroutine tc_n_params_read_hd
982 
983  subroutine rc_params_read_n(fl)
985  use mod_constants, only: bigdouble
986  type(rc_fluid), intent(inout) :: fl
987  integer :: n
988  ! list parameters
989  integer :: ncool = 4000
990  double precision :: cfrac=0.1d0
991 
992  !> Name of cooling curve
993  character(len=std_len) :: coolcurve='JCorona'
994 
995  !> Name of cooling method
996  character(len=std_len) :: coolmethod='exact'
997 
998  !> Fixed temperature not lower than tlow
999  logical :: Tfix=.false.
1000 
1001  !> Lower limit of temperature
1002  double precision :: tlow=bigdouble
1003 
1004  !> Add cooling source in a split way (.true.) or un-split way (.false.)
1005  logical :: rc_split=.false.
1006 
1007  namelist /rc_list_n/ coolcurve, coolmethod, ncool, cfrac, tlow, tfix, rc_split
1008 
1009  do n = 1, size(par_files)
1010  open(unitpar, file=trim(par_files(n)), status="old")
1011  read(unitpar, rc_list_n, end=111)
1012 111 close(unitpar)
1013  end do
1014 
1015  fl%ncool=ncool
1016  fl%coolcurve=coolcurve
1017  fl%coolmethod=coolmethod
1018  fl%tlow=tlow
1019  fl%Tfix=tfix
1020  fl%rc_split=rc_split
1021  fl%cfrac=cfrac
1022  end subroutine rc_params_read_n
1023 
1024  !end wrappers
1025 
1026  ! fill in tc_fluid fields from namelist
1027  subroutine tc_c_params_read_mhd(fl)
1029  type(tc_fluid), intent(inout) :: fl
1030 
1031  integer :: n
1032 
1033  ! list parameters
1034  logical :: tc_perpendicular=.true.
1035  logical :: tc_saturate=.false.
1036  double precision :: tc_k_para=0d0
1037  double precision :: tc_k_perp=0d0
1038  character(len=std_len) :: tc_slope_limiter="MC"
1039 
1040  namelist /tc_c_list/ tc_perpendicular, tc_saturate, tc_slope_limiter, tc_k_para, tc_k_perp
1041  do n = 1, size(par_files)
1042  open(unitpar, file=trim(par_files(n)), status="old")
1043  read(unitpar, tc_c_list, end=111)
1044 111 close(unitpar)
1045  end do
1046 
1047  fl%tc_perpendicular = tc_perpendicular
1048  fl%tc_saturate = tc_saturate
1049  fl%tc_k_para = tc_k_para
1050  fl%tc_k_perp = tc_k_perp
1051  fl%tc_slope_limiter = tc_slope_limiter
1052  end subroutine tc_c_params_read_mhd
1053 
1054  subroutine tc_c_params_read_hd(fl)
1056  use mod_global_parameters, only: unitpar
1057  type(tc_fluid), intent(inout) :: fl
1058  integer :: n
1059  logical :: tc_saturate=.false.
1060  double precision :: tc_k_para=0d0
1061 
1062  namelist /tc_c_list/ tc_saturate, tc_k_para
1063 
1064  do n = 1, size(par_files)
1065  open(unitpar, file=trim(par_files(n)), status="old")
1066  read(unitpar, tc_c_list, end=111)
1067 111 close(unitpar)
1068  end do
1069  fl%tc_saturate = tc_saturate
1070  fl%tc_k_para = tc_k_para
1071 
1072  end subroutine tc_c_params_read_hd
1073 
1074 !! end th cond
1075 
1076 !!rad cool
1077  subroutine rc_params_read_c(fl)
1079  use mod_constants, only: bigdouble
1080  type(rc_fluid), intent(inout) :: fl
1081  integer :: n
1082  ! list parameters
1083  integer :: ncool = 4000
1084  double precision :: cfrac=0.1d0
1085 
1086  !> Name of cooling curve
1087  character(len=std_len) :: coolcurve='JCcorona'
1088 
1089  !> Name of cooling method
1090  character(len=std_len) :: coolmethod='exact'
1091 
1092  !> Fixed temperature not lower than tlow
1093  logical :: Tfix=.false.
1094 
1095  !> Lower limit of temperature
1096  double precision :: tlow=bigdouble
1097 
1098  !> Add cooling source in a split way (.true.) or un-split way (.false.)
1099  logical :: rc_split=.false.
1100 
1101 
1102  namelist /rc_list_c/ coolcurve, coolmethod, ncool, cfrac, tlow, tfix, rc_split
1103 
1104  do n = 1, size(par_files)
1105  open(unitpar, file=trim(par_files(n)), status="old")
1106  read(unitpar, rc_list_c, end=111)
1107 111 close(unitpar)
1108  end do
1109 
1110  fl%ncool=ncool
1111  fl%coolcurve=coolcurve
1112  fl%coolmethod=coolmethod
1113  fl%tlow=tlow
1114  fl%Tfix=tfix
1115  fl%rc_split=rc_split
1116  fl%cfrac=cfrac
1117  end subroutine rc_params_read_c
1118 
1119 !! end rad cool
1120 
1121  !> sets the equilibrium variables
1122  subroutine set_equi_vars_grid_faces(igrid,x,ixI^L,ixO^L)
1125  use mod_usr_methods
1126  integer, intent(in) :: igrid, ixI^L, ixO^L
1127  double precision, intent(in) :: x(ixI^S,1:ndim)
1128 
1129  double precision :: delx(ixI^S,1:ndim)
1130  double precision :: xC(ixI^S,1:ndim),xshift^D
1131  integer :: idims, ixC^L, hxO^L, ix, idims2
1132 
1133  if(slab_uniform)then
1134  ^d&delx(ixi^s,^d)=rnode(rpdx^d_,igrid)\
1135  else
1136  ! for all non-cartesian and stretched cartesian coordinates
1137  delx(ixi^s,1:ndim)=ps(igrid)%dx(ixi^s,1:ndim)
1138  endif
1139 
1140 
1141  do idims=1,ndim
1142  hxo^l=ixo^l-kr(idims,^d);
1143  if(stagger_grid) then
1144  ! ct needs all transverse cells
1145  ixcmax^d=ixomax^d+nghostcells-nghostcells*kr(idims,^d); ixcmin^d=hxomin^d-nghostcells+nghostcells*kr(idims,^d);
1146  else
1147  ! ixC is centered index in the idims direction from ixOmin-1/2 to ixOmax+1/2
1148  ixcmax^d=ixomax^d; ixcmin^d=hxomin^d;
1149  end if
1150  ! always xshift=0 or 1/2
1151  xshift^d=half*(one-kr(^d,idims));
1152  do idims2=1,ndim
1153  select case(idims2)
1154  {case(^d)
1155  do ix = ixc^lim^d
1156  ! xshift=half: this is the cell center coordinate
1157  ! xshift=0: this is the cell edge i+1/2 coordinate
1158  xc(ix^d%ixC^s,^d)=x(ix^d%ixC^s,^d)+(half-xshift^d)*delx(ix^d%ixC^s,^d)
1159  end do\}
1160  end select
1161  end do
1162  call usr_set_equi_vars(ixi^l,ixc^l,xc,ps(igrid)%equi_vars(ixi^s,1:number_equi_vars,idims))
1163  end do
1164 
1165  end subroutine set_equi_vars_grid_faces
1166 
1167  !> sets the equilibrium variables
1168  subroutine set_equi_vars_grid(igrid)
1170  use mod_usr_methods
1171 
1172  integer, intent(in) :: igrid
1173 
1174  !values at the center
1175  call usr_set_equi_vars(ixg^ll,ixg^ll,ps(igrid)%x,ps(igrid)%equi_vars(ixg^t,1:number_equi_vars,0))
1176 
1177  !values at the interfaces
1178  call set_equi_vars_grid_faces(igrid,ps(igrid)%x,ixg^ll,ixm^ll)
1179 
1180  end subroutine set_equi_vars_grid
1181 
1182  ! w, wnew conserved
1183  function convert_vars_splitting(ixI^L,ixO^L, w, x, nwc) result(wnew)
1185  integer, intent(in) :: ixi^l,ixo^l, nwc
1186  double precision, intent(in) :: w(ixi^s, 1:nw)
1187  double precision, intent(in) :: x(ixi^s,1:ndim)
1188  double precision :: wnew(ixo^s, 1:nwc)
1189  double precision :: rho(ixi^s)
1190 
1191  call get_rhon_tot(w,x,ixi^l,ixo^l,rho(ixi^s))
1192  wnew(ixo^s,rho_n_) = rho(ixo^s)
1193  wnew(ixo^s,mom_n(:)) = w(ixo^s,mom_n(:))
1194  call get_rhoc_tot(w,x,ixi^l,ixo^l,rho(ixi^s))
1195  wnew(ixo^s,rho_c_) = rho(ixo^s)
1196  wnew(ixo^s,mom_c(:)) = w(ixo^s,mom_c(:))
1197 
1198  if (b0field) then
1199  ! add background magnetic field B0 to B
1200  wnew(ixo^s,mag(:))=w(ixo^s,mag(:))+block%B0(ixo^s,:,0)
1201  else
1202  wnew(ixo^s,mag(:))=w(ixo^s,mag(:))
1203  end if
1204 
1205  if(phys_energy) then
1206  wnew(ixo^s,e_n_) = w(ixo^s,e_n_)
1207  if(has_equi_pe_n0) then
1208  wnew(ixo^s,e_n_) = wnew(ixo^s,e_n_) + block%equi_vars(ixo^s,equi_pe_n0_,0)* inv_gamma_1
1209  endif
1210  wnew(ixo^s,e_c_) = w(ixo^s,e_c_)
1211  if(has_equi_pe_c0) then
1212  wnew(ixo^s,e_c_) = wnew(ixo^s,e_c_) + block%equi_vars(ixo^s,equi_pe_c0_,0)* inv_gamma_1
1213  endif
1214  if(b0field .and. phys_total_energy) then
1215  wnew(ixo^s,e_c_)=wnew(ixo^s,e_c_)+0.5d0*sum(block%B0(ixo^s,:,0)**2,dim=ndim+1) &
1216  + sum(w(ixo^s,mag(:))*block%B0(ixo^s,:,0),dim=ndim+1)
1217  endif
1218  endif
1219 
1220  end function convert_vars_splitting
1221 
1222  !> copied from mod_gravity
1223  subroutine grav_params_read(files)
1224  use mod_global_parameters, only: unitpar
1225  character(len=*), intent(in) :: files(:)
1226  integer :: n
1227 
1228  namelist /grav_list/ grav_split
1229 
1230  do n = 1, size(files)
1231  open(unitpar, file=trim(files(n)), status="old")
1232  read(unitpar, grav_list, end=111)
1233 111 close(unitpar)
1234  end do
1235 
1236  end subroutine grav_params_read
1237 
1240  use mod_convert, only: add_convert_method
1241  integer :: ii
1242  do ii = 1,ndim
1243  if(ii==1) then
1244  call add_convert_method(dump_hyperdiffusivity_coef_x, nw, cons_wnames(1:nw), "hyper_x")
1245  elseif(ii==2) then
1246  call add_convert_method(dump_hyperdiffusivity_coef_y, nw, cons_wnames(1:nw), "hyper_y")
1247  else
1248  call add_convert_method(dump_hyperdiffusivity_coef_z, nw, cons_wnames(1:nw), "hyper_z")
1249  endif
1250  enddo
1251  end subroutine associate_dump_hyper
1252 
1255  use mod_usr_methods
1256  use mod_convert, only: add_convert_method
1257 
1258  ! after user parameter setting
1259  gamma_1=twofl_gamma-1.d0
1260  if (.not. phys_energy) then
1261  if (twofl_gamma <= 0.0d0) call mpistop ("Error: twofl_gamma <= 0")
1262  if (twofl_adiab < 0.0d0) call mpistop ("Error: twofl_adiab < 0")
1264  else
1265  if (twofl_gamma <= 0.0d0 .or. twofl_gamma == 1.0d0) &
1266  call mpistop ("Error: twofl_gamma <= 0 or twofl_gamma == 1")
1267  inv_gamma_1=1.d0/gamma_1
1268  small_e = small_pressure * inv_gamma_1
1269  end if
1270 
1271  ! this has to be done here as use_imex_scheme is not set in init subroutine,
1272  ! but here it is
1273  if(use_imex_scheme) then
1274  if(has_collisions()) then
1275  ! implicit collisional terms update
1276  phys_implicit_update => twofl_implicit_coll_terms_update
1277  phys_evaluate_implicit => twofl_evaluate_implicit
1278  if(mype .eq. 1) then
1279  print*, "IMPLICIT UPDATE with calc_mult_factor", twofl_implicit_calc_mult_method
1280  endif
1281  if(twofl_implicit_calc_mult_method == 1) then
1282  calc_mult_factor => calc_mult_factor1
1283  else
1284  calc_mult_factor => calc_mult_factor2
1285  endif
1286  endif
1287  else
1288  ! check dtcoll par for explicit implementation of the coll. terms
1289  if(dtcollpar .le. 0d0 .or. dtcollpar .ge. 1d0) then
1290  if (mype .eq. 0) print*, "Explicit update of coll terms requires 0<dtcollpar<1, dtcollpar set to 0.8."
1291  dtcollpar = 0.8
1292  endif
1293 
1294  endif
1295 ! if(H_ion_fr == 0d0 .and. He_ion_fr == 0d0) then
1296 ! call mpistop("H_ion_fr or He_ion_fr must be > 0 or use hd module")
1297 ! endif
1298 ! if(H_ion_fr == 1d0 .and. He_ion_fr == 1d0) then
1299 ! call mpistop("H_ion_fr or He_ion_fr must be < 1 or use mhd module")
1300 ! endif
1301  if (number_equi_vars > 0 .and. .not. associated(usr_set_equi_vars)) then
1302  call mpistop("usr_set_equi_vars has to be implemented in the user file")
1303  endif
1304  if(convert .or. autoconvert) then
1305  if(convert_type .eq. 'dat_generic_mpi') then
1306  if(twofl_dump_full_vars) then
1307  if(mype .eq. 0) print*, " add conversion method: split -> full "
1308  call add_convert_method(convert_vars_splitting, nw, cons_wnames, "new")
1309  endif
1310  if(twofl_dump_coll_terms) then
1311  if(mype .eq. 0) print*, " add conversion method: dump coll terms "
1312  call add_convert_method(dump_coll_terms, 3, (/"alpha ", "gamma_rec", "gamma_ion"/), "_coll")
1313  endif
1315  if(mype .eq. 0) print*, " add conversion method: dump hyperdiffusivity coeff. "
1316  call associate_dump_hyper()
1317  endif
1318  endif
1319  endif
1320  end subroutine twofl_check_params
1321 
1324  double precision :: mp,kB,miu0,c_lightspeed
1325  !double precision :: a,b,c,d
1326  double precision :: a,b
1327  ! Derive scaling units
1328  if(si_unit) then
1329  mp=mp_si
1330  kb=kb_si
1331  miu0=miu0_si
1332  c_lightspeed=c_si
1333  else
1334  mp=mp_cgs
1335  kb=kb_cgs
1336  miu0=4.d0*dpi
1337  c_lightspeed=const_c
1338  end if
1339 
1340 
1341  a=1d0
1342  b=1d0
1343  rc=2d0
1344  rn=1d0
1345 
1346  !now the unit choice:
1347  !unit 1 from number density or density -> mH
1348  !unit 2 from
1349 
1350  if(unit_density/=1.d0) then
1352  else
1353  ! unit of numberdensity is independent by default
1355  end if
1356  if(unit_velocity/=1.d0) then
1360  else if(unit_pressure/=1.d0) then
1364  else if(unit_magneticfield/=1.d0) then
1368  else
1369  ! unit of temperature is independent by default
1373  end if
1374  if(unit_time/=1.d0) then
1376  else
1377  ! unit of length is independent by default
1379  end if
1380  ! Additional units needed for the particles
1381  c_norm=c_lightspeed/unit_velocity
1383  if (.not. si_unit) unit_charge = unit_charge*const_c
1385  end subroutine twofl_physical_units
1386 
1387  subroutine twofl_check_w(primitive,ixI^L,ixO^L,w,flag)
1389 
1390  logical, intent(in) :: primitive
1391  integer, intent(in) :: ixI^L, ixO^L
1392  double precision, intent(in) :: w(ixI^S,nw)
1393  double precision :: tmp(ixI^S)
1394  logical, intent(inout) :: flag(ixI^S,1:nw)
1395 
1396  flag=.false.
1397 
1398  if(has_equi_rho_n0) then
1399  tmp(ixo^s) = w(ixo^s,rho_n_) + block%equi_vars(ixo^s,equi_rho_n0_,0)
1400  else
1401  tmp(ixo^s) = w(ixo^s,rho_n_)
1402  endif
1403  where(tmp(ixo^s) < small_density) flag(ixo^s,rho_n_) = .true.
1404  if(has_equi_rho_c0) then
1405  tmp(ixo^s) = w(ixo^s,rho_c_) + block%equi_vars(ixo^s,equi_rho_c0_,0)
1406  else
1407  tmp(ixo^s) = w(ixo^s,rho_c_)
1408  endif
1409  where(tmp(ixo^s) < small_density) flag(ixo^s,rho_c_) = .true.
1410  if(phys_energy) then
1411  if(primitive) then
1412  tmp(ixo^s) = w(ixo^s,e_n_)
1413  if(has_equi_pe_n0) then
1414  tmp(ixo^s) = tmp(ixo^s)+block%equi_vars(ixo^s,equi_pe_n0_,0)
1415  endif
1416  where(tmp(ixo^s) < small_pressure) flag(ixo^s,e_n_) = .true.
1417  tmp(ixo^s) = w(ixo^s,e_c_)
1418  if(has_equi_pe_c0) then
1419  tmp(ixo^s) = tmp(ixo^s)+block%equi_vars(ixo^s,equi_pe_c0_,0)
1420  endif
1421  where(tmp(ixo^s) < small_pressure) flag(ixo^s,e_c_) = .true.
1422  ! TODO , also in mhd?
1423  !if(twofl_eq_energy == EQ_ENERGY_TOT2) then
1424  ! where(w(ixO^S,eaux_c_) < small_pressure) flag(ixO^S,eaux_c_) = .true.
1425  !endif
1426  else
1427  if(phys_internal_e) then
1428  tmp(ixo^s)=w(ixo^s,e_n_)
1429  if(has_equi_pe_n0) then
1430  tmp(ixo^s) = tmp(ixo^s)+block%equi_vars(ixo^s,equi_pe_n0_,0)*inv_gamma_1
1431  endif
1432  where(tmp(ixo^s) < small_e) flag(ixo^s,e_n_) = .true.
1433  tmp(ixo^s)=w(ixo^s,e_c_)
1434  if(has_equi_pe_c0) then
1435  tmp(ixo^s) = tmp(ixo^s)+block%equi_vars(ixo^s,equi_pe_c0_,0)*inv_gamma_1
1436  endif
1437  where(tmp(ixo^s) < small_e) flag(ixo^s,e_c_) = .true.
1438  else
1439  !neutrals
1440  tmp(ixo^s)=w(ixo^s,e_n_)-&
1441  twofl_kin_en_n(w,ixi^l,ixo^l)
1442  if(has_equi_pe_n0) then
1443  tmp(ixo^s) = tmp(ixo^s)+block%equi_vars(ixo^s,equi_pe_n0_,0)*inv_gamma_1
1444  endif
1445  where(tmp(ixo^s) < small_e) flag(ixo^s,e_n_) = .true.
1446  if(phys_total_energy) then
1447  tmp(ixo^s)=w(ixo^s,e_c_)-&
1448  twofl_kin_en_c(w,ixi^l,ixo^l)-twofl_mag_en(w,ixi^l,ixo^l)
1449  else
1450  tmp(ixo^s)=w(ixo^s,e_c_)-&
1451  twofl_kin_en_c(w,ixi^l,ixo^l)
1452  end if
1453  if(has_equi_pe_c0) then
1454  tmp(ixo^s) = tmp(ixo^s)+block%equi_vars(ixo^s,equi_pe_c0_,0)*inv_gamma_1
1455  endif
1456  where(tmp(ixo^s) < small_e) flag(ixo^s,e_c_) = .true.
1457  if(twofl_eq_energy == eq_energy_tot2) then
1458  tmp(ixo^s)=w(ixo^s,eaux_c_)
1459  if(has_equi_pe_c0) then
1460  tmp(ixo^s) = tmp(ixo^s)+block%equi_vars(ixo^s,equi_pe_c0_,0)*inv_gamma_1
1461  endif
1462  where(tmp(ixo^s) < small_e) flag(ixo^s,e_c_) = .true.
1463  endif
1464  end if
1465  endif
1466  end if
1467 
1468  end subroutine twofl_check_w
1469 
1470  !> Transform primitive variables into conservative ones
1471  subroutine twofl_to_conserved(ixI^L,ixO^L,w,x)
1473  integer, intent(in) :: ixi^l, ixo^l
1474  double precision, intent(inout) :: w(ixi^s, nw)
1475  double precision, intent(in) :: x(ixi^s, 1:ndim)
1476  integer :: idir
1477  double precision :: rhoc(ixi^s)
1478  double precision :: rhon(ixi^s)
1479 
1480  !if (fix_small_values) then
1481  ! call twofl_handle_small_values(.true., w, x, ixI^L, ixO^L, 'twofl_to_conserved')
1482  !end if
1483 
1484  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
1485  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
1486 
1487  ! Calculate total energy from pressure, kinetic and magnetic energy
1488  if(phys_energy) then
1489  if(phys_internal_e) then
1490  w(ixo^s,e_n_)=w(ixo^s,e_n_)*inv_gamma_1
1491  w(ixo^s,e_c_)=w(ixo^s,e_c_)*inv_gamma_1
1492  else
1493  w(ixo^s,e_n_)=w(ixo^s,e_n_)*inv_gamma_1&
1494  +half*sum(w(ixo^s,mom_n(:))**2,dim=ndim+1)*rhon(ixo^s)
1495  if(phys_total_energy) then
1496  w(ixo^s,e_c_)=w(ixo^s,e_c_)*inv_gamma_1&
1497  +half*sum(w(ixo^s,mom_c(:))**2,dim=ndim+1)*rhoc(ixo^s)&
1498  +twofl_mag_en(w, ixi^l, ixo^l)
1499  if(twofl_eq_energy == eq_energy_tot2) then
1500  w(ixo^s,eaux_c_)=w(ixo^s,eaux_c_)*inv_gamma_1
1501  endif
1502  else
1503  ! kinetic energy + internal energy is evolved
1504  w(ixo^s,e_c_)=w(ixo^s,e_c_)*inv_gamma_1&
1505  +half*sum(w(ixo^s,mom_c(:))**2,dim=ndim+1)*rhoc(ixo^s)
1506  endif
1507  end if
1508  !print*, "TOCONS ec ", w(1:10,e_c_)
1509  !print*, "TOCONS en ", w(1:10,e_n_)
1510  end if
1511 
1512  ! Convert velocity to momentum
1513  do idir = 1, ndir
1514  w(ixo^s, mom_n(idir)) = rhon(ixo^s) * w(ixo^s, mom_n(idir))
1515  w(ixo^s, mom_c(idir)) = rhoc(ixo^s) * w(ixo^s, mom_c(idir))
1516  end do
1517  end subroutine twofl_to_conserved
1518 
1519  !> Transform conservative variables into primitive ones
1520  subroutine twofl_to_primitive(ixI^L,ixO^L,w,x)
1522  integer, intent(in) :: ixi^l, ixo^l
1523  double precision, intent(inout) :: w(ixi^s, nw)
1524  double precision, intent(in) :: x(ixi^s, 1:ndim)
1525  integer :: idir
1526  double precision :: rhoc(ixi^s)
1527  double precision :: rhon(ixi^s)
1528 
1529  if (fix_small_values) then
1530  call twofl_handle_small_values(.false., w, x, ixi^l, ixo^l, 'twofl_to_primitive')
1531  end if
1532 
1533  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
1534  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
1535 
1536  if(phys_energy) then
1537  if(phys_internal_e) then
1538  w(ixo^s,e_n_)=w(ixo^s,e_n_)*gamma_1
1539  w(ixo^s,e_c_)=w(ixo^s,e_c_)*gamma_1
1540  else
1541  ! neutrals evolved energy = ke + e_int
1542  w(ixo^s,e_n_)=gamma_1*(w(ixo^s,e_n_)&
1543  -twofl_kin_en_n(w,ixi^l,ixo^l))
1544  ! charges
1545  if(phys_total_energy) then
1546  ! evolved energy = ke + e_int + e_mag
1547  w(ixo^s,e_c_)=gamma_1*(w(ixo^s,e_c_)&
1548  -twofl_kin_en_c(w,ixi^l,ixo^l)&
1549  -twofl_mag_en(w,ixi^l,ixo^l))
1550  if(twofl_eq_energy == eq_energy_tot2) then
1551  w(ixo^s,eaux_c_)=w(ixo^s,eaux_c_)*gamma_1
1552  endif
1553  else
1554  ! evolved energy = ke + e_int
1555  w(ixo^s,e_c_)=gamma_1*(w(ixo^s,e_c_)&
1556  -twofl_kin_en_c(w,ixi^l,ixo^l))
1557  end if
1558  end if
1559  end if
1560 
1561  ! Convert momentum to velocity
1562  do idir = 1, ndir
1563  w(ixo^s, mom_c(idir)) = w(ixo^s, mom_c(idir))/rhoc(ixo^s)
1564  w(ixo^s, mom_n(idir)) = w(ixo^s, mom_n(idir))/rhon(ixo^s)
1565  end do
1566 
1567  end subroutine twofl_to_primitive
1568 
1569 !!USED IN TC
1570  !> Transform internal energy to total energy
1571  subroutine twofl_ei_to_e_c(ixI^L,ixO^L,w,x)
1573  integer, intent(in) :: ixI^L, ixO^L
1574  double precision, intent(inout) :: w(ixI^S, nw)
1575  double precision, intent(in) :: x(ixI^S, 1:ndim)
1576 
1577  ! Calculate total energy from internal, kinetic and magnetic energy
1578  if(phys_solve_eaux) w(ixi^s,eaux_c_)=w(ixi^s,e_c_)
1579  if(twofl_eq_energy == eq_energy_ki) then
1580  w(ixo^s,e_c_)=w(ixo^s,e_c_)&
1581  +twofl_kin_en_c(w,ixi^l,ixo^l)
1582  else
1583  w(ixo^s,e_c_)=w(ixo^s,e_c_)&
1584  +twofl_kin_en_c(w,ixi^l,ixo^l)&
1585  +twofl_mag_en(w,ixi^l,ixo^l)
1586  endif
1587  end subroutine twofl_ei_to_e_c
1588 
1589  !> Transform total energy to internal energy
1590  subroutine twofl_e_to_ei_c(ixI^L,ixO^L,w,x)
1592  integer, intent(in) :: ixI^L, ixO^L
1593  double precision, intent(inout) :: w(ixI^S, nw)
1594  double precision, intent(in) :: x(ixI^S, 1:ndim)
1595 
1596  if(twofl_eq_energy == eq_energy_ki) then
1597  w(ixo^s,e_c_)=w(ixo^s,e_c_)&
1598  -twofl_kin_en_c(w,ixi^l,ixo^l)
1599  else
1600  ! Calculate ei = e - ek - eb
1601  w(ixo^s,e_c_)=w(ixo^s,e_c_)&
1602  -twofl_kin_en_c(w,ixi^l,ixo^l)&
1603  -twofl_mag_en(w,ixi^l,ixo^l)
1604  endif
1605  end subroutine twofl_e_to_ei_c
1606 
1607  !Neutrals
1608  subroutine twofl_ei_to_e_n(ixI^L,ixO^L,w,x)
1610  integer, intent(in) :: ixI^L, ixO^L
1611  double precision, intent(inout) :: w(ixI^S, nw)
1612  double precision, intent(in) :: x(ixI^S, 1:ndim)
1613 
1614  ! Calculate total energy from internal and kinetic energy
1615 
1616  w(ixo^s,e_n_)=w(ixo^s,e_n_)+twofl_kin_en_n(w,ixi^l,ixo^l)
1617 
1618  end subroutine twofl_ei_to_e_n
1619 
1620  !> Transform total energy to internal energy
1621  subroutine twofl_e_to_ei_n(ixI^L,ixO^L,w,x)
1623  integer, intent(in) :: ixI^L, ixO^L
1624  double precision, intent(inout) :: w(ixI^S, nw)
1625  double precision, intent(in) :: x(ixI^S, 1:ndim)
1626 
1627  ! Calculate ei = e - ek
1628  w(ixo^s,e_n_)=w(ixo^s,e_n_)-twofl_kin_en_n(w,ixi^l,ixo^l)
1629 
1630  call twofl_handle_small_ei_n(w,x,ixi^l,ixo^l,e_n_,"e_to_ei_n")
1631  end subroutine twofl_e_to_ei_n
1632 
1633  subroutine twofl_energy_synchro(ixI^L,ixO^L,w,x)
1635  integer, intent(in) :: ixI^L,ixO^L
1636  double precision, intent(in) :: x(ixI^S,1:ndim)
1637  double precision, intent(inout) :: w(ixI^S,1:nw)
1638 
1639  double precision :: pth1(ixI^S),pth2(ixI^S),alfa(ixI^S),beta(ixI^S)
1640  double precision, parameter :: beta_low=0.005d0,beta_high=0.05d0
1641 
1642 ! double precision :: vtot(ixI^S),cs2(ixI^S),mach(ixI^S)
1643 ! double precision, parameter :: mach_low=20.d0,mach_high=200.d0
1644 
1645  ! get magnetic energy
1646  alfa(ixo^s)=twofl_mag_en(w,ixi^l,ixo^l)
1647  pth1(ixo^s)=gamma_1*(w(ixo^s,e_c_)-twofl_kin_en_c(w,ixi^l,ixo^l)-alfa(ixo^s))
1648  pth2(ixo^s)=w(ixo^s,eaux_c_)*gamma_1
1649  ! get plasma beta
1650  beta(ixo^s)=min(pth1(ixo^s),pth2(ixo^s))/alfa(ixo^s)
1651 
1652  ! whether Mach number should be another criterion ?
1653 ! vtot(ixO^S)=sum(w(ixO^S,mom(:))**2,dim=ndim+1)
1654 ! call twofl_get_csound2(w,x,ixI^L,ixO^L,cs2)
1655 ! mach(ixO^S)=sqrt(vtot(ixO^S)/cs2(ixO^S))/w(ixO^S,rho_)
1656  where(beta(ixo^s) .ge. beta_high)
1657 ! where(beta(ixO^S) .ge. beta_high .and. mach(ixO^S) .le. mach_low)
1658  w(ixo^s,eaux_c_)=pth1(ixo^s)*inv_gamma_1
1659  else where(beta(ixo^s) .le. beta_low)
1660 ! else where(beta(ixO^S) .le. beta_low .or. mach(ixO^S) .ge. mach_high)
1661  w(ixo^s,e_c_)=w(ixo^s,e_c_)-pth1(ixo^s)*inv_gamma_1+w(ixo^s,eaux_c_)
1662  else where
1663  alfa(ixo^s)=dlog(beta(ixo^s)/beta_low)/dlog(beta_high/beta_low)
1664 ! alfa(ixO^S)=min(dlog(beta(ixO^S)/beta_low)/dlog(beta_high/beta_low),
1665 ! dlog(mach_high(ixO^S)/mach(ixO^S))/dlog(mach_high/mach_low))
1666  w(ixo^s,eaux_c_)=(pth2(ixo^s)*(one-alfa(ixo^s))&
1667  +pth1(ixo^s)*alfa(ixo^s))*inv_gamma_1
1668  w(ixo^s,e_c_)=w(ixo^s,e_c_)-pth1(ixo^s)*inv_gamma_1+w(ixo^s,eaux_c_)
1669  end where
1670  end subroutine twofl_energy_synchro
1671 
1672  subroutine twofl_handle_small_values(primitive, w, x, ixI^L, ixO^L, subname)
1674  use mod_small_values
1675  logical, intent(in) :: primitive
1676  integer, intent(in) :: ixI^L,ixO^L
1677  double precision, intent(inout) :: w(ixI^S,1:nw)
1678  double precision, intent(in) :: x(ixI^S,1:ndim)
1679  character(len=*), intent(in) :: subname
1680 
1681  integer :: idir
1682  logical :: flag(ixI^S,1:nw)
1683  double precision :: tmp2(ixI^S)
1684  double precision :: tmp1(ixI^S)
1685 
1686  if(small_values_method == "ignore") return
1687 
1688  call twofl_check_w(primitive, ixi^l, ixo^l, w, flag)
1689 
1690  if(any(flag)) then
1691  select case (small_values_method)
1692  case ("replace")
1693  if(has_equi_rho_c0) then
1694  where(flag(ixo^s,rho_c_)) w(ixo^s,rho_c_) = &
1695  small_density-block%equi_vars(ixo^s,equi_rho_c0_,0)
1696  else
1697  where(flag(ixo^s,rho_c_)) w(ixo^s,rho_c_) = small_density
1698  endif
1699  if(has_equi_rho_n0) then
1700  where(flag(ixo^s,rho_n_)) w(ixo^s,rho_n_) = &
1701  small_density-block%equi_vars(ixo^s,equi_rho_n0_,0)
1702  else
1703  where(flag(ixo^s,rho_n_)) w(ixo^s,rho_n_) = small_density
1704  endif
1705  do idir = 1, ndir
1706  if(small_values_fix_iw(mom_n(idir))) then
1707  where(flag(ixo^s,rho_n_)) w(ixo^s, mom_n(idir)) = 0.0d0
1708  end if
1709  if(small_values_fix_iw(mom_c(idir))) then
1710  where(flag(ixo^s,rho_c_)) w(ixo^s, mom_c(idir)) = 0.0d0
1711  end if
1712  end do
1713 
1714  if(phys_energy) then
1715  if(primitive) then
1716  if(has_equi_pe_n0) then
1717  tmp1(ixo^s) = small_pressure - &
1718  block%equi_vars(ixo^s,equi_pe_n0_,0)
1719  else
1720  tmp1(ixo^s) = small_pressure
1721  endif
1722  if(has_equi_pe_c0) then
1723  tmp2(ixo^s) = small_e - &
1724  block%equi_vars(ixo^s,equi_pe_c0_,0)
1725  else
1726  tmp2(ixo^s) = small_pressure
1727  endif
1728  else
1729  ! conserved
1730  if(has_equi_pe_n0) then
1731  tmp1(ixo^s) = small_e - &
1732  block%equi_vars(ixo^s,equi_pe_n0_,0)*inv_gamma_1
1733  else
1734  tmp1(ixo^s) = small_e
1735  endif
1736  if(has_equi_pe_c0) then
1737  tmp2(ixo^s) = small_e - &
1738  block%equi_vars(ixo^s,equi_pe_c0_,0)*inv_gamma_1
1739  else
1740  tmp2(ixo^s) = small_e
1741  endif
1742  if(phys_internal_e) then
1743  where(flag(ixo^s,e_n_))
1744  w(ixo^s,e_n_)=tmp1(ixo^s)
1745  end where
1746  where(flag(ixo^s,e_c_))
1747  w(ixo^s,e_c_)=tmp2(ixo^s)
1748  end where
1749  else
1750  where(flag(ixo^s,e_n_))
1751  w(ixo^s,e_n_) = tmp1(ixo^s)+&
1752  twofl_kin_en_n(w,ixi^l,ixo^l)
1753  end where
1754  if(phys_total_energy) then
1755  where(flag(ixo^s,e_c_))
1756  w(ixo^s,e_c_) = tmp2(ixo^s)+&
1757  twofl_kin_en_c(w,ixi^l,ixo^l)+&
1758  twofl_mag_en(w,ixi^l,ixo^l)
1759  end where
1760  else
1761  where(flag(ixo^s,e_c_))
1762  w(ixo^s,e_c_) = tmp2(ixo^s)+&
1763  twofl_kin_en_c(w,ixi^l,ixo^l)
1764  end where
1765  endif
1766  if(phys_solve_eaux) then
1767  where(flag(ixo^s,e_c_))
1768  w(ixo^s,eaux_c_)=tmp2(ixo^s)
1769  end where
1770  end if
1771  end if
1772  end if
1773  end if
1774  case ("average")
1775  call small_values_average(ixi^l, ixo^l, w, x, flag)
1776  case default
1777  if(.not.primitive) then
1778  !convert w to primitive
1779  ! Calculate pressure = (gamma-1) * (e-ek-eb)
1780  if(phys_energy) then
1781  if(phys_internal_e) then
1782  w(ixo^s,e_c_)=w(ixo^s,e_c_)*gamma_1
1783  w(ixo^s,e_n_)=w(ixo^s,e_n_)*gamma_1
1784  else
1785  w(ixo^s,e_n_)=gamma_1*(w(ixo^s,e_n_)&
1786  -twofl_kin_en_n(w,ixi^l,ixo^l))
1787  if(phys_total_energy) then
1788  w(ixo^s,e_c_)=gamma_1*(w(ixo^s,e_c_)&
1789  -twofl_kin_en_c(w,ixi^l,ixo^l)&
1790  -twofl_mag_en(w,ixi^l,ixo^l))
1791  else
1792  w(ixo^s,e_c_)=gamma_1*(w(ixo^s,e_c_)&
1793  -twofl_kin_en_c(w,ixi^l,ixo^l))
1794 
1795  endif
1796  if(phys_solve_eaux) w(ixo^s,eaux_c_)=w(ixo^s,eaux_c_)*gamma_1
1797  end if
1798  end if
1799  ! Convert momentum to velocity
1800  if(has_equi_rho_n0) then
1801  tmp1(ixo^s) = w(ixo^s,rho_n_) + block%equi_vars(ixo^s,equi_rho_n0_,0)
1802  else
1803  tmp1(ixo^s) = w(ixo^s,rho_n_)
1804  endif
1805 
1806  if(has_equi_rho_c0) then
1807  tmp2(ixo^s) = w(ixo^s,rho_c_) + block%equi_vars(ixo^s,equi_rho_c0_,0)
1808  else
1809  tmp2(ixo^s) = w(ixo^s,rho_c_)
1810  endif
1811  do idir = 1, ndir
1812  w(ixo^s, mom_n(idir)) = w(ixo^s, mom_n(idir))/tmp1(ixo^s)
1813  w(ixo^s, mom_c(idir)) = w(ixo^s, mom_c(idir))/tmp2(ixo^s)
1814  end do
1815  end if
1816  call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
1817  end select
1818  end if
1819  end subroutine twofl_handle_small_values
1820 
1821  !> Calculate cmax_idim=csound+abs(v_idim) within ixO^L
1822  subroutine twofl_get_cmax(w,x,ixI^L,ixO^L,idim,cmax)
1824 
1825  integer, intent(in) :: ixI^L, ixO^L, idim
1826  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
1827  double precision, intent(inout) :: cmax(ixI^S)
1828  double precision :: vc(ixI^S)
1829  double precision :: cmax2(ixI^S)
1830  double precision :: vn(ixI^S)
1831 
1832  call twofl_get_csound_c_idim(w,x,ixi^l,ixo^l,idim,cmax)
1833  call twofl_get_v_c_idim(w,x,ixi^l,ixo^l,idim,vc)
1834  call twofl_get_v_n_idim(w,x,ixi^l,ixo^l,idim,vn)
1835  call twofl_get_csound_n(w,x,ixi^l,ixo^l,cmax2)
1836  cmax(ixo^s)=max(abs(vn(ixo^s))+cmax2(ixo^s),&
1837  abs(vc(ixo^s))+cmax(ixo^s))
1838 
1839  end subroutine twofl_get_cmax
1840 
1841  subroutine twofl_get_a2max(w,x,ixI^L,ixO^L,a2max)
1843 
1844  integer, intent(in) :: ixI^L, ixO^L
1845  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
1846  double precision, intent(inout) :: a2max(ndim)
1847  double precision :: a2(ixI^S,ndim,nw)
1848  integer :: gxO^L,hxO^L,jxO^L,kxO^L,i,j
1849 
1850  a2=zero
1851  do i = 1,ndim
1852  !> 4th order
1853  hxo^l=ixo^l-kr(i,^d);
1854  gxo^l=hxo^l-kr(i,^d);
1855  jxo^l=ixo^l+kr(i,^d);
1856  kxo^l=jxo^l+kr(i,^d);
1857  a2(ixo^s,i,1:nw)=abs(-w(kxo^s,1:nw)+16.d0*w(jxo^s,1:nw)&
1858  -30.d0*w(ixo^s,1:nw)+16.d0*w(hxo^s,1:nw)-w(gxo^s,1:nw))
1859  a2max(i)=maxval(a2(ixo^s,i,1:nw))/12.d0/dxlevel(i)**2
1860  end do
1861  end subroutine twofl_get_a2max
1862 
1863  ! COPIED from hd/moh_hd_phys
1864  !> get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
1865  subroutine twofl_get_tcutoff_n(ixI^L,ixO^L,w,x,tco_local,Tmax_local)
1867  integer, intent(in) :: ixI^L,ixO^L
1868  double precision, intent(in) :: x(ixI^S,1:ndim),w(ixI^S,1:nw)
1869  double precision, intent(out) :: tco_local, Tmax_local
1870 
1871  double precision, parameter :: delta=0.25d0
1872  double precision :: tmp1(ixI^S),Te(ixI^S),lts(ixI^S)
1873  integer :: jxO^L,hxO^L
1874  logical :: lrlt(ixI^S)
1875 
1876  {^ifoned
1877  ! reuse lts as rhon
1878  call get_rhon_tot(w,x,ixi^l,ixi^l,lts)
1879  tmp1(ixi^s)=w(ixi^s,e_n_)-0.5d0*sum(w(ixi^s,mom_n(:))**2,dim=ndim+1)/lts(ixi^s)
1880  te(ixi^s)=tmp1(ixi^s)/lts(ixi^s)*(twofl_gamma-1.d0)
1881 
1882  tmax_local=maxval(te(ixo^s))
1883 
1884  hxo^l=ixo^l-1;
1885  jxo^l=ixo^l+1;
1886  lts(ixo^s)=0.5d0*abs(te(jxo^s)-te(hxo^s))/te(ixo^s)
1887  lrlt=.false.
1888  where(lts(ixo^s) > delta)
1889  lrlt(ixo^s)=.true.
1890  end where
1891  tco_local=zero
1892  if(any(lrlt(ixo^s))) then
1893  tco_local=maxval(te(ixo^s), mask=lrlt(ixo^s))
1894  end if
1895  }
1896  end subroutine twofl_get_tcutoff_n
1897 
1898  !> get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
1899  subroutine twofl_get_tcutoff_c(ixI^L,ixO^L,w,x,Tco_local,Tmax_local)
1901  use mod_geometry
1902  integer, intent(in) :: ixI^L,ixO^L
1903  double precision, intent(in) :: x(ixI^S,1:ndim)
1904  double precision, intent(inout) :: w(ixI^S,1:nw)
1905  double precision, intent(out) :: Tco_local,Tmax_local
1906 
1907  double precision, parameter :: trac_delta=0.25d0
1908  double precision :: tmp1(ixI^S),Te(ixI^S),lts(ixI^S)
1909  double precision, dimension(ixI^S,1:ndir) :: bunitvec
1910  double precision, dimension(ixI^S,1:ndim) :: gradT
1911  double precision :: Bdir(ndim)
1912  double precision :: ltr(ixI^S),ltrc,ltrp,altr(ixI^S)
1913  integer :: idims,jxO^L,hxO^L,ixA^D,ixB^D
1914  integer :: jxP^L,hxP^L,ixP^L
1915  logical :: lrlt(ixI^S)
1916 
1917  ! reuse lts as rhoc
1918  call get_rhoc_tot(w,x,ixi^l,ixi^l,lts)
1919  if(phys_internal_e) then
1920  tmp1(ixi^s)=w(ixi^s,e_c_)
1921  else
1922  tmp1(ixi^s)=w(ixi^s,e_c_)-0.5d0*(sum(w(ixi^s,mom_c(:))**2,dim=ndim+1)/&
1923  lts(ixi^s)+sum(w(ixi^s,mag(:))**2,dim=ndim+1))
1924  end if
1925  te(ixi^s)=tmp1(ixi^s)/lts(ixi^s)*(twofl_gamma-1.d0)
1926  tmax_local=maxval(te(ixo^s))
1927 
1928  {^ifoned
1929  select case(twofl_trac_type)
1930  case(0)
1931  !> test case, fixed cutoff temperature
1932  w(ixi^s,tcoff_c_)=2.5d5/unit_temperature
1933  case(1)
1934  hxo^l=ixo^l-1;
1935  jxo^l=ixo^l+1;
1936  lts(ixo^s)=0.5d0*abs(te(jxo^s)-te(hxo^s))/te(ixo^s)
1937  lrlt=.false.
1938  where(lts(ixo^s) > trac_delta)
1939  lrlt(ixo^s)=.true.
1940  end where
1941  if(any(lrlt(ixo^s))) then
1942  tco_local=maxval(te(ixo^s), mask=lrlt(ixo^s))
1943  end if
1944  case(2)
1945  !> iijima et al. 2021, LTRAC method
1946  ltrc=1.5d0
1947  ltrp=2.5d0
1948  ixp^l=ixo^l^ladd1;
1949  hxo^l=ixo^l-1;
1950  jxo^l=ixo^l+1;
1951  hxp^l=ixp^l-1;
1952  jxp^l=ixp^l+1;
1953  lts(ixp^s)=0.5d0*abs(te(jxp^s)-te(hxp^s))/te(ixp^s)
1954  ltr(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
1955  w(ixo^s,tcoff_c_)=te(ixo^s)*&
1956  (0.25*(ltr(jxo^s)+two*ltr(ixo^s)+ltr(hxo^s)))**0.4d0
1957  case default
1958  call mpistop("twofl_trac_type not allowed for 1D simulation")
1959  end select
1960  }
1961  {^nooned
1962  select case(twofl_trac_type)
1963  case(0)
1964  !> test case, fixed cutoff temperature
1965  w(ixi^s,tcoff_c_)=2.5d5/unit_temperature
1966  case(1,4,6)
1967  ! temperature gradient at cell centers
1968  do idims=1,ndim
1969  call gradient(te,ixi^l,ixo^l,idims,tmp1)
1970  gradt(ixo^s,idims)=tmp1(ixo^s)
1971  end do
1972  ! B vector
1973  if(b0field) then
1974  bunitvec(ixo^s,:)=w(ixo^s,iw_mag(:))+block%B0(ixo^s,:,0)
1975  else
1976  bunitvec(ixo^s,:)=w(ixo^s,iw_mag(:))
1977  end if
1978  if(twofl_trac_type .gt. 1) then
1979  ! B direction at cell center
1980  bdir=zero
1981  {do ixa^d=0,1\}
1982  ixb^d=(ixomin^d+ixomax^d-1)/2+ixa^d;
1983  bdir(1:ndim)=bdir(1:ndim)+bunitvec(ixb^d,1:ndim)
1984  {end do\}
1985  if(sum(bdir(:)**2) .gt. zero) then
1986  bdir(1:ndim)=bdir(1:ndim)/dsqrt(sum(bdir(:)**2))
1987  end if
1988  block%special_values(3:ndim+2)=bdir(1:ndim)
1989  end if
1990  tmp1(ixo^s)=dsqrt(sum(bunitvec(ixo^s,:)**2,dim=ndim+1))
1991  where(tmp1(ixo^s)/=0.d0)
1992  tmp1(ixo^s)=1.d0/tmp1(ixo^s)
1993  elsewhere
1994  tmp1(ixo^s)=bigdouble
1995  end where
1996  ! b unit vector: magnetic field direction vector
1997  do idims=1,ndim
1998  bunitvec(ixo^s,idims)=bunitvec(ixo^s,idims)*tmp1(ixo^s)
1999  end do
2000  ! temperature length scale inversed
2001  lts(ixo^s)=abs(sum(gradt(ixo^s,1:ndim)*bunitvec(ixo^s,1:ndim),dim=ndim+1))/te(ixo^s)
2002  ! fraction of cells size to temperature length scale
2003  if(slab_uniform) then
2004  lts(ixo^s)=minval(dxlevel)*lts(ixo^s)
2005  else
2006  lts(ixo^s)=minval(block%ds(ixo^s,:),dim=ndim+1)*lts(ixo^s)
2007  end if
2008  lrlt=.false.
2009  where(lts(ixo^s) > trac_delta)
2010  lrlt(ixo^s)=.true.
2011  end where
2012  if(any(lrlt(ixo^s))) then
2013  block%special_values(1)=maxval(te(ixo^s), mask=lrlt(ixo^s))
2014  else
2015  block%special_values(1)=zero
2016  end if
2017  block%special_values(2)=tmax_local
2018  case(2)
2019  !> iijima et al. 2021, LTRAC method
2020  ltrc=1.5d0
2021  ltrp=4.d0
2022  ixp^l=ixo^l^ladd1;
2023  ! temperature gradient at cell centers
2024  do idims=1,ndim
2025  call gradient(te,ixi^l,ixp^l,idims,tmp1)
2026  gradt(ixp^s,idims)=tmp1(ixp^s)
2027  end do
2028  ! B vector
2029  if(b0field) then
2030  bunitvec(ixp^s,:)=w(ixp^s,iw_mag(:))+block%B0(ixp^s,:,0)
2031  else
2032  bunitvec(ixp^s,:)=w(ixp^s,iw_mag(:))
2033  end if
2034  tmp1(ixp^s)=dsqrt(sum(bunitvec(ixp^s,:)**2,dim=ndim+1))
2035  where(tmp1(ixp^s)/=0.d0)
2036  tmp1(ixp^s)=1.d0/tmp1(ixp^s)
2037  elsewhere
2038  tmp1(ixp^s)=bigdouble
2039  end where
2040  ! b unit vector: magnetic field direction vector
2041  do idims=1,ndim
2042  bunitvec(ixp^s,idims)=bunitvec(ixp^s,idims)*tmp1(ixp^s)
2043  end do
2044  ! temperature length scale inversed
2045  lts(ixp^s)=abs(sum(gradt(ixp^s,1:ndim)*bunitvec(ixp^s,1:ndim),dim=ndim+1))/te(ixp^s)
2046  ! fraction of cells size to temperature length scale
2047  if(slab_uniform) then
2048  lts(ixp^s)=minval(dxlevel)*lts(ixp^s)
2049  else
2050  lts(ixp^s)=minval(block%ds(ixp^s,:),dim=ndim+1)*lts(ixp^s)
2051  end if
2052  ltr(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
2053 
2054  altr(ixi^s)=zero
2055  do idims=1,ndim
2056  hxo^l=ixo^l-kr(idims,^d);
2057  jxo^l=ixo^l+kr(idims,^d);
2058  altr(ixo^s)=altr(ixo^s) &
2059  +0.25*(ltr(hxo^s)+two*ltr(ixo^s)+ltr(jxo^s))*bunitvec(ixo^s,idims)**2
2060  w(ixo^s,tcoff_c_)=te(ixo^s)*altr(ixo^s)**(0.4*ltrp)
2061  end do
2062  case(3,5)
2063  !> do nothing here
2064  case default
2065  call mpistop("unknown twofl_trac_type")
2066  end select
2067  }
2068  end subroutine twofl_get_tcutoff_c
2069 
2070  !> get H speed for H-correction to fix the carbuncle problem at grid-aligned shock front
2071  subroutine twofl_get_h_speed_one(wprim,x,ixI^L,ixO^L,idim,Hspeed)
2073 
2074  integer, intent(in) :: ixI^L, ixO^L, idim
2075  double precision, intent(in) :: wprim(ixI^S, nw)
2076  double precision, intent(in) :: x(ixI^S,1:ndim)
2077  double precision, intent(out) :: Hspeed(ixI^S,1:number_species)
2078 
2079  double precision :: csound(ixI^S,ndim),tmp(ixI^S)
2080  integer :: jxC^L, ixC^L, ixA^L, id, ix^D
2081 
2082  hspeed=0.d0
2083  ixa^l=ixo^l^ladd1;
2084  do id=1,ndim
2085  call twofl_get_csound_prim(wprim,x,ixi^l,ixa^l,id,tmp)
2086  csound(ixa^s,id)=tmp(ixa^s)
2087  end do
2088  ixcmax^d=ixomax^d;
2089  ixcmin^d=ixomin^d+kr(idim,^d)-1;
2090  jxcmax^d=ixcmax^d+kr(idim,^d);
2091  jxcmin^d=ixcmin^d+kr(idim,^d);
2092  hspeed(ixc^s,1)=0.5d0*abs(&
2093  0.5d0 * (wprim(jxc^s,mom_c(idim))+ wprim(jxc^s,mom_n(idim))) &
2094  +csound(jxc^s,idim)- &
2095  0.5d0 * (wprim(ixc^s,mom_c(idim)) + wprim(ixc^s,mom_n(idim)))&
2096  +csound(ixc^s,idim))
2097 
2098  do id=1,ndim
2099  if(id==idim) cycle
2100  ixamax^d=ixcmax^d+kr(id,^d);
2101  ixamin^d=ixcmin^d+kr(id,^d);
2102  hspeed(ixc^s,1)=max(hspeed(ixc^s,1),0.5d0*abs(&
2103  0.5d0 * (wprim(ixa^s,mom_c(id)) + wprim(ixa^s,mom_n(id)))&
2104  +csound(ixa^s,id)-&
2105  0.5d0 * (wprim(ixc^s,mom_c(id)) + wprim(ixc^s,mom_n(id)))&
2106  +csound(ixc^s,id)))
2107 
2108 
2109  ixamax^d=ixcmax^d-kr(id,^d);
2110  ixamin^d=ixcmin^d-kr(id,^d);
2111  hspeed(ixc^s,1)=max(hspeed(ixc^s,1),0.5d0*abs(&
2112  0.5d0 * (wprim(ixc^s,mom_c(id)) + wprim(ixc^s,mom_n(id)))&
2113  +csound(ixc^s,id)-&
2114  0.5d0 * (wprim(ixa^s,mom_c(id)) + wprim(ixa^s,mom_n(id)))&
2115  +csound(ixa^s,id)))
2116 
2117  end do
2118 
2119  do id=1,ndim
2120  if(id==idim) cycle
2121  ixamax^d=jxcmax^d+kr(id,^d);
2122  ixamin^d=jxcmin^d+kr(id,^d);
2123  hspeed(ixc^s,1)=max(hspeed(ixc^s,1),0.5d0*abs(&
2124  0.5d0 * (wprim(ixa^s,mom_c(id)) + wprim(ixa^s,mom_n(id)))&
2125  +csound(ixa^s,id)-&
2126  0.5d0 * (wprim(jxc^s,mom_c(id)) + wprim(jxc^s,mom_n(id)))&
2127  +csound(jxc^s,id)))
2128  ixamax^d=jxcmax^d-kr(id,^d);
2129  ixamin^d=jxcmin^d-kr(id,^d);
2130  hspeed(ixc^s,1)=max(hspeed(ixc^s,1),0.5d0*abs(&
2131  0.5d0 * (wprim(jxc^s,mom_c(id)) + wprim(jxc^s,mom_n(id)))&
2132  +csound(jxc^s,id)-&
2133  0.5d0 * (wprim(ixa^s,mom_c(id)) + wprim(ixa^s,mom_n(id)))&
2134  +csound(ixa^s,id)))
2135  end do
2136 
2137  end subroutine twofl_get_h_speed_one
2138 
2139  !> get H speed for H-correction to fix the carbuncle problem at grid-aligned shock front
2140  subroutine twofl_get_h_speed_species(wprim,x,ixI^L,ixO^L,idim,Hspeed)
2142 
2143  integer, intent(in) :: ixI^L, ixO^L, idim
2144  double precision, intent(in) :: wprim(ixI^S, nw)
2145  double precision, intent(in) :: x(ixI^S,1:ndim)
2146  double precision, intent(out) :: Hspeed(ixI^S,1:number_species)
2147 
2148  double precision :: csound(ixI^S,ndim),tmp(ixI^S)
2149  integer :: jxC^L, ixC^L, ixA^L, id, ix^D
2150 
2151  hspeed=0.d0
2152  ! charges
2153  ixa^l=ixo^l^ladd1;
2154  do id=1,ndim
2155  call twofl_get_csound_prim_c(wprim,x,ixi^l,ixa^l,id,tmp)
2156  csound(ixa^s,id)=tmp(ixa^s)
2157  end do
2158  ixcmax^d=ixomax^d;
2159  ixcmin^d=ixomin^d+kr(idim,^d)-1;
2160  jxcmax^d=ixcmax^d+kr(idim,^d);
2161  jxcmin^d=ixcmin^d+kr(idim,^d);
2162  hspeed(ixc^s,1)=0.5d0*abs(wprim(jxc^s,mom_c(idim))+csound(jxc^s,idim)-wprim(ixc^s,mom_c(idim))+csound(ixc^s,idim))
2163 
2164  do id=1,ndim
2165  if(id==idim) cycle
2166  ixamax^d=ixcmax^d+kr(id,^d);
2167  ixamin^d=ixcmin^d+kr(id,^d);
2168  hspeed(ixc^s,1)=max(hspeed(ixc^s,1),0.5d0*abs(wprim(ixa^s,mom_c(id))+csound(ixa^s,id)-wprim(ixc^s,mom_c(id))+csound(ixc^s,id)))
2169  ixamax^d=ixcmax^d-kr(id,^d);
2170  ixamin^d=ixcmin^d-kr(id,^d);
2171  hspeed(ixc^s,1)=max(hspeed(ixc^s,1),0.5d0*abs(wprim(ixc^s,mom_c(id))+csound(ixc^s,id)-wprim(ixa^s,mom_c(id))+csound(ixa^s,id)))
2172  end do
2173 
2174  do id=1,ndim
2175  if(id==idim) cycle
2176  ixamax^d=jxcmax^d+kr(id,^d);
2177  ixamin^d=jxcmin^d+kr(id,^d);
2178  hspeed(ixc^s,1)=max(hspeed(ixc^s,1),0.5d0*abs(wprim(ixa^s,mom_c(id))+csound(ixa^s,id)-wprim(jxc^s,mom_c(id))+csound(jxc^s,id)))
2179  ixamax^d=jxcmax^d-kr(id,^d);
2180  ixamin^d=jxcmin^d-kr(id,^d);
2181  hspeed(ixc^s,1)=max(hspeed(ixc^s,1),0.5d0*abs(wprim(jxc^s,mom_c(id))+csound(jxc^s,id)-wprim(ixa^s,mom_c(id))+csound(ixa^s,id)))
2182  end do
2183 
2184  ! neutrals
2185  ixa^l=ixo^l^ladd1;
2186  do id=1,ndim
2187  call twofl_get_csound_prim_n(wprim,x,ixi^l,ixa^l,id,tmp)
2188  csound(ixa^s,id)=tmp(ixa^s)
2189  end do
2190  ixcmax^d=ixomax^d;
2191  ixcmin^d=ixomin^d+kr(idim,^d)-1;
2192  jxcmax^d=ixcmax^d+kr(idim,^d);
2193  jxcmin^d=ixcmin^d+kr(idim,^d);
2194  hspeed(ixc^s,2)=0.5d0*abs(wprim(jxc^s,mom_n(idim))+csound(jxc^s,idim)-wprim(ixc^s,mom_n(idim))+csound(ixc^s,idim))
2195 
2196  do id=1,ndim
2197  if(id==idim) cycle
2198  ixamax^d=ixcmax^d+kr(id,^d);
2199  ixamin^d=ixcmin^d+kr(id,^d);
2200  hspeed(ixc^s,2)=max(hspeed(ixc^s,2),0.5d0*abs(wprim(ixa^s,mom_n(id))+csound(ixa^s,id)-wprim(ixc^s,mom_n(id))+csound(ixc^s,id)))
2201  ixamax^d=ixcmax^d-kr(id,^d);
2202  ixamin^d=ixcmin^d-kr(id,^d);
2203  hspeed(ixc^s,2)=max(hspeed(ixc^s,2),0.5d0*abs(wprim(ixc^s,mom_n(id))+csound(ixc^s,id)-wprim(ixa^s,mom_n(id))+csound(ixa^s,id)))
2204  end do
2205 
2206  do id=1,ndim
2207  if(id==idim) cycle
2208  ixamax^d=jxcmax^d+kr(id,^d);
2209  ixamin^d=jxcmin^d+kr(id,^d);
2210  hspeed(ixc^s,2)=max(hspeed(ixc^s,2),0.5d0*abs(wprim(ixa^s,mom_n(id))+csound(ixa^s,id)-wprim(jxc^s,mom_n(id))+csound(jxc^s,id)))
2211  ixamax^d=jxcmax^d-kr(id,^d);
2212  ixamin^d=jxcmin^d-kr(id,^d);
2213  hspeed(ixc^s,2)=max(hspeed(ixc^s,2),0.5d0*abs(wprim(jxc^s,mom_n(id))+csound(jxc^s,id)-wprim(ixa^s,mom_n(id))+csound(ixa^s,id)))
2214  end do
2215 
2216  end subroutine twofl_get_h_speed_species
2217 
2218  !> Estimating bounds for the minimum and maximum signal velocities
2219  subroutine twofl_get_cbounds_one(wLC,wRC,wLp,wRp,x,ixI^L,ixO^L,idim,Hspeed,cmax,cmin)
2222 
2223  integer, intent(in) :: ixI^L, ixO^L, idim
2224  double precision, intent(in) :: wLC(ixI^S, nw), wRC(ixI^S, nw)
2225  double precision, intent(in) :: wLp(ixI^S, nw), wRp(ixI^S, nw)
2226  double precision, intent(in) :: x(ixI^S,1:ndim)
2227  double precision, intent(inout) :: cmax(ixI^S,number_species)
2228  double precision, intent(inout), optional :: cmin(ixI^S,number_species)
2229  double precision, intent(in) :: Hspeed(ixI^S,1:number_species)
2230 
2231  double precision :: wmean(ixI^S,nw)
2232  double precision :: rhon(ixI^S)
2233  double precision :: rhoc(ixI^S)
2234  double precision, dimension(ixI^S) :: umean, dmean, csoundL, csoundR, tmp1,tmp2,tmp3
2235  integer :: ix^D
2236 
2237  select case (boundspeed)
2238  case (1)
2239  ! This implements formula (10.52) from "Riemann Solvers and Numerical
2240  ! Methods for Fluid Dynamics" by Toro.
2241  call get_rhoc_tot(wlp,x,ixi^l,ixo^l,rhoc)
2242  call get_rhon_tot(wlp,x,ixi^l,ixo^l,rhon)
2243  tmp1(ixo^s)=sqrt(abs(rhoc(ixo^s) +rhon(ixo^s)))
2244 
2245  call get_rhoc_tot(wrp,x,ixi^l,ixo^l,rhoc)
2246  call get_rhon_tot(wrp,x,ixi^l,ixo^l,rhon)
2247  tmp2(ixo^s)=sqrt(abs(rhoc(ixo^s) +rhon(ixo^s)))
2248 
2249  tmp3(ixo^s)=1.d0/(tmp1(ixo^s)+tmp2(ixo^s))
2250  umean(ixo^s)=(0.5*(wlp(ixo^s,mom_n(idim))+wlp(ixo^s,mom_c(idim)))*tmp1(ixo^s) + &
2251  0.5*(wrp(ixo^s,mom_n(idim))+wrp(ixo^s,mom_c(idim)))*tmp2(ixo^s))*tmp3(ixo^s)
2252  call twofl_get_csound_prim(wlp,x,ixi^l,ixo^l,idim,csoundl)
2253  call twofl_get_csound_prim(wrp,x,ixi^l,ixo^l,idim,csoundr)
2254 
2255  dmean(ixo^s)=(tmp1(ixo^s)*csoundl(ixo^s)**2+tmp2(ixo^s)*csoundr(ixo^s)**2)*tmp3(ixo^s)+&
2256  0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2*(&
2257  0.5*(wrp(ixo^s,mom_n(idim))+wrp(ixo^s,mom_c(idim)))- &
2258  0.5*(wlp(ixo^s,mom_n(idim))+wlp(ixo^s,mom_c(idim))))**2
2259  dmean(ixo^s)=sqrt(dmean(ixo^s))
2260  if(present(cmin)) then
2261  cmin(ixo^s,1)=umean(ixo^s)-dmean(ixo^s)
2262  cmax(ixo^s,1)=umean(ixo^s)+dmean(ixo^s)
2263  if(h_correction) then
2264  {do ix^db=ixomin^db,ixomax^db\}
2265  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
2266  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
2267  {end do\}
2268  end if
2269  else
2270  cmax(ixo^s,1)=abs(umean(ixo^s))+dmean(ixo^s)
2271  end if
2272  case (2)
2273  ! typeboundspeed=='cmaxmean'
2274  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
2275  call get_rhon_tot(wmean,x,ixi^l,ixo^l,rhon)
2276  tmp2(ixo^s)=wmean(ixo^s,mom_n(idim))/rhon(ixo^s)
2277  call get_rhoc_tot(wmean,x,ixi^l,ixo^l,rhoc)
2278  tmp1(ixo^s)=wmean(ixo^s,mom_c(idim))/rhoc(ixo^s)
2279  call twofl_get_csound(wmean,x,ixi^l,ixo^l,idim,csoundr)
2280  if(present(cmin)) then
2281  cmax(ixo^s,1)=max(max(abs(tmp2(ixo^s)), abs(tmp1(ixo^s)) ) +csoundr(ixo^s),zero)
2282  cmin(ixo^s,1)=min(min(abs(tmp2(ixo^s)), abs(tmp1(ixo^s)) ) -csoundr(ixo^s),zero)
2283  if(h_correction) then
2284  {do ix^db=ixomin^db,ixomax^db\}
2285  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
2286  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
2287  {end do\}
2288  end if
2289  else
2290  cmax(ixo^s,1)= max(abs(tmp2(ixo^s)),abs(tmp1(ixo^s)))+csoundr(ixo^s)
2291  end if
2292  case (3)
2293  ! Miyoshi 2005 JCP 208, 315 equation (67)
2294  call twofl_get_csound(wlp,x,ixi^l,ixo^l,idim,csoundl)
2295  call twofl_get_csound(wrp,x,ixi^l,ixo^l,idim,csoundr)
2296  csoundl(ixo^s)=max(csoundl(ixo^s),csoundr(ixo^s))
2297  if(present(cmin)) then
2298  cmin(ixo^s,1)=min(0.5*(wlp(ixo^s,mom_c(idim))+ wrp(ixo^s,mom_n(idim))),&
2299  0.5*(wrp(ixo^s,mom_c(idim))+ wrp(ixo^s,mom_n(idim))))-csoundl(ixo^s)
2300  cmax(ixo^s,1)=max(0.5*(wlp(ixo^s,mom_c(idim))+ wrp(ixo^s,mom_n(idim))),&
2301  0.5*(wrp(ixo^s,mom_c(idim))+ wrp(ixo^s,mom_n(idim))))+csoundl(ixo^s)
2302  if(h_correction) then
2303  {do ix^db=ixomin^db,ixomax^db\}
2304  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
2305  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
2306  {end do\}
2307  end if
2308  else
2309  cmax(ixo^s,1)=max(0.5*(wlp(ixo^s,mom_c(idim))+ wrp(ixo^s,mom_n(idim))),&
2310  0.5*(wrp(ixo^s,mom_c(idim))+ wrp(ixo^s,mom_n(idim))))+csoundl(ixo^s)
2311  end if
2312  end select
2313 
2314  end subroutine twofl_get_cbounds_one
2315 
2316  !> Calculate fast magnetosonic wave speed
2317  subroutine twofl_get_csound_prim_c(w,x,ixI^L,ixO^L,idim,csound)
2319 
2320  integer, intent(in) :: ixI^L, ixO^L, idim
2321  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
2322  double precision, intent(out):: csound(ixI^S)
2323  double precision :: cfast2(ixI^S), AvMinCs2(ixI^S), b2(ixI^S), kmax
2324  double precision :: inv_rho(ixO^S)
2325  double precision :: rhoc(ixI^S)
2326 
2327  integer :: ix1,ix2
2328 
2329 
2330  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
2331  inv_rho(ixo^s)=1.d0/rhoc(ixo^s)
2332 
2333  if(phys_energy) then
2334  call twofl_get_pthermal_c_primitive(w,x,ixi^l,ixo^l,csound)
2335  csound(ixo^s)=twofl_gamma*csound(ixo^s)/rhoc(ixo^s)
2336  else
2337  call twofl_get_csound2_adiab_c(w,x,ixi^l,ixo^l,csound)
2338  endif
2339 
2340  ! store |B|^2 in v
2341  b2(ixo^s) = twofl_mag_en_all(w,ixi^l,ixo^l)
2342  cfast2(ixo^s) = b2(ixo^s) * inv_rho(ixo^s)+csound(ixo^s)
2343  avmincs2(ixo^s) = cfast2(ixo^s)**2-4.0d0*csound(ixo^s) &
2344  * twofl_mag_i_all(w,ixi^l,ixo^l,idim)**2 &
2345  * inv_rho(ixo^s)
2346 
2347  where(avmincs2(ixo^s)<zero)
2348  avmincs2(ixo^s)=zero
2349  end where
2350 
2351  avmincs2(ixo^s)=sqrt(avmincs2(ixo^s))
2352 
2353  if (.not. twofl_hall) then
2354  csound(ixo^s) = sqrt(half*(cfast2(ixo^s)+avmincs2(ixo^s)))
2355  else
2356  ! take the Hall velocity into account:
2357  ! most simple estimate, high k limit:
2358  ! largest wavenumber supported by grid: Nyquist (in practise can reduce by some factor)
2359  kmax = dpi/min({dxlevel(^d)},bigdouble)*half
2360  csound(ixo^s) = max(sqrt(half*(cfast2(ixo^s)+avmincs2(ixo^s))), &
2361  twofl_etah * sqrt(b2(ixo^s))*inv_rho(ixo^s)*kmax)
2362  end if
2363 
2364  end subroutine twofl_get_csound_prim_c
2365 
2366  !> Calculate fast magnetosonic wave speed
2367  subroutine twofl_get_csound_prim_n(w,x,ixI^L,ixO^L,idim,csound)
2369 
2370  integer, intent(in) :: ixI^L, ixO^L, idim
2371  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
2372  double precision, intent(out):: csound(ixI^S)
2373  double precision :: rhon(ixI^S)
2374 
2375  if(phys_energy) then
2376  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
2377  call twofl_get_pthermal_n_primitive(w,x,ixi^l,ixo^l,csound)
2378  csound(ixo^s)=twofl_gamma*csound(ixo^s)/rhon(ixo^s)
2379  else
2380  call twofl_get_csound2_adiab_n(w,x,ixi^l,ixo^l,csound)
2381  endif
2382  csound(ixo^s) = sqrt(csound(ixo^s))
2383 
2384  end subroutine twofl_get_csound_prim_n
2385 
2386  !> Estimating bounds for the minimum and maximum signal velocities
2387  subroutine twofl_get_cbounds_species(wLC,wRC,wLp,wRp,x,ixI^L,ixO^L,idim,Hspeed,cmax,cmin)
2390  use mod_variables
2391 
2392  integer, intent(in) :: ixI^L, ixO^L, idim
2393  double precision, intent(in) :: wLC(ixI^S, nw), wRC(ixI^S, nw)
2394  double precision, intent(in) :: wLp(ixI^S, nw), wRp(ixI^S, nw)
2395  double precision, intent(in) :: x(ixI^S,1:ndim)
2396  double precision, intent(inout) :: cmax(ixI^S,1:number_species)
2397  double precision, intent(inout), optional :: cmin(ixI^S,1:number_species)
2398  double precision, intent(in) :: Hspeed(ixI^S,1:number_species)
2399 
2400  double precision :: wmean(ixI^S,nw)
2401  double precision :: rho(ixI^S)
2402  double precision, dimension(ixI^S) :: umean, dmean, csoundL, csoundR, tmp1,tmp2,tmp3
2403  integer :: ix^D
2404 
2405  select case (boundspeed)
2406  case (1)
2407  ! This implements formula (10.52) from "Riemann Solvers and Numerical
2408  ! Methods for Fluid Dynamics" by Toro.
2409  ! charges
2410  call get_rhoc_tot(wlp,x,ixi^l,ixo^l,rho)
2411  tmp1(ixo^s)=sqrt(abs(rho(ixo^s)))
2412 
2413  call get_rhoc_tot(wrp,x,ixi^l,ixo^l,rho)
2414  tmp2(ixo^s)=sqrt(abs(rho(ixo^s)))
2415 
2416  tmp3(ixo^s)=1.d0/(tmp1(ixo^s)+tmp2(ixo^s))
2417  umean(ixo^s)=(wlp(ixo^s,mom_c(idim))*tmp1(ixo^s)+wrp(ixo^s,mom_c(idim))*tmp2(ixo^s))*tmp3(ixo^s)
2418  call twofl_get_csound_prim_c(wlp,x,ixi^l,ixo^l,idim,csoundl)
2419  call twofl_get_csound_prim_c(wrp,x,ixi^l,ixo^l,idim,csoundr)
2420 
2421 
2422  dmean(ixo^s)=(tmp1(ixo^s)*csoundl(ixo^s)**2+tmp2(ixo^s)*csoundr(ixo^s)**2)*tmp3(ixo^s)+&
2423  0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2*&
2424  (wrp(ixo^s,mom_c(idim)) - wlp(ixo^s,mom_c(idim)))**2
2425  dmean(ixo^s)=sqrt(dmean(ixo^s))
2426  if(present(cmin)) then
2427  cmin(ixo^s,1)=umean(ixo^s)-dmean(ixo^s)
2428  cmax(ixo^s,1)=umean(ixo^s)+dmean(ixo^s)
2429  if(h_correction) then
2430  {do ix^db=ixomin^db,ixomax^db\}
2431  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
2432  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
2433  {end do\}
2434  end if
2435  else
2436  cmax(ixo^s,1)=abs(umean(ixo^s))+dmean(ixo^s)
2437  end if
2438 
2439  ! neutrals
2440 
2441  call get_rhon_tot(wlp,x,ixi^l,ixo^l,rho)
2442  tmp1(ixo^s)=sqrt(abs(rho(ixo^s)))
2443 
2444  call get_rhon_tot(wrp,x,ixi^l,ixo^l,rho)
2445  tmp2(ixo^s)=sqrt(abs(rho(ixo^s)))
2446 
2447  tmp3(ixo^s)=1.d0/(tmp1(ixo^s)+tmp2(ixo^s))
2448  umean(ixo^s)=(wlp(ixo^s,mom_n(idim))*tmp1(ixo^s)+wrp(ixo^s,mom_n(idim))*tmp2(ixo^s))*tmp3(ixo^s)
2449  call twofl_get_csound_prim_n(wlp,x,ixi^l,ixo^l,idim,csoundl)
2450  call twofl_get_csound_prim_n(wrp,x,ixi^l,ixo^l,idim,csoundr)
2451 
2452 
2453  dmean(ixo^s)=(tmp1(ixo^s)*csoundl(ixo^s)**2+tmp2(ixo^s)*csoundr(ixo^s)**2)*tmp3(ixo^s)+&
2454  0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2*&
2455  (wrp(ixo^s,mom_n(idim)) - wlp(ixo^s,mom_n(idim)))**2
2456  dmean(ixo^s)=sqrt(dmean(ixo^s))
2457  if(present(cmin)) then
2458  cmin(ixo^s,2)=umean(ixo^s)-dmean(ixo^s)
2459  cmax(ixo^s,2)=umean(ixo^s)+dmean(ixo^s)
2460  if(h_correction) then
2461  {do ix^db=ixomin^db,ixomax^db\}
2462  cmin(ix^d,2)=sign(one,cmin(ix^d,2))*max(abs(cmin(ix^d,2)),hspeed(ix^d,2))
2463  cmax(ix^d,2)=sign(one,cmax(ix^d,2))*max(abs(cmax(ix^d,2)),hspeed(ix^d,2))
2464  {end do\}
2465  end if
2466  else
2467  cmax(ixo^s,2)=abs(umean(ixo^s))+dmean(ixo^s)
2468  end if
2469 
2470  case (2)
2471  ! typeboundspeed=='cmaxmean'
2472  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
2473  ! charges
2474 
2475  call get_rhoc_tot(wmean,x,ixi^l,ixo^l,rho)
2476  tmp1(ixo^s)=wmean(ixo^s,mom_c(idim))/rho(ixo^s)
2477  call twofl_get_csound_c_idim(wmean,x,ixi^l,ixo^l,idim,csoundr)
2478  if(present(cmin)) then
2479  cmax(ixo^s,1)=max(abs(tmp1(ixo^s))+csoundr(ixo^s),zero)
2480  cmin(ixo^s,1)=min(abs(tmp1(ixo^s))-csoundr(ixo^s),zero)
2481  if(h_correction) then
2482  {do ix^db=ixomin^db,ixomax^db\}
2483  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
2484  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
2485  {end do\}
2486  end if
2487  else
2488  cmax(ixo^s,1)=abs(tmp1(ixo^s))+csoundr(ixo^s)
2489  end if
2490  !neutrals
2491 
2492  call get_rhon_tot(wmean,x,ixi^l,ixo^l,rho)
2493  tmp1(ixo^s)=wmean(ixo^s,mom_n(idim))/rho(ixo^s)
2494  call twofl_get_csound_n(wmean,x,ixi^l,ixo^l,csoundr)
2495  if(present(cmin)) then
2496  cmax(ixo^s,2)=max(abs(tmp1(ixo^s))+csoundr(ixo^s),zero)
2497  cmin(ixo^s,2)=min(abs(tmp1(ixo^s))-csoundr(ixo^s),zero)
2498  if(h_correction) then
2499  {do ix^db=ixomin^db,ixomax^db\}
2500  cmin(ix^d,2)=sign(one,cmin(ix^d,2))*max(abs(cmin(ix^d,2)),hspeed(ix^d,2))
2501  cmax(ix^d,2)=sign(one,cmax(ix^d,2))*max(abs(cmax(ix^d,2)),hspeed(ix^d,2))
2502  {end do\}
2503  end if
2504  else
2505  cmax(ixo^s,2)= abs(tmp1(ixo^s))+csoundr(ixo^s)
2506  end if
2507  case (3)
2508  ! Miyoshi 2005 JCP 208, 315 equation (67)
2509  call twofl_get_csound_c_idim(wlp,x,ixi^l,ixo^l,idim,csoundl)
2510  call twofl_get_csound_c_idim(wrp,x,ixi^l,ixo^l,idim,csoundr)
2511  csoundl(ixo^s)=max(csoundl(ixo^s),csoundr(ixo^s))
2512  if(present(cmin)) then
2513  cmin(ixo^s,1)=min(wlp(ixo^s,mom_c(idim)),wrp(ixo^s,mom_c(idim)))-csoundl(ixo^s)
2514  cmax(ixo^s,1)=max(wlp(ixo^s,mom_c(idim)),wrp(ixo^s,mom_c(idim)))+csoundl(ixo^s)
2515  if(h_correction) then
2516  {do ix^db=ixomin^db,ixomax^db\}
2517  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
2518  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
2519  {end do\}
2520  end if
2521  else
2522  cmax(ixo^s,1)=max(wlp(ixo^s,mom_c(idim)),wrp(ixo^s,mom_c(idim)))+csoundl(ixo^s)
2523  end if
2524  call twofl_get_csound_n(wlp,x,ixi^l,ixo^l,csoundl)
2525  call twofl_get_csound_n(wrp,x,ixi^l,ixo^l,csoundr)
2526  csoundl(ixo^s)=max(csoundl(ixo^s),csoundr(ixo^s))
2527  if(present(cmin)) then
2528  cmin(ixo^s,2)=min(wlp(ixo^s,mom_n(idim)),wrp(ixo^s,mom_n(idim)))-csoundl(ixo^s)
2529  cmax(ixo^s,2)=max(wlp(ixo^s,mom_n(idim)),wrp(ixo^s,mom_n(idim)))+csoundl(ixo^s)
2530  if(h_correction) then
2531  {do ix^db=ixomin^db,ixomax^db\}
2532  cmin(ix^d,2)=sign(one,cmin(ix^d,2))*max(abs(cmin(ix^d,1)),hspeed(ix^d,2))
2533  cmax(ix^d,2)=sign(one,cmax(ix^d,2))*max(abs(cmax(ix^d,1)),hspeed(ix^d,2))
2534  {end do\}
2535  end if
2536  else
2537  cmax(ixo^s,2)=max(wlp(ixo^s,mom_n(idim)),wrp(ixo^s,mom_n(idim)))+csoundl(ixo^s)
2538  end if
2539 
2540  end select
2541 
2542  end subroutine twofl_get_cbounds_species
2543 
2544  !> prepare velocities for ct methods
2545  subroutine twofl_get_ct_velocity(vcts,wLp,wRp,ixI^L,ixO^L,idim,cmax,cmin)
2547 
2548  integer, intent(in) :: ixI^L, ixO^L, idim
2549  double precision, intent(in) :: wLp(ixI^S, nw), wRp(ixI^S, nw)
2550  double precision, intent(in) :: cmax(ixI^S)
2551  double precision, intent(in), optional :: cmin(ixI^S)
2552  type(ct_velocity), intent(inout):: vcts
2553 
2554  integer :: idimE,idimN
2555 
2556  ! calculate velocities related to different UCT schemes
2557  select case(type_ct)
2558  case('average')
2559  case('uct_contact')
2560  if(.not.allocated(vcts%vnorm)) allocate(vcts%vnorm(ixi^s,1:ndim))
2561  ! get average normal velocity at cell faces
2562  vcts%vnorm(ixo^s,idim)=0.5d0*(wlp(ixo^s,mom_c(idim))+wrp(ixo^s,mom_c(idim)))
2563  case('uct_hll')
2564  if(.not.allocated(vcts%vbarC)) then
2565  allocate(vcts%vbarC(ixi^s,1:ndir,2),vcts%vbarLC(ixi^s,1:ndir,2),vcts%vbarRC(ixi^s,1:ndir,2))
2566  allocate(vcts%cbarmin(ixi^s,1:ndim),vcts%cbarmax(ixi^s,1:ndim))
2567  end if
2568  ! Store magnitude of characteristics
2569  if(present(cmin)) then
2570  vcts%cbarmin(ixo^s,idim)=max(-cmin(ixo^s),zero)
2571  vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
2572  else
2573  vcts%cbarmax(ixo^s,idim)=max( cmax(ixo^s),zero)
2574  vcts%cbarmin(ixo^s,idim)=vcts%cbarmax(ixo^s,idim)
2575  end if
2576 
2577  idimn=mod(idim,ndir)+1 ! 'Next' direction
2578  idime=mod(idim+1,ndir)+1 ! Electric field direction
2579  ! Store velocities
2580  vcts%vbarLC(ixo^s,idim,1)=wlp(ixo^s,mom_c(idimn))
2581  vcts%vbarRC(ixo^s,idim,1)=wrp(ixo^s,mom_c(idimn))
2582  vcts%vbarC(ixo^s,idim,1)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,1) &
2583  +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
2584  /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
2585 
2586  vcts%vbarLC(ixo^s,idim,2)=wlp(ixo^s,mom_c(idime))
2587  vcts%vbarRC(ixo^s,idim,2)=wrp(ixo^s,mom_c(idime))
2588  vcts%vbarC(ixo^s,idim,2)=(vcts%cbarmax(ixo^s,idim)*vcts%vbarLC(ixo^s,idim,2) &
2589  +vcts%cbarmin(ixo^s,idim)*vcts%vbarRC(ixo^s,idim,1))&
2590  /(vcts%cbarmax(ixo^s,idim)+vcts%cbarmin(ixo^s,idim))
2591  case default
2592  call mpistop('choose average, uct_contact,or uct_hll for type_ct!')
2593  end select
2594 
2595  end subroutine twofl_get_ct_velocity
2596 
2597  subroutine twofl_get_csound_c_idim(w,x,ixI^L,ixO^L,idim,csound)
2599 
2600  integer, intent(in) :: ixI^L, ixO^L, idim
2601  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
2602  double precision, intent(out):: csound(ixI^S)
2603  double precision :: cfast2(ixI^S), AvMinCs2(ixI^S), b2(ixI^S), kmax
2604  double precision :: inv_rho(ixO^S)
2605  double precision :: tmp(ixI^S)
2606 #if (!defined(ONE_FLUID) || ONE_FLUID==0) && (defined(A_TOT) && A_TOT == 1)
2607  double precision :: rhon(ixI^S)
2608 #endif
2609  call get_rhoc_tot(w,x,ixi^l,ixo^l,tmp)
2610 #if (!defined(ONE_FLUID) || ONE_FLUID==0) && (defined(A_TOT) && A_TOT == 1)
2611  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
2612  inv_rho(ixo^s) = 1d0/(rhon(ixo^s)+tmp(ixo^s))
2613 #else
2614  inv_rho(ixo^s)=1.d0/tmp(ixo^s)
2615 #endif
2616 
2617  call twofl_get_csound2_c_from_conserved(w,x,ixi^l,ixo^l,csound)
2618 
2619  ! store |B|^2 in v
2620  b2(ixo^s) = twofl_mag_en_all(w,ixi^l,ixo^l)
2621 
2622  cfast2(ixo^s) = b2(ixo^s) * inv_rho(ixo^s)+csound(ixo^s)
2623  avmincs2(ixo^s) = cfast2(ixo^s)**2-4.0d0*csound(ixo^s) &
2624  * twofl_mag_i_all(w,ixi^l,ixo^l,idim)**2 &
2625  * inv_rho(ixo^s)
2626 
2627  where(avmincs2(ixo^s)<zero)
2628  avmincs2(ixo^s)=zero
2629  end where
2630 
2631  avmincs2(ixo^s)=sqrt(avmincs2(ixo^s))
2632 
2633  if (.not. twofl_hall) then
2634  csound(ixo^s) = sqrt(half*(cfast2(ixo^s)+avmincs2(ixo^s)))
2635  else
2636  ! take the Hall velocity into account:
2637  ! most simple estimate, high k limit:
2638  ! largest wavenumber supported by grid: Nyquist (in practise can reduce by some factor)
2639  kmax = dpi/min({dxlevel(^d)},bigdouble)*half
2640  csound(ixo^s) = max(sqrt(half*(cfast2(ixo^s)+avmincs2(ixo^s))), &
2641  twofl_etah * sqrt(b2(ixo^s))*inv_rho(ixo^s)*kmax)
2642  end if
2643 
2644  end subroutine twofl_get_csound_c_idim
2645 
2646  !> Calculate fast magnetosonic wave speed when cbounds_species=false
2647  subroutine twofl_get_csound_prim(w,x,ixI^L,ixO^L,idim,csound)
2649 
2650  integer, intent(in) :: ixI^L, ixO^L, idim
2651  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
2652  double precision, intent(out):: csound(ixI^S)
2653  double precision :: cfast2(ixI^S), AvMinCs2(ixI^S), b2(ixI^S), kmax
2654  double precision :: inv_rho(ixO^S)
2655  double precision :: rhoc(ixI^S)
2656 #if (defined(A_TOT) && A_TOT == 1)
2657  double precision :: rhon(ixI^S)
2658 #endif
2659  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
2660 #if (defined(A_TOT) && A_TOT == 1)
2661  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
2662  inv_rho(ixo^s) = 1d0/(rhon(ixo^s)+rhoc(ixo^s))
2663 #else
2664  inv_rho(ixo^s)=1.d0/rhoc(ixo^s)
2665 #endif
2666 
2667  call twofl_get_csound2_primitive(w,x,ixi^l,ixo^l,csound)
2668 
2669  ! store |B|^2 in v
2670  b2(ixo^s) = twofl_mag_en_all(w,ixi^l,ixo^l)
2671  cfast2(ixo^s) = b2(ixo^s) * inv_rho(ixo^s)+csound(ixo^s)
2672  avmincs2(ixo^s) = cfast2(ixo^s)**2-4.0d0*csound(ixo^s) &
2673  * twofl_mag_i_all(w,ixi^l,ixo^l,idim)**2 &
2674  * inv_rho(ixo^s)
2675 
2676  where(avmincs2(ixo^s)<zero)
2677  avmincs2(ixo^s)=zero
2678  end where
2679 
2680  avmincs2(ixo^s)=sqrt(avmincs2(ixo^s))
2681 
2682  if (.not. twofl_hall) then
2683  csound(ixo^s) = sqrt(half*(cfast2(ixo^s)+avmincs2(ixo^s)))
2684  else
2685  ! take the Hall velocity into account:
2686  ! most simple estimate, high k limit:
2687  ! largest wavenumber supported by grid: Nyquist (in practise can reduce by some factor)
2688  kmax = dpi/min({dxlevel(^d)},bigdouble)*half
2689  csound(ixo^s) = max(sqrt(half*(cfast2(ixo^s)+avmincs2(ixo^s))), &
2690  twofl_etah * sqrt(b2(ixo^s))*inv_rho(ixo^s)*kmax)
2691  end if
2692 
2693  contains
2694  !TODO copy it inside
2695  subroutine twofl_get_csound2_primitive(w,x,ixI^L,ixO^L,csound2)
2697  integer, intent(in) :: ixI^L, ixO^L
2698  double precision, intent(in) :: w(ixI^S,nw)
2699  double precision, intent(in) :: x(ixI^S,1:ndim)
2700  double precision, intent(out) :: csound2(ixI^S)
2701  double precision :: pth_c(ixI^S)
2702  double precision :: pth_n(ixI^S)
2703 
2704  if(phys_energy) then
2705  call twofl_get_pthermal_c_primitive(w,x,ixi^l,ixo^l,pth_c)
2706  call twofl_get_pthermal_n_primitive(w,x,ixi^l,ixo^l,pth_n)
2707  call twofl_get_csound2_from_pthermal(w,x,ixi^l,ixo^l,pth_c,pth_n,csound2)
2708  else
2709  call twofl_get_csound2_adiab(w,x,ixi^l,ixo^l,csound2)
2710  endif
2711  end subroutine twofl_get_csound2_primitive
2712 
2713  end subroutine twofl_get_csound_prim
2714 
2715  subroutine twofl_get_csound2(w,x,ixI^L,ixO^L,csound2)
2717  integer, intent(in) :: ixI^L, ixO^L
2718  double precision, intent(in) :: w(ixI^S,nw)
2719  double precision, intent(in) :: x(ixI^S,1:ndim)
2720  double precision, intent(out) :: csound2(ixI^S)
2721  double precision :: pth_c(ixI^S)
2722  double precision :: pth_n(ixI^S)
2723 
2724  if(phys_energy) then
2725  call twofl_get_pthermal_c(w,x,ixi^l,ixo^l,pth_c)
2726  call twofl_get_pthermal_n(w,x,ixi^l,ixo^l,pth_n)
2727  call twofl_get_csound2_from_pthermal(w,x,ixi^l,ixo^l,pth_c,pth_n,csound2)
2728  else
2729  call twofl_get_csound2_adiab(w,x,ixi^l,ixo^l,csound2)
2730  endif
2731  end subroutine twofl_get_csound2
2732 
2733  subroutine twofl_get_csound2_adiab(w,x,ixI^L,ixO^L,csound2)
2735  integer, intent(in) :: ixI^L, ixO^L
2736  double precision, intent(in) :: w(ixI^S,nw)
2737  double precision, intent(in) :: x(ixI^S,1:ndim)
2738  double precision, intent(out) :: csound2(ixI^S)
2739  double precision :: rhoc(ixI^S)
2740  double precision :: rhon(ixI^S)
2741 
2742  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
2743  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
2744  csound2(ixo^s)=twofl_gamma*twofl_adiab*&
2745  max((rhoc(ixo^s)**twofl_gamma + rhon(ixo^s)**twofl_gamma)/(rhoc(ixo^s)+ rhon(ixo^s)),&
2746  rhon(ixo^s)**gamma_1,rhoc(ixo^s)**gamma_1)
2747  end subroutine twofl_get_csound2_adiab
2748 
2749  subroutine twofl_get_csound(w,x,ixI^L,ixO^L,idim,csound)
2751 
2752  integer, intent(in) :: ixI^L, ixO^L, idim
2753  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
2754  double precision, intent(out):: csound(ixI^S)
2755  double precision :: cfast2(ixI^S), AvMinCs2(ixI^S), b2(ixI^S), kmax
2756  double precision :: inv_rho(ixO^S)
2757  double precision :: rhoc(ixI^S)
2758 #if (defined(A_TOT) && A_TOT == 1)
2759  double precision :: rhon(ixI^S)
2760 #endif
2761  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
2762 #if (defined(A_TOT) && A_TOT == 1)
2763  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
2764  inv_rho(ixo^s) = 1d0/(rhon(ixo^s)+rhoc(ixo^s))
2765 #else
2766  inv_rho(ixo^s)=1.d0/rhoc(ixo^s)
2767 #endif
2768 
2769  call twofl_get_csound2(w,x,ixi^l,ixo^l,csound)
2770 
2771  ! store |B|^2 in v
2772  b2(ixo^s) = twofl_mag_en_all(w,ixi^l,ixo^l)
2773 
2774  cfast2(ixo^s) = b2(ixo^s) * inv_rho(ixo^s)+csound(ixo^s)
2775  avmincs2(ixo^s) = cfast2(ixo^s)**2-4.0d0*csound(ixo^s) &
2776  * twofl_mag_i_all(w,ixi^l,ixo^l,idim)**2 &
2777  * inv_rho(ixo^s)
2778 
2779  where(avmincs2(ixo^s)<zero)
2780  avmincs2(ixo^s)=zero
2781  end where
2782 
2783  avmincs2(ixo^s)=sqrt(avmincs2(ixo^s))
2784 
2785  if (.not. twofl_hall) then
2786  csound(ixo^s) = sqrt(half*(cfast2(ixo^s)+avmincs2(ixo^s)))
2787  else
2788  ! take the Hall velocity into account:
2789  ! most simple estimate, high k limit:
2790  ! largest wavenumber supported by grid: Nyquist (in practise can reduce by some factor)
2791  kmax = dpi/min({dxlevel(^d)},bigdouble)*half
2792  csound(ixo^s) = max(sqrt(half*(cfast2(ixo^s)+avmincs2(ixo^s))), &
2793  twofl_etah * sqrt(b2(ixo^s))*inv_rho(ixo^s)*kmax)
2794  end if
2795 
2796  end subroutine twofl_get_csound
2797 
2798  subroutine twofl_get_csound2_from_pthermal(w,x,ixI^L,ixO^L,pth_c,pth_n,csound2)
2800  integer, intent(in) :: ixI^L, ixO^L
2801  double precision, intent(in) :: w(ixI^S,nw)
2802  double precision, intent(in) :: x(ixI^S,1:ndim)
2803  double precision, intent(in) :: pth_c(ixI^S)
2804  double precision, intent(in) :: pth_n(ixI^S)
2805  double precision, intent(out) :: csound2(ixI^S)
2806  double precision :: csound1(ixI^S),rhon(ixI^S),rhoc(ixI^S)
2807 
2808  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
2809  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
2810 #if !defined(C_TOT) || C_TOT == 0
2811  csound2(ixo^s)=twofl_gamma*max((pth_c(ixo^s) + pth_n(ixo^s))/(rhoc(ixo^s) + rhon(ixo^s)),&
2812  pth_n(ixo^s)/rhon(ixo^s), pth_c(ixo^s)/rhoc(ixo^s))
2813 #else
2814  csound2(ixo^s)=twofl_gamma*(csound2(ixo^s) + csound1(ixo^s))/(rhoc(ixo^s) + rhon(ixo^s))
2815 
2816 #endif
2817  end subroutine twofl_get_csound2_from_pthermal
2818 
2819 ! end cbounds_species=false
2820 
2821  subroutine twofl_get_csound_n(w,x,ixI^L,ixO^L,csound)
2823 
2824  integer, intent(in) :: ixI^L, ixO^L
2825  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
2826  double precision, intent(out):: csound(ixI^S)
2827  double precision :: pe_n1(ixI^S)
2828  call twofl_get_csound2_n_from_conserved(w,x,ixi^l,ixo^l,csound)
2829  csound(ixo^s) = sqrt(csound(ixo^s))
2830  end subroutine twofl_get_csound_n
2831 
2832  !> separate routines so that it is faster
2833  !> Calculate temperature=p/rho when in e_ the internal energy is stored
2834  subroutine twofl_get_temperature_from_eint_n(w, x, ixI^L, ixO^L, res)
2836  integer, intent(in) :: ixI^L, ixO^L
2837  double precision, intent(in) :: w(ixI^S, 1:nw)
2838  double precision, intent(in) :: x(ixI^S, 1:ndim)
2839  double precision, intent(out):: res(ixI^S)
2840 
2841  res(ixo^s) = 1d0/rn * gamma_1 * w(ixo^s, e_n_) /w(ixo^s,rho_n_)
2842 
2843  end subroutine twofl_get_temperature_from_eint_n
2844 
2845  subroutine twofl_get_temperature_from_eint_n_with_equi(w, x, ixI^L, ixO^L, res)
2847  integer, intent(in) :: ixI^L, ixO^L
2848  double precision, intent(in) :: w(ixI^S, 1:nw)
2849  double precision, intent(in) :: x(ixI^S, 1:ndim)
2850  double precision, intent(out):: res(ixI^S)
2851 
2852  res(ixo^s) = 1d0/rn * (gamma_1 * w(ixo^s, e_n_) + block%equi_vars(ixo^s,equi_pe_n0_,b0i)) /&
2853  (w(ixo^s,rho_n_) +block%equi_vars(ixo^s,equi_rho_n0_,b0i))
2855 
2856 ! subroutine twofl_get_temperature_n_pert_from_tot(Te, ixI^L, ixO^L, res)
2857 ! use mod_global_parameters
2858 ! integer, intent(in) :: ixI^L, ixO^L
2859 ! double precision, intent(in) :: Te(ixI^S)
2860 ! double precision, intent(out):: res(ixI^S)
2861 ! res(ixO^S) = Te(ixO^S) -1d0/Rn * &
2862 ! block%equi_vars(ixO^S,equi_pe_n0_,0)/block%equi_vars(ixO^S,equi_rho_n0_,0)
2863 ! end subroutine twofl_get_temperature_n_pert_from_tot
2864 
2865  subroutine twofl_get_temperature_n_equi(w,x, ixI^L, ixO^L, res)
2867  integer, intent(in) :: ixI^L, ixO^L
2868  double precision, intent(in) :: w(ixI^S, 1:nw)
2869  double precision, intent(in) :: x(ixI^S, 1:ndim)
2870  double precision, intent(out):: res(ixI^S)
2871  res(ixo^s) = 1d0/rn * &
2872  block%equi_vars(ixo^s,equi_pe_n0_,b0i)/block%equi_vars(ixo^s,equi_rho_n0_,b0i)
2873  end subroutine twofl_get_temperature_n_equi
2874 
2875  subroutine twofl_get_rho_n_equi(w, x,ixI^L, ixO^L, res)
2877  integer, intent(in) :: ixI^L, ixO^L
2878  double precision, intent(in) :: w(ixI^S, 1:nw)
2879  double precision, intent(in) :: x(ixI^S, 1:ndim)
2880  double precision, intent(out):: res(ixI^S)
2881  res(ixo^s) = block%equi_vars(ixo^s,equi_rho_n0_,b0i)
2882  end subroutine twofl_get_rho_n_equi
2883 
2884  subroutine twofl_get_pe_n_equi(w, x, ixI^L, ixO^L, res)
2886  integer, intent(in) :: ixI^L, ixO^L
2887  double precision, intent(in) :: w(ixI^S, 1:nw)
2888  double precision, intent(in) :: x(ixI^S, 1:ndim)
2889  double precision, intent(out):: res(ixI^S)
2890  res(ixo^s) = block%equi_vars(ixo^s,equi_pe_n0_,b0i)
2891  end subroutine twofl_get_pe_n_equi
2892 
2893  !> Calculate temperature=p/rho when in e_ the total energy is stored
2894  !> this does not check the values of twofl_energy and twofl_internal_e,
2895  !> twofl_energy = .true. and twofl_internal_e = .false.
2896  !> also check small_values is avoided
2897  subroutine twofl_get_temperature_from_etot_n(w, x, ixI^L, ixO^L, res)
2899  integer, intent(in) :: ixI^L, ixO^L
2900  double precision, intent(in) :: w(ixI^S, 1:nw)
2901  double precision, intent(in) :: x(ixI^S, 1:ndim)
2902  double precision, intent(out):: res(ixI^S)
2903  res(ixo^s)=1d0/rn * (gamma_1*(w(ixo^s,e_n_)&
2904  - twofl_kin_en_n(w,ixi^l,ixo^l)))/w(ixo^s,rho_n_)
2905  end subroutine twofl_get_temperature_from_etot_n
2906 
2907  subroutine twofl_get_temperature_from_etot_n_with_equi(w, x, ixI^L, ixO^L, res)
2909  integer, intent(in) :: ixI^L, ixO^L
2910  double precision, intent(in) :: w(ixI^S, 1:nw)
2911  double precision, intent(in) :: x(ixI^S, 1:ndim)
2912  double precision, intent(out):: res(ixI^S)
2913  res(ixo^s)=1d0/rn * (gamma_1*(w(ixo^s,e_n_)&
2914  - twofl_kin_en_n(w,ixi^l,ixo^l)) + block%equi_vars(ixo^s,equi_pe_n0_,b0i))&
2915  /(w(ixo^s,rho_n_) +block%equi_vars(ixo^s,equi_rho_n0_,b0i))
2916 
2918 
2919  !> separate routines so that it is faster
2920  !> Calculate temperature=p/rho when in e_ the internal energy is stored
2921  subroutine twofl_get_temperature_from_eint_c(w, x, ixI^L, ixO^L, res)
2923  integer, intent(in) :: ixI^L, ixO^L
2924  double precision, intent(in) :: w(ixI^S, 1:nw)
2925  double precision, intent(in) :: x(ixI^S, 1:ndim)
2926  double precision, intent(out):: res(ixI^S)
2927 
2928  res(ixo^s) = 1d0/rc * gamma_1 * w(ixo^s, e_c_) /w(ixo^s,rho_c_)
2929 
2930  end subroutine twofl_get_temperature_from_eint_c
2931 
2932  subroutine twofl_get_temperature_from_eint_c_with_equi(w, x, ixI^L, ixO^L, res)
2934  integer, intent(in) :: ixI^L, ixO^L
2935  double precision, intent(in) :: w(ixI^S, 1:nw)
2936  double precision, intent(in) :: x(ixI^S, 1:ndim)
2937  double precision, intent(out):: res(ixI^S)
2938  res(ixo^s) = 1d0/rc * (gamma_1 * w(ixo^s, e_c_) + block%equi_vars(ixo^s,equi_pe_c0_,b0i)) /&
2939  (w(ixo^s,rho_c_) +block%equi_vars(ixo^s,equi_rho_c0_,b0i))
2941 
2942 ! subroutine twofl_get_temperature_c_pert_from_tot(Te, ixI^L, ixO^L, res)
2943 ! use mod_global_parameters
2944 ! integer, intent(in) :: ixI^L, ixO^L
2945 ! double precision, intent(in) :: Te(ixI^S)
2946 ! double precision, intent(out):: res(ixI^S)
2947 ! res(ixO^S) = Te(ixO^S) -1d0/Rc * &
2948 ! block%equi_vars(ixO^S,equi_pe_c0_,0)/block%equi_vars(ixO^S,equi_rho_c0_,0)
2949 ! end subroutine twofl_get_temperature_c_pert_from_tot
2950 
2951  subroutine twofl_get_temperature_c_equi(w,x, ixI^L, ixO^L, res)
2953  integer, intent(in) :: ixI^L, ixO^L
2954  double precision, intent(in) :: w(ixI^S, 1:nw)
2955  double precision, intent(in) :: x(ixI^S, 1:ndim)
2956  double precision, intent(out):: res(ixI^S)
2957  res(ixo^s) = 1d0/rc * &
2958  block%equi_vars(ixo^s,equi_pe_c0_,b0i)/block%equi_vars(ixo^s,equi_rho_c0_,b0i)
2959  end subroutine twofl_get_temperature_c_equi
2960 
2961  subroutine twofl_get_rho_c_equi(w, x, ixI^L, ixO^L, res)
2963  integer, intent(in) :: ixI^L, ixO^L
2964  double precision, intent(in) :: w(ixI^S, 1:nw)
2965  double precision, intent(in) :: x(ixI^S, 1:ndim)
2966  double precision, intent(out):: res(ixI^S)
2967  res(ixo^s) = block%equi_vars(ixo^s,equi_rho_c0_,b0i)
2968  end subroutine twofl_get_rho_c_equi
2969 
2970  subroutine twofl_get_pe_c_equi(w,x, ixI^L, ixO^L, res)
2972  integer, intent(in) :: ixI^L, ixO^L
2973  double precision, intent(in) :: w(ixI^S, 1:nw)
2974  double precision, intent(in) :: x(ixI^S, 1:ndim)
2975  double precision, intent(out):: res(ixI^S)
2976  res(ixo^s) = block%equi_vars(ixo^s,equi_pe_c0_,b0i)
2977  end subroutine twofl_get_pe_c_equi
2978 
2979  !> Calculate temperature=p/rho when in e_ the total energy is stored
2980  !> this does not check the values of twofl_energy and twofl_internal_e,
2981  !> twofl_energy = .true. and twofl_internal_e = .false.
2982  !> also check small_values is avoided
2983  subroutine twofl_get_temperature_from_etot_c(w, x, ixI^L, ixO^L, res)
2985  integer, intent(in) :: ixI^L, ixO^L
2986  double precision, intent(in) :: w(ixI^S, 1:nw)
2987  double precision, intent(in) :: x(ixI^S, 1:ndim)
2988  double precision, intent(out):: res(ixI^S)
2989  res(ixo^s)=1d0/rc * (gamma_1*(w(ixo^s,e_c_)&
2990  - twofl_kin_en_c(w,ixi^l,ixo^l)&
2991  - twofl_mag_en(w,ixi^l,ixo^l)))/w(ixo^s,rho_c_)
2992  end subroutine twofl_get_temperature_from_etot_c
2993  subroutine twofl_get_temperature_from_eki_c(w, x, ixI^L, ixO^L, res)
2995  integer, intent(in) :: ixI^L, ixO^L
2996  double precision, intent(in) :: w(ixI^S, 1:nw)
2997  double precision, intent(in) :: x(ixI^S, 1:ndim)
2998  double precision, intent(out):: res(ixI^S)
2999  res(ixo^s)=1d0/rc * (gamma_1*(w(ixo^s,e_c_)&
3000  - twofl_kin_en_c(w,ixi^l,ixo^l)))/w(ixo^s,rho_c_)
3001  end subroutine twofl_get_temperature_from_eki_c
3002 
3003  subroutine twofl_get_temperature_from_etot_c_with_equi(w, x, ixI^L, ixO^L, res)
3005  integer, intent(in) :: ixI^L, ixO^L
3006  double precision, intent(in) :: w(ixI^S, 1:nw)
3007  double precision, intent(in) :: x(ixI^S, 1:ndim)
3008  double precision, intent(out):: res(ixI^S)
3009  res(ixo^s)=1d0/rc * (gamma_1*(w(ixo^s,e_c_)&
3010  - twofl_kin_en_c(w,ixi^l,ixo^l)&
3011  - twofl_mag_en(w,ixi^l,ixo^l)) + block%equi_vars(ixo^s,equi_pe_c0_,b0i))&
3012  /(w(ixo^s,rho_c_) +block%equi_vars(ixo^s,equi_rho_c0_,b0i))
3013 
3015 
3016  subroutine twofl_get_temperature_from_eki_c_with_equi(w, x, ixI^L, ixO^L, res)
3018  integer, intent(in) :: ixI^L, ixO^L
3019  double precision, intent(in) :: w(ixI^S, 1:nw)
3020  double precision, intent(in) :: x(ixI^S, 1:ndim)
3021  double precision, intent(out):: res(ixI^S)
3022  res(ixo^s)=1d0/rc * (gamma_1*(w(ixo^s,e_c_)&
3023  - twofl_kin_en_c(w,ixi^l,ixo^l)) + block%equi_vars(ixo^s,equi_pe_c0_,b0i))&
3024  /(w(ixo^s,rho_c_) +block%equi_vars(ixo^s,equi_rho_c0_,b0i))
3025 
3027 
3028  subroutine twofl_get_csound2_adiab_n(w,x,ixI^L,ixO^L,csound2)
3030  integer, intent(in) :: ixI^L, ixO^L
3031  double precision, intent(in) :: w(ixI^S,nw)
3032  double precision, intent(in) :: x(ixI^S,1:ndim)
3033  double precision, intent(out) :: csound2(ixI^S)
3034  double precision :: rhon(ixI^S)
3035 
3036  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
3037  csound2(ixo^s)=twofl_gamma*twofl_adiab*rhon(ixo^s)**gamma_1
3038 
3039  end subroutine twofl_get_csound2_adiab_n
3040 
3041  subroutine twofl_get_csound2_n_from_conserved(w,x,ixI^L,ixO^L,csound2)
3043  integer, intent(in) :: ixI^L, ixO^L
3044  double precision, intent(in) :: w(ixI^S,nw)
3045  double precision, intent(in) :: x(ixI^S,1:ndim)
3046  double precision, intent(out) :: csound2(ixI^S)
3047  double precision :: rhon(ixI^S)
3048 
3049  if(phys_energy) then
3050  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
3051  call twofl_get_pthermal_n(w,x,ixi^l,ixo^l,csound2)
3052  csound2(ixo^s)=twofl_gamma*csound2(ixo^s)/rhon(ixo^s)
3053  else
3054  call twofl_get_csound2_adiab_n(w,x,ixi^l,ixo^l,csound2)
3055  endif
3056  end subroutine twofl_get_csound2_n_from_conserved
3057 
3058  !! TO DELETE
3059  subroutine twofl_get_csound2_n_from_primitive(w,x,ixI^L,ixO^L,csound2)
3061  integer, intent(in) :: ixI^L, ixO^L
3062  double precision, intent(in) :: w(ixI^S,nw)
3063  double precision, intent(in) :: x(ixI^S,1:ndim)
3064  double precision, intent(out) :: csound2(ixI^S)
3065  double precision :: rhon(ixI^S)
3066 
3067  if(phys_energy) then
3068  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
3069  call twofl_get_pthermal_n_primitive(w,x,ixi^l,ixo^l,csound2)
3070  csound2(ixo^s)=twofl_gamma*csound2(ixo^s)/rhon(ixo^s)
3071  else
3072  call twofl_get_csound2_adiab_n(w,x,ixi^l,ixo^l,csound2)
3073  endif
3074  end subroutine twofl_get_csound2_n_from_primitive
3075 
3076  subroutine twofl_get_csound2_adiab_c(w,x,ixI^L,ixO^L,csound2)
3078  integer, intent(in) :: ixI^L, ixO^L
3079  double precision, intent(in) :: w(ixI^S,nw)
3080  double precision, intent(in) :: x(ixI^S,1:ndim)
3081  double precision, intent(out) :: csound2(ixI^S)
3082  double precision :: rhoc(ixI^S)
3083 
3084  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
3085  csound2(ixo^s)=twofl_gamma*twofl_adiab* rhoc(ixo^s)**gamma_1
3086 
3087  end subroutine twofl_get_csound2_adiab_c
3088 
3089  subroutine twofl_get_csound2_c_from_conserved(w,x,ixI^L,ixO^L,csound2)
3091  integer, intent(in) :: ixi^l, ixo^l
3092  double precision, intent(in) :: w(ixi^s,nw)
3093  double precision, intent(in) :: x(ixi^s,1:ndim)
3094  double precision, intent(out) :: csound2(ixi^s)
3095  double precision :: rhoc(ixi^s)
3096 
3097  if(phys_energy) then
3098  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
3099  call twofl_get_pthermal_c(w,x,ixi^l,ixo^l,csound2)
3100  csound2(ixo^s)=twofl_gamma*csound2(ixo^s)/rhoc(ixo^s)
3101  else
3102  call twofl_get_csound2_adiab_c(w,x,ixi^l,ixo^l,csound2)
3103  endif
3104  end subroutine twofl_get_csound2_c_from_conserved
3105 
3106  !> Calculate fluxes within ixO^L.
3107  subroutine twofl_get_flux(wC,w,x,ixI^L,ixO^L,idim,f)
3109  use mod_geometry
3110 
3111  integer, intent(in) :: ixI^L, ixO^L, idim
3112  ! conservative w
3113  double precision, intent(in) :: wC(ixI^S,nw)
3114  ! primitive w
3115  double precision, intent(in) :: w(ixI^S,nw)
3116  double precision, intent(in) :: x(ixI^S,1:ndim)
3117  double precision,intent(out) :: f(ixI^S,nwflux)
3118 
3119  double precision :: pgas(ixO^S), ptotal(ixO^S),tmp(ixI^S)
3120  double precision, allocatable:: vHall(:^D&,:)
3121  integer :: idirmin, iw, idir, jdir, kdir
3122 
3123  ! value at the interfaces, idim = block%iw0 --> b0i
3124  ! reuse tmp, used afterwards
3125  ! value at the interface so we can't put momentum
3126  call get_rhoc_tot(w,x,ixi^l,ixo^l,tmp)
3127  ! Get flux of density
3128  f(ixo^s,rho_c_)=w(ixo^s,mom_c(idim))*tmp(ixo^s)
3129  ! pgas is time dependent only
3130  if(phys_energy) then
3131  pgas(ixo^s)=w(ixo^s,e_c_)
3132  else
3133  pgas(ixo^s)=twofl_adiab*tmp(ixo^s)**twofl_gamma
3134  if(has_equi_pe_c0) then
3135  pgas(ixo^s)=pgas(ixo^s)-block%equi_vars(ixo^s,equi_pe_c0_,b0i)
3136  endif
3137  end if
3138 
3139  if (twofl_hall) then
3140  allocate(vhall(ixi^s,1:ndir))
3141  call twofl_getv_hall(w,x,ixi^l,ixo^l,vhall)
3142  end if
3143 
3144  if(b0field) tmp(ixo^s)=sum(block%B0(ixo^s,:,idim)*w(ixo^s,mag(:)),dim=ndim+1)
3145 
3146  ptotal(ixo^s) = pgas(ixo^s) + 0.5d0*sum(w(ixo^s, mag(:))**2, dim=ndim+1)
3147 
3148  ! Get flux of momentum
3149  ! f_i[m_k]=v_i*m_k-b_k*b_i [+ptotal if i==k]
3150  do idir=1,ndir
3151  if(idim==idir) then
3152  f(ixo^s,mom_c(idir))=ptotal(ixo^s)-w(ixo^s,mag(idim))*w(ixo^s,mag(idir))
3153  if(b0field) f(ixo^s,mom_c(idir))=f(ixo^s,mom_c(idir))+tmp(ixo^s)
3154  else
3155  f(ixo^s,mom_c(idir))= -w(ixo^s,mag(idir))*w(ixo^s,mag(idim))
3156  end if
3157  if (b0field) then
3158  f(ixo^s,mom_c(idir))=f(ixo^s,mom_c(idir))&
3159  -w(ixo^s,mag(idir))*block%B0(ixo^s,idim,idim)&
3160  -w(ixo^s,mag(idim))*block%B0(ixo^s,idir,idim)
3161  end if
3162  f(ixo^s,mom_c(idir))=f(ixo^s,mom_c(idir))+w(ixo^s,mom_c(idim))*wc(ixo^s,mom_c(idir))
3163  end do
3164 
3165  ! Get flux of energy
3166  ! f_i[e]=v_i*e+v_i*ptotal-b_i*(b_k*v_k)
3167  if(phys_energy) then
3168  if (phys_internal_e) then
3169  f(ixo^s,e_c_)=w(ixo^s,mom_c(idim))*wc(ixo^s,e_c_)
3170  else if(twofl_eq_energy == eq_energy_ki) then
3171 
3172  f(ixo^s,e_c_)=w(ixo^s,mom_c(idim))*(wc(ixo^s,e_c_)+pgas(ixo^s))
3173  else
3174  f(ixo^s,e_c_)=w(ixo^s,mom_c(idim))*(wc(ixo^s,e_c_)+ptotal(ixo^s))&
3175  -w(ixo^s,mag(idim))*sum(w(ixo^s,mag(:))*w(ixo^s,mom_c(:)),dim=ndim+1)
3176  !if(phys_solve_eaux) f(ixO^S,eaux_)=w(ixO^S,mom(idim))*wC(ixO^S,eaux_)
3177 
3178  if (b0field) then
3179  f(ixo^s,e_c_) = f(ixo^s,e_c_) &
3180  + w(ixo^s,mom_c(idim)) * tmp(ixo^s) &
3181  - sum(w(ixo^s,mom_c(:))*w(ixo^s,mag(:)),dim=ndim+1) * block%B0(ixo^s,idim,idim)
3182  end if
3183 
3184  if (twofl_hall) then
3185  ! f_i[e]= f_i[e] + vHall_i*(b_k*b_k) - b_i*(vHall_k*b_k)
3186  if (twofl_etah>zero) then
3187  f(ixo^s,e_c_) = f(ixo^s,e_c_) + vhall(ixo^s,idim) * &
3188  sum(w(ixo^s, mag(:))**2,dim=ndim+1) &
3189  - w(ixo^s,mag(idim)) * sum(vhall(ixo^s,:)*w(ixo^s,mag(:)),dim=ndim+1)
3190  if (b0field) then
3191  f(ixo^s,e_c_) = f(ixo^s,e_c_) &
3192  + vhall(ixo^s,idim) * tmp(ixo^s) &
3193  - sum(vhall(ixo^s,:)*w(ixo^s,mag(:)),dim=ndim+1) * block%B0(ixo^s,idim,idim)
3194  end if
3195  end if
3196  end if
3197  end if !total_energy
3198  ! add flux of equilibrium internal energy corresponding to pe_c0
3199  if(has_equi_pe_c0) then
3200 #if !defined(E_RM_W0) || E_RM_W0 == 1
3201  f(ixo^s,e_c_)= f(ixo^s,e_c_) &
3202  + w(ixo^s,mom_c(idim)) * block%equi_vars(ixo^s,equi_pe_c0_,idim) * inv_gamma_1
3203 #else
3204  if(phys_internal_e) then
3205  f(ixo^s,e_c_)= f(ixo^s,e_c_) &
3206  + w(ixo^s,mom_c(idim)) * block%equi_vars(ixo^s,equi_pe_c0_,idim) * inv_gamma_1
3207  else
3208  f(ixo^s,e_c_)= f(ixo^s,e_c_) &
3209  + w(ixo^s,mom_c(idim)) * block%equi_vars(ixo^s,equi_pe_c0_,idim) * twofl_gamma * inv_gamma_1
3210  endif
3211 #endif
3212  end if
3213  end if !phys_energy
3214 
3215  ! compute flux of magnetic field
3216  ! f_i[b_k]=v_i*b_k-v_k*b_i
3217  do idir=1,ndir
3218  if (idim==idir) then
3219  ! f_i[b_i] should be exactly 0, so we do not use the transport flux
3220  if (twofl_glm) then
3221  f(ixo^s,mag(idir))=w(ixo^s,psi_)
3222  else
3223  f(ixo^s,mag(idir))=zero
3224  end if
3225  else
3226  f(ixo^s,mag(idir))=w(ixo^s,mom_c(idim))*w(ixo^s,mag(idir))-w(ixo^s,mag(idim))*w(ixo^s,mom_c(idir))
3227 
3228  if (b0field) then
3229  f(ixo^s,mag(idir))=f(ixo^s,mag(idir))&
3230  +w(ixo^s,mom_c(idim))*block%B0(ixo^s,idir,idim)&
3231  -w(ixo^s,mom_c(idir))*block%B0(ixo^s,idim,idim)
3232  end if
3233 
3234  if (twofl_hall) then
3235  ! f_i[b_k] = f_i[b_k] + vHall_i*b_k - vHall_k*b_i
3236  if (twofl_etah>zero) then
3237  if (b0field) then
3238  f(ixo^s,mag(idir)) = f(ixo^s,mag(idir)) &
3239  - vhall(ixo^s,idir)*(w(ixo^s,mag(idim))+block%B0(ixo^s,idim,idim)) &
3240  + vhall(ixo^s,idim)*(w(ixo^s,mag(idir))+block%B0(ixo^s,idir,idim))
3241  else
3242  f(ixo^s,mag(idir)) = f(ixo^s,mag(idir)) &
3243  - vhall(ixo^s,idir)*w(ixo^s,mag(idim)) &
3244  + vhall(ixo^s,idim)*w(ixo^s,mag(idir))
3245  end if
3246  end if
3247  end if
3248 
3249  end if
3250  end do
3251 
3252  if (twofl_glm) then
3253  !f_i[psi]=Ch^2*b_{i} Eq. 24e and Eq. 38c Dedner et al 2002 JCP, 175, 645
3254  f(ixo^s,psi_) = cmax_global**2*w(ixo^s,mag(idim))
3255  end if
3256 
3257  if (twofl_hall) then
3258  deallocate(vhall)
3259  end if
3260 
3261  !!neutrals
3262  call get_rhon_tot(w,x,ixi^l,ixo^l,tmp)
3263  f(ixo^s,rho_n_)=w(ixo^s,mom_n(idim))*tmp(ixo^s)
3264  if(phys_energy) then
3265  pgas(ixo^s) = w(ixo^s, e_n_)
3266  else
3267  pgas(ixo^s)=twofl_adiab*tmp(ixo^s)**twofl_gamma
3268  if(has_equi_pe_n0) then
3269  pgas(ixo^s)=pgas(ixo^s)-block%equi_vars(ixo^s,equi_pe_n0_,b0i)
3270  endif
3271  endif
3272  ! Momentum flux is v_i*m_i, +p in direction idim
3273  do idir = 1, ndir
3274  !if(idim==idir) then
3275  ! f(ixO^S,mom_c(idir)) = pgas(ixO^S)
3276  !else
3277  ! f(ixO^S,mom_c(idir)) = 0.0d0
3278  !end if
3279  !f(ixO^S,mom_c(idir))=f(ixO^S,mom_c(idir))+w(ixO^S,mom_c(idim))*wC(ixO^S,mom_c(idir))
3280  f(ixo^s, mom_n(idir)) = w(ixo^s,mom_n(idim)) * wc(ixo^s, mom_n(idir))
3281  end do
3282 
3283  f(ixo^s, mom_n(idim)) = f(ixo^s, mom_n(idim)) + pgas(ixo^s)
3284 
3285  if(phys_energy) then
3286  !reuse pgas for storing a in the term: div (u_n * a) and make multiplication at the end
3287  pgas(ixo^s) = wc(ixo^s,e_n_)
3288  if(.not. phys_internal_e) then
3289  ! add pressure perturbation
3290  pgas(ixo^s) = pgas(ixo^s) + w(ixo^s,e_n_)
3291  endif
3292  ! add flux of equilibrium internal energy corresponding to pe_n0
3293  if(has_equi_pe_n0) then
3294 #if !defined(E_RM_W0) || E_RM_W0 == 1
3295  pgas(ixo^s) = pgas(ixo^s) + block%equi_vars(ixo^s,equi_pe_n0_,idim) * inv_gamma_1
3296 #else
3297  pgas(ixo^s) = pgas(ixo^s) + block%equi_vars(ixo^s,equi_pe_n0_,idim) * twofl_gamma * inv_gamma_1
3298 #endif
3299  endif
3300  ! add u_n * a in the flux
3301  f(ixo^s, e_n_) = w(ixo^s,mom_n(idim)) * pgas(ixo^s)
3302 
3303  ! Viscosity fluxes - viscInDiv
3304  !if (hd_viscosity) then
3305  ! call visc_get_flux_prim(w, x, ixI^L, ixO^L, idim, f, phys_energy)
3306  !endif
3307  end if
3308 
3309  end subroutine twofl_get_flux
3310 
3311  !> w[iws]=w[iws]+qdt*S[iws,wCT] where S is the source based on wCT within ixO
3312  subroutine twofl_add_source(qdt,ixI^L,ixO^L,wCT,w,x,qsourcesplit,active,wCTprim)
3316  !use mod_gravity, only: gravity_add_source
3317 
3318  integer, intent(in) :: ixI^L, ixO^L
3319  double precision, intent(in) :: qdt
3320  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
3321  double precision, intent(inout) :: w(ixI^S,1:nw)
3322  logical, intent(in) :: qsourcesplit
3323  logical, intent(inout) :: active
3324  double precision, intent(in), optional :: wCTprim(ixI^S,1:nw)
3325 
3326  if (.not. qsourcesplit) then
3327  ! Source for solving internal energy
3328  if(phys_internal_e) then
3329  active = .true.
3330  call internal_energy_add_source_n(qdt,ixi^l,ixo^l,wct,w,x)
3331  call internal_energy_add_source_c(qdt,ixi^l,ixo^l,wct,w,x,e_c_)
3332  else
3333  if(phys_solve_eaux) then
3334  call internal_energy_add_source_c(qdt,ixi^l,ixo^l,wct,w,x,eaux_c_)
3335  endif
3336 #if !defined(E_RM_W0) || E_RM_W0==1
3337  ! add -p0 div v source terms when equi are present
3338  if(has_equi_pe_n0) then
3339  active = .true.
3340  call add_pe_n0_divv(qdt,ixi^l,ixo^l,wct,w,x)
3341  endif
3342  if(has_equi_pe_c0) then
3343  active = .true.
3344  call add_pe_c0_divv(qdt,ixi^l,ixo^l,wct,w,x)
3345  endif
3346 #endif
3347  if(twofl_eq_energy == eq_energy_ki) then
3348  active = .true.
3349  call add_source_lorentz_work(qdt,ixi^l,ixo^l,w,wct,x)
3350  endif
3351  endif
3352 
3353  ! Source for B0 splitting
3354  if (b0field) then
3355  active = .true.
3356  call add_source_b0split(qdt,ixi^l,ixo^l,wct,w,x)
3357  end if
3358 
3359  ! Sources for resistivity in eqs. for e, B1, B2 and B3
3360  if (abs(twofl_eta)>smalldouble)then
3361  active = .true.
3362  call add_source_res2(qdt,ixi^l,ixo^l,wct,w,x)
3363  end if
3364 
3365  if (twofl_eta_hyper>0.d0)then
3366  active = .true.
3367  call add_source_hyperres(qdt,ixi^l,ixo^l,wct,w,x)
3368  end if
3369  !it is not added in a split manner
3370  if(.not. use_imex_scheme .and. has_collisions()) then
3371  active = .true.
3372  call twofl_explicit_coll_terms_update(qdt,ixi^l,ixo^l,w,wct,x)
3373  endif
3374 
3375  if(twofl_hyperdiffusivity) then
3376  active = .true.
3377  call add_source_hyperdiffusive(qdt,ixi^l,ixo^l,w,wct,x)
3378  endif
3379 
3380  end if
3381 
3382  {^nooned
3383  if(.not.source_split_divb .and. .not.qsourcesplit .and. istep==nstep) then
3384  ! Sources related to div B
3385  select case (type_divb)
3386  case (divb_none)
3387  ! Do nothing
3388  case (divb_glm)
3389  active = .true.
3390  call add_source_glm(dt,ixi^l,ixo^l,pso(block%igrid)%w,w,x)
3391  case (divb_powel)
3392  active = .true.
3393  call add_source_powel(dt,ixi^l,ixo^l,pso(block%igrid)%w,w,x)
3394  case (divb_janhunen)
3395  active = .true.
3396  call add_source_janhunen(dt,ixi^l,ixo^l,pso(block%igrid)%w,w,x)
3397  case (divb_linde)
3398  active = .true.
3399  call add_source_linde(dt,ixi^l,ixo^l,pso(block%igrid)%w,w,x)
3400  case (divb_lindejanhunen)
3401  active = .true.
3402  call add_source_linde(dt,ixi^l,ixo^l,pso(block%igrid)%w,w,x)
3403  call add_source_janhunen(dt,ixi^l,ixo^l,pso(block%igrid)%w,w,x)
3404  case (divb_lindepowel)
3405  active = .true.
3406  call add_source_linde(dt,ixi^l,ixo^l,pso(block%igrid)%w,w,x)
3407  call add_source_powel(dt,ixi^l,ixo^l,pso(block%igrid)%w,w,x)
3408  case (divb_lindeglm)
3409  active = .true.
3410  call add_source_linde(dt,ixi^l,ixo^l,pso(block%igrid)%w,w,x)
3411  call add_source_glm(dt,ixi^l,ixo^l,pso(block%igrid)%w,w,x)
3412  case (divb_ct)
3413  continue ! Do nothing
3414  case (divb_multigrid)
3415  continue ! Do nothing
3416  case default
3417  call mpistop('Unknown divB fix')
3418  end select
3419  else if(source_split_divb .and. qsourcesplit) then
3420  ! Sources related to div B
3421  select case (type_divb)
3422  case (divb_none)
3423  ! Do nothing
3424  case (divb_glm)
3425  active = .true.
3426  call add_source_glm(qdt,ixi^l,ixo^l,wct,w,x)
3427  case (divb_powel)
3428  active = .true.
3429  call add_source_powel(qdt,ixi^l,ixo^l,wct,w,x)
3430  case (divb_janhunen)
3431  active = .true.
3432  call add_source_janhunen(qdt,ixi^l,ixo^l,wct,w,x)
3433  case (divb_linde)
3434  active = .true.
3435  call add_source_linde(qdt,ixi^l,ixo^l,wct,w,x)
3436  case (divb_lindejanhunen)
3437  active = .true.
3438  call add_source_linde(qdt,ixi^l,ixo^l,wct,w,x)
3439  call add_source_janhunen(qdt,ixi^l,ixo^l,wct,w,x)
3440  case (divb_lindepowel)
3441  active = .true.
3442  call add_source_linde(qdt,ixi^l,ixo^l,wct,w,x)
3443  call add_source_powel(qdt,ixi^l,ixo^l,wct,w,x)
3444  case (divb_lindeglm)
3445  active = .true.
3446  call add_source_linde(qdt,ixi^l,ixo^l,wct,w,x)
3447  call add_source_glm(qdt,ixi^l,ixo^l,wct,w,x)
3448  case (divb_ct)
3449  continue ! Do nothing
3450  case (divb_multigrid)
3451  continue ! Do nothing
3452  case default
3453  call mpistop('Unknown divB fix')
3454  end select
3455  end if
3456  }
3457 
3458  if(twofl_radiative_cooling_c) then
3459  call radiative_cooling_add_source(qdt,ixi^l,ixo^l,wct,&
3460  w,x,qsourcesplit,active,rc_fl_c)
3461  end if
3462  if(twofl_radiative_cooling_n) then
3463  call radiative_cooling_add_source(qdt,ixi^l,ixo^l,wct,&
3464  w,x,qsourcesplit,active,rc_fl_n)
3465  end if
3466 !
3467 ! if(twofl_viscosity) then
3468 ! call viscosity_add_source(qdt,ixI^L,ixO^L,wCT,&
3469 ! w,x,phys_energy,qsourcesplit,active)
3470 ! end if
3471 !
3472  if(twofl_gravity) then
3473  call gravity_add_source(qdt,ixi^l,ixo^l,wct,&
3474  w,x,twofl_eq_energy .eq. eq_energy_ki .or. phys_total_energy,qsourcesplit,active)
3475  end if
3476 
3477  end subroutine twofl_add_source
3478 
3479  subroutine add_pe_n0_divv(qdt,ixI^L,ixO^L,wCT,w,x)
3481  use mod_geometry
3482 
3483  integer, intent(in) :: ixI^L, ixO^L
3484  double precision, intent(in) :: qdt
3485  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
3486  double precision, intent(inout) :: w(ixI^S,1:nw)
3487  double precision :: v(ixI^S,1:ndir)
3488 
3489  call twofl_get_v_n(wct,x,ixi^l,ixi^l,v)
3490  call add_geom_pdivv(qdt,ixi^l,ixo^l,v,-block%equi_vars(ixi^s,equi_pe_n0_,0),w,x,e_n_)
3491 
3492  end subroutine add_pe_n0_divv
3493 
3494  subroutine add_pe_c0_divv(qdt,ixI^L,ixO^L,wCT,w,x)
3496  use mod_geometry
3497 
3498  integer, intent(in) :: ixI^L, ixO^L
3499  double precision, intent(in) :: qdt
3500  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
3501  double precision, intent(inout) :: w(ixI^S,1:nw)
3502  double precision :: v(ixI^S,1:ndir)
3503 
3504  call twofl_get_v_c(wct,x,ixi^l,ixi^l,v)
3505  call add_geom_pdivv(qdt,ixi^l,ixo^l,v,-block%equi_vars(ixi^s,equi_pe_c0_,0),w,x,e_c_)
3506 
3507  end subroutine add_pe_c0_divv
3508 
3509  subroutine add_geom_pdivv(qdt,ixI^L,ixO^L,v,p,w,x,ind)
3511  use mod_geometry
3512 
3513  integer, intent(in) :: ixI^L, ixO^L,ind
3514  double precision, intent(in) :: qdt
3515  double precision, intent(in) :: p(ixI^S), v(ixI^S,1:ndir), x(ixI^S,1:ndim)
3516  double precision, intent(inout) :: w(ixI^S,1:nw)
3517  double precision :: divv(ixI^S)
3518 
3519  if(slab_uniform) then
3520  if(nghostcells .gt. 2) then
3521  call divvector(v,ixi^l,ixo^l,divv,sixthorder=.true.)
3522  else
3523  call divvector(v,ixi^l,ixo^l,divv,fourthorder=.true.)
3524  end if
3525  else
3526  call divvector(v,ixi^l,ixo^l,divv)
3527  end if
3528  w(ixo^s,ind)=w(ixo^s,ind)+qdt*p(ixo^s)*divv(ixo^s)
3529  end subroutine add_geom_pdivv
3530 
3531  !> Compute the Lorentz force (JxB)
3532  subroutine get_lorentz(ixI^L,ixO^L,w,JxB)
3534  integer, intent(in) :: ixI^L, ixO^L
3535  double precision, intent(in) :: w(ixI^S,1:nw)
3536  double precision, intent(inout) :: JxB(ixI^S,3)
3537  double precision :: a(ixI^S,3), b(ixI^S,3), tmp(ixI^S,3)
3538  integer :: idir, idirmin
3539  ! For ndir=2 only 3rd component of J can exist, ndir=1 is impossible for MHD
3540  double precision :: current(ixI^S,7-2*ndir:3)
3541 
3542  b=0.0d0
3543  do idir = 1, ndir
3544  b(ixo^s, idir) = twofl_mag_i_all(w, ixi^l, ixo^l,idir)
3545  end do
3546 
3547  ! store J current in a
3548  call get_current(w,ixi^l,ixo^l,idirmin,current)
3549 
3550  a=0.0d0
3551  do idir=7-2*ndir,3
3552  a(ixo^s,idir)=current(ixo^s,idir)
3553  end do
3554 
3555  call cross_product(ixi^l,ixo^l,a,b,jxb)
3556  end subroutine get_lorentz
3557 
3558  subroutine add_source_lorentz_work(qdt,ixI^L,ixO^L,w,wCT,x)
3560  integer, intent(in) :: ixI^L, ixO^L
3561  double precision, intent(in) :: qdt
3562  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
3563  double precision, intent(inout) :: w(ixI^S,1:nw)
3564  double precision :: a(ixI^S,3), b(ixI^S,1:ndir)
3565 
3566  call get_lorentz(ixi^l, ixo^l,wct,a)
3567  call twofl_get_v_c(wct,x,ixi^l,ixo^l,b)
3568  w(ixo^s,e_c_)=w(ixo^s,e_c_)+qdt*sum(a(ixo^s,1:ndir)*b(ixo^s,1:ndir),dim=ndim+1)
3569 
3570  end subroutine add_source_lorentz_work
3571 
3572  !> Calculate v_n vector
3573  subroutine twofl_get_v_n(w,x,ixI^L,ixO^L,v)
3575 
3576  integer, intent(in) :: ixI^L, ixO^L
3577  double precision, intent(in) :: w(ixI^S,nw), x(ixI^S,1:ndim)
3578  double precision, intent(out) :: v(ixI^S,ndir)
3579  double precision :: rhon(ixI^S)
3580  integer :: idir
3581 
3582  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
3583 
3584  do idir=1,ndir
3585  v(ixo^s,idir) = w(ixo^s, mom_n(idir)) / rhon(ixo^s)
3586  end do
3587 
3588  end subroutine twofl_get_v_n
3589 
3590  subroutine get_rhon_tot(w,x,ixI^L,ixO^L,rhon)
3592  integer, intent(in) :: ixi^l, ixo^l
3593  double precision, intent(in) :: w(ixi^s,1:nw), x(ixi^s,1:ndim)
3594  double precision, intent(out) :: rhon(ixi^s)
3595  if(has_equi_rho_n0) then
3596  rhon(ixo^s) = w(ixo^s,rho_n_) + block%equi_vars(ixo^s,equi_rho_n0_,b0i)
3597  else
3598  rhon(ixo^s) = w(ixo^s,rho_n_)
3599  endif
3600 
3601  end subroutine get_rhon_tot
3602 
3603  subroutine twofl_get_pthermal_n(w,x,ixI^L,ixO^L,pth)
3606  integer, intent(in) :: ixI^L, ixO^L
3607  double precision, intent(in) :: w(ixI^S,1:nw)
3608  double precision, intent(in) :: x(ixI^S,1:ndim)
3609  double precision, intent(out) :: pth(ixI^S)
3610 
3611  integer :: ix^D, iw
3612 
3613  if(phys_energy) then
3614  if(phys_internal_e) then
3615  pth(ixo^s)=gamma_1*w(ixo^s,e_n_)
3616  else
3617  pth(ixo^s)=gamma_1*(w(ixo^s,e_n_)&
3618  - twofl_kin_en_n(w,ixi^l,ixo^l))
3619  end if
3620  if(has_equi_pe_n0) then
3621  pth(ixo^s) = pth(ixo^s) + block%equi_vars(ixo^s,equi_pe_n0_,b0i)
3622  endif
3623  else
3624  call get_rhon_tot(w,x,ixi^l,ixo^l,pth)
3625  pth(ixo^s)=twofl_adiab*pth(ixo^s)**twofl_gamma
3626  end if
3627 
3628  if (fix_small_values) then
3629  {do ix^db= ixo^lim^db\}
3630  if(pth(ix^d)<small_pressure) then
3631  pth(ix^d)=small_pressure
3632  end if
3633  {enddo^d&\}
3634  end if
3635  if (check_small_values) then
3636  {do ix^db= ixo^lim^db\}
3637  if(pth(ix^d)<small_pressure) then
3638  write(*,*) "Error: small value of gas pressure",pth(ix^d),&
3639  " encountered when call twofl_get_pthermal_n"
3640  write(*,*) "Iteration: ", it, " Time: ", global_time
3641  write(*,*) "Location: ", x(ix^d,:)
3642  write(*,*) "Cell number: ", ix^d
3643  do iw=1,nw
3644  write(*,*) trim(cons_wnames(iw)),": ",w(ix^d,iw)
3645  end do
3646  ! use erroneous arithmetic operation to crash the run
3647  if(trace_small_values) write(*,*) sqrt(pth(ix^d)-bigdouble)
3648  write(*,*) "Saving status at the previous time step"
3649  crash=.true.
3650  end if
3651  {enddo^d&\}
3652  end if
3653 
3654  end subroutine twofl_get_pthermal_n
3655 
3656  subroutine twofl_get_pthermal_n_primitive(w,x,ixI^L,ixO^L,pth)
3658  integer, intent(in) :: ixI^L, ixO^L
3659  double precision, intent(in) :: w(ixI^S,1:nw)
3660  double precision, intent(in) :: x(ixI^S,1:ndim)
3661  double precision, intent(out) :: pth(ixI^S)
3662 
3663  if(phys_energy) then
3664  if(has_equi_pe_n0) then
3665  pth(ixo^s) = w(ixo^s,e_n_) + block%equi_vars(ixo^s,equi_pe_n0_,b0i)
3666  else
3667  pth(ixo^s) = w(ixo^s,e_n_)
3668  endif
3669  else
3670  call get_rhon_tot(w,x,ixi^l,ixo^l,pth)
3671  pth(ixo^s)=twofl_adiab*pth(ixo^s)**twofl_gamma
3672  end if
3673  end subroutine twofl_get_pthermal_n_primitive
3674 
3675  !> Calculate v component
3676  subroutine twofl_get_v_n_idim(w,x,ixI^L,ixO^L,idim,v)
3678 
3679  integer, intent(in) :: ixi^l, ixo^l, idim
3680  double precision, intent(in) :: w(ixi^s,nw), x(ixi^s,1:ndim)
3681  double precision, intent(out) :: v(ixi^s)
3682  double precision :: rhon(ixi^s)
3683 
3684  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
3685  v(ixo^s) = w(ixo^s, mom_n(idim)) / rhon(ixo^s)
3686 
3687  end subroutine twofl_get_v_n_idim
3688 
3689  subroutine internal_energy_add_source_n(qdt,ixI^L,ixO^L,wCT,w,x)
3691  use mod_geometry
3692 
3693  integer, intent(in) :: ixI^L, ixO^L
3694  double precision, intent(in) :: qdt
3695  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
3696  double precision, intent(inout) :: w(ixI^S,1:nw)
3697  double precision :: pth(ixI^S),v(ixI^S,1:ndir),divv(ixI^S)
3698 
3699  call twofl_get_pthermal_n(wct,x,ixi^l,ixo^l,pth)
3700  call twofl_get_v_n(wct,x,ixi^l,ixi^l,v)
3701  call add_geom_pdivv(qdt,ixi^l,ixo^l,v,-pth,w,x,e_n_)
3702 
3703  if(fix_small_values .and. .not. has_equi_pe_n0) then
3704  call twofl_handle_small_ei_n(w,x,ixi^l,ixo^l,e_n_,'internal_energy_add_source')
3705  end if
3706  end subroutine internal_energy_add_source_n
3707 
3708  !> Calculate v_c vector
3709  subroutine twofl_get_v_c(w,x,ixI^L,ixO^L,v)
3711 
3712  integer, intent(in) :: ixI^L, ixO^L
3713  double precision, intent(in) :: w(ixI^S,nw), x(ixI^S,1:ndim)
3714  double precision, intent(out) :: v(ixI^S,ndir)
3715  double precision :: rhoc(ixI^S)
3716  integer :: idir
3717 
3718  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
3719  do idir=1,ndir
3720  v(ixo^s,idir) = w(ixo^s, mom_c(idir)) / rhoc(ixo^s)
3721  end do
3722 
3723  end subroutine twofl_get_v_c
3724 
3725  subroutine get_rhoc_tot(w,x,ixI^L,ixO^L,rhoc)
3727  integer, intent(in) :: ixi^l, ixo^l
3728  double precision, intent(in) :: w(ixi^s,1:nw), x(ixi^s,1:ndim)
3729  double precision, intent(out) :: rhoc(ixi^s)
3730  if(has_equi_rho_c0) then
3731  rhoc(ixo^s) = w(ixo^s,rho_c_) + block%equi_vars(ixo^s,equi_rho_c0_,b0i)
3732  else
3733  rhoc(ixo^s) = w(ixo^s,rho_c_)
3734  endif
3735 
3736  end subroutine get_rhoc_tot
3737 
3738  subroutine twofl_get_pthermal_c(w,x,ixI^L,ixO^L,pth)
3741  integer, intent(in) :: ixi^l, ixo^l
3742  double precision, intent(in) :: w(ixi^s,1:nw)
3743  double precision, intent(in) :: x(ixi^s,1:ndim)
3744  double precision, intent(out) :: pth(ixi^s)
3745  integer :: ix^d, iw
3746 
3747  if(phys_energy) then
3748  if(phys_internal_e) then
3749  pth(ixo^s)=gamma_1*w(ixo^s,e_c_)
3750  elseif(phys_total_energy) then
3751  pth(ixo^s)=gamma_1*(w(ixo^s,e_c_)&
3752  - twofl_kin_en_c(w,ixi^l,ixo^l)&
3753  - twofl_mag_en(w,ixi^l,ixo^l))
3754  else
3755  pth(ixo^s)=gamma_1*(w(ixo^s,e_c_)&
3756  - twofl_kin_en_c(w,ixi^l,ixo^l))
3757  end if
3758  if(has_equi_pe_c0) then
3759  pth(ixo^s) = pth(ixo^s) + block%equi_vars(ixo^s,equi_pe_c0_,b0i)
3760  endif
3761  else
3762  call get_rhoc_tot(w,x,ixi^l,ixo^l,pth)
3763  pth(ixo^s)=twofl_adiab*pth(ixo^s)**twofl_gamma
3764  end if
3765 
3766  if (fix_small_values) then
3767  {do ix^db= ixo^lim^db\}
3768  if(pth(ix^d)<small_pressure) then
3769  pth(ix^d)=small_pressure
3770  end if
3771  {enddo^d&\}
3772  end if
3773 
3774  if (check_small_values) then
3775  {do ix^db= ixo^lim^db\}
3776  if(pth(ix^d)<small_pressure) then
3777  write(*,*) "Error: small value of gas pressure",pth(ix^d),&
3778  " encountered when call twofl_get_pe_c1"
3779  write(*,*) "Iteration: ", it, " Time: ", global_time
3780  write(*,*) "Location: ", x(ix^d,:)
3781  write(*,*) "Cell number: ", ix^d
3782  do iw=1,nw
3783  write(*,*) trim(cons_wnames(iw)),": ",w(ix^d,iw)
3784  end do
3785  ! use erroneous arithmetic operation to crash the run
3786  if(trace_small_values) write(*,*) sqrt(pth(ix^d)-bigdouble)
3787  write(*,*) "Saving status at the previous time step"
3788  crash=.true.
3789  end if
3790  {enddo^d&\}
3791  end if
3792 
3793  end subroutine twofl_get_pthermal_c
3794 
3795  subroutine twofl_get_pthermal_c_primitive(w,x,ixI^L,ixO^L,pth)
3797  integer, intent(in) :: ixI^L, ixO^L
3798  double precision, intent(in) :: w(ixI^S,1:nw)
3799  double precision, intent(in) :: x(ixI^S,1:ndim)
3800  double precision, intent(out) :: pth(ixI^S)
3801 
3802  if(phys_energy) then
3803  if(has_equi_pe_c0) then
3804  pth(ixo^s) = w(ixo^s,e_c_) + block%equi_vars(ixo^s,equi_pe_c0_,b0i)
3805  else
3806  pth(ixo^s) = w(ixo^s,e_c_)
3807  endif
3808  else
3809  call get_rhoc_tot(w,x,ixi^l,ixo^l,pth)
3810  pth(ixo^s)=twofl_adiab*pth(ixo^s)**twofl_gamma
3811  end if
3812  end subroutine twofl_get_pthermal_c_primitive
3813 
3814  !> Calculate v_c component
3815  subroutine twofl_get_v_c_idim(w,x,ixI^L,ixO^L,idim,v)
3817 
3818  integer, intent(in) :: ixi^l, ixo^l, idim
3819  double precision, intent(in) :: w(ixi^s,nw), x(ixi^s,1:ndim)
3820  double precision, intent(out) :: v(ixi^s)
3821  double precision :: rhoc(ixi^s)
3822 
3823  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
3824  v(ixo^s) = w(ixo^s, mom_c(idim)) / rhoc(ixo^s)
3825 
3826  end subroutine twofl_get_v_c_idim
3827 
3828  subroutine internal_energy_add_source_c(qdt,ixI^L,ixO^L,wCT,w,x,ie)
3830  use mod_geometry
3831 
3832  integer, intent(in) :: ixI^L, ixO^L,ie
3833  double precision, intent(in) :: qdt
3834  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
3835  double precision, intent(inout) :: w(ixI^S,1:nw)
3836  double precision :: pth(ixI^S),v(ixI^S,1:ndir),divv(ixI^S)
3837 
3838  call twofl_get_pthermal_c(wct,x,ixi^l,ixo^l,pth)
3839  call twofl_get_v_c(wct,x,ixi^l,ixi^l,v)
3840  call add_geom_pdivv(qdt,ixi^l,ixo^l,v,-pth,w,x,ie)
3841  if(fix_small_values .and. .not. has_equi_pe_c0) then
3842  call twofl_handle_small_ei_c(w,x,ixi^l,ixo^l,ie,'internal_energy_add_source')
3843  end if
3844  end subroutine internal_energy_add_source_c
3845 
3846  !> handle small or negative internal energy
3847  subroutine twofl_handle_small_ei_c(w, x, ixI^L, ixO^L, ie, subname)
3849  use mod_small_values
3850  integer, intent(in) :: ixI^L,ixO^L, ie
3851  double precision, intent(inout) :: w(ixI^S,1:nw)
3852  double precision, intent(in) :: x(ixI^S,1:ndim)
3853  character(len=*), intent(in) :: subname
3854 
3855  integer :: idir
3856  logical :: flag(ixI^S,1:nw)
3857  double precision :: rhoc(ixI^S)
3858  double precision :: rhon(ixI^S)
3859 
3860  flag=.false.
3861  if(has_equi_pe_c0) then
3862  where(w(ixo^s,ie)+block%equi_vars(ixo^s,equi_pe_c0_,0)*inv_gamma_1<small_e)&
3863  flag(ixo^s,ie)=.true.
3864  else
3865  where(w(ixo^s,ie)<small_e) flag(ixo^s,ie)=.true.
3866  endif
3867  if(any(flag(ixo^s,ie))) then
3868  select case (small_values_method)
3869  case ("replace")
3870  if(has_equi_pe_c0) then
3871  where(flag(ixo^s,ie)) w(ixo^s,ie)=small_e - &
3872  block%equi_vars(ixo^s,equi_pe_c0_,0)*inv_gamma_1
3873  else
3874  where(flag(ixo^s,ie)) w(ixo^s,ie)=small_e
3875  endif
3876  case ("average")
3877  call small_values_average(ixi^l, ixo^l, w, x, flag, ie)
3878  case default
3879  ! small values error shows primitive variables
3880  ! to_primitive subroutine cannot be used as this error handling
3881  ! is also used in TC where e_to_ei is explicitly called
3882  w(ixo^s,e_n_)=w(ixo^s,e_n_)*gamma_1
3883  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
3884  w(ixo^s,e_c_)=w(ixo^s,e_c_)*gamma_1
3885  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
3886  do idir = 1, ndir
3887  w(ixo^s, mom_n(idir)) = w(ixo^s, mom_n(idir))/rhon(ixo^s)
3888  w(ixo^s, mom_c(idir)) = w(ixo^s, mom_c(idir))/rhoc(ixo^s)
3889  end do
3890  call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
3891  end select
3892  end if
3893 
3894  end subroutine twofl_handle_small_ei_c
3895 
3896  !> handle small or negative internal energy
3897  subroutine twofl_handle_small_ei_n(w, x, ixI^L, ixO^L, ie, subname)
3899  use mod_small_values
3900  integer, intent(in) :: ixI^L,ixO^L, ie
3901  double precision, intent(inout) :: w(ixI^S,1:nw)
3902  double precision, intent(in) :: x(ixI^S,1:ndim)
3903  character(len=*), intent(in) :: subname
3904 
3905  integer :: idir
3906  logical :: flag(ixI^S,1:nw)
3907  double precision :: rhoc(ixI^S)
3908  double precision :: rhon(ixI^S)
3909 
3910  flag=.false.
3911  if(has_equi_pe_n0) then
3912  where(w(ixo^s,ie)+block%equi_vars(ixo^s,equi_pe_n0_,0)*inv_gamma_1<small_e)&
3913  flag(ixo^s,ie)=.true.
3914  else
3915  where(w(ixo^s,ie)<small_e) flag(ixo^s,ie)=.true.
3916  endif
3917  if(any(flag(ixo^s,ie))) then
3918  select case (small_values_method)
3919  case ("replace")
3920  if(has_equi_pe_n0) then
3921  where(flag(ixo^s,ie)) w(ixo^s,ie)=small_e - &
3922  block%equi_vars(ixo^s,equi_pe_n0_,0)*inv_gamma_1
3923  else
3924  where(flag(ixo^s,ie)) w(ixo^s,ie)=small_e
3925  endif
3926  case ("average")
3927  call small_values_average(ixi^l, ixo^l, w, x, flag, ie)
3928  case default
3929  ! small values error shows primitive variables
3930  w(ixo^s,e_n_)=w(ixo^s,e_n_)*gamma_1
3931  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
3932  w(ixo^s,e_c_)=w(ixo^s,e_c_)*gamma_1
3933  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
3934  do idir = 1, ndir
3935  w(ixo^s, mom_n(idir)) = w(ixo^s, mom_n(idir))/rhon(ixo^s)
3936  w(ixo^s, mom_c(idir)) = w(ixo^s, mom_c(idir))/rhoc(ixo^s)
3937  end do
3938  call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
3939  end select
3940  end if
3941 
3942  end subroutine twofl_handle_small_ei_n
3943 
3944  !> Source terms after split off time-independent magnetic field
3945  subroutine add_source_b0split(qdt,ixI^L,ixO^L,wCT,w,x)
3947 
3948  integer, intent(in) :: ixI^L, ixO^L
3949  double precision, intent(in) :: qdt, wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
3950  double precision, intent(inout) :: w(ixI^S,1:nw)
3951 
3952  double precision :: a(ixI^S,3), b(ixI^S,3), axb(ixI^S,3)
3953  integer :: idir
3954 
3955  a=0.d0
3956  b=0.d0
3957  ! for force-free field J0xB0 =0
3958  if(.not.b0field_forcefree) then
3959  ! store B0 magnetic field in b
3960  b(ixo^s,1:ndir)=block%B0(ixo^s,1:ndir,0)
3961 
3962  ! store J0 current in a
3963  do idir=7-2*ndir,3
3964  a(ixo^s,idir)=block%J0(ixo^s,idir)
3965  end do
3966  call cross_product(ixi^l,ixo^l,a,b,axb)
3967  axb(ixo^s,:)=axb(ixo^s,:)*qdt
3968  ! add J0xB0 source term in momentum equations
3969  w(ixo^s,mom_c(1:ndir))=w(ixo^s,mom_c(1:ndir))+axb(ixo^s,1:ndir)
3970  end if
3971 
3972  if(phys_total_energy) then
3973  a=0.d0
3974  ! for free-free field -(vxB0) dot J0 =0
3975  b(ixo^s,:)=wct(ixo^s,mag(:))
3976  ! store full magnetic field B0+B1 in b
3977  if(.not.b0field_forcefree) b(ixo^s,:)=b(ixo^s,:)+block%B0(ixo^s,:,0)
3978  ! store velocity in a
3979  do idir=1,ndir
3980  call twofl_get_v_c_idim(wct,x,ixi^l,ixo^l,idir,a(ixi^s,idir))
3981  end do
3982  call cross_product(ixi^l,ixo^l,a,b,axb)
3983  axb(ixo^s,:)=axb(ixo^s,:)*qdt
3984  ! add -(vxB) dot J0 source term in energy equation
3985  do idir=7-2*ndir,3
3986  w(ixo^s,e_c_)=w(ixo^s,e_c_)-axb(ixo^s,idir)*block%J0(ixo^s,idir)
3987  end do
3988  end if
3989 
3990  if (fix_small_values) call twofl_handle_small_values(.false.,w,x,ixi^l,ixo^l,'add_source_B0')
3991 
3992  end subroutine add_source_b0split
3993 
3994  !> Add resistive source to w within ixO Uses 3 point stencil (1 neighbour) in
3995  !> each direction, non-conservative. If the fourthorder precompiler flag is
3996  !> set, uses fourth order central difference for the laplacian. Then the
3997  !> stencil is 5 (2 neighbours).
3998  subroutine add_source_res1(qdt,ixI^L,ixO^L,wCT,w,x)
4000  use mod_usr_methods
4001  use mod_geometry
4002 
4003  integer, intent(in) :: ixI^L, ixO^L
4004  double precision, intent(in) :: qdt
4005  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
4006  double precision, intent(inout) :: w(ixI^S,1:nw)
4007  integer :: ixA^L,idir,jdir,kdir,idirmin,idim,jxO^L,hxO^L,ix
4008  integer :: lxO^L, kxO^L
4009 
4010  double precision :: tmp(ixI^S),tmp2(ixI^S)
4011 
4012  ! For ndir=2 only 3rd component of J can exist, ndir=1 is impossible for MHD
4013  double precision :: current(ixI^S,7-2*ndir:3),eta(ixI^S)
4014  double precision :: gradeta(ixI^S,1:ndim), Bf(ixI^S,1:ndir)
4015 
4016  ! Calculating resistive sources involve one extra layer
4017  if (twofl_4th_order) then
4018  ixa^l=ixo^l^ladd2;
4019  else
4020  ixa^l=ixo^l^ladd1;
4021  end if
4022 
4023  if (iximin^d>ixamin^d.or.iximax^d<ixamax^d|.or.) &
4024  call mpistop("Error in add_source_res1: Non-conforming input limits")
4025 
4026  ! Calculate current density and idirmin
4027  call get_current(wct,ixi^l,ixo^l,idirmin,current)
4028 
4029  if (twofl_eta>zero)then
4030  eta(ixa^s)=twofl_eta
4031  gradeta(ixo^s,1:ndim)=zero
4032  else
4033  call usr_special_resistivity(wct,ixi^l,ixa^l,idirmin,x,current,eta)
4034  ! assumes that eta is not function of current?
4035  do idim=1,ndim
4036  call gradient(eta,ixi^l,ixo^l,idim,tmp)
4037  gradeta(ixo^s,idim)=tmp(ixo^s)
4038  end do
4039  end if
4040 
4041  if(b0field) then
4042  bf(ixi^s,1:ndir)=wct(ixi^s,mag(1:ndir))+block%B0(ixi^s,1:ndir,0)
4043  else
4044  bf(ixi^s,1:ndir)=wct(ixi^s,mag(1:ndir))
4045  end if
4046 
4047  do idir=1,ndir
4048  ! Put B_idir into tmp2 and eta*Laplace B_idir into tmp
4049  if (twofl_4th_order) then
4050  tmp(ixo^s)=zero
4051  tmp2(ixi^s)=bf(ixi^s,idir)
4052  do idim=1,ndim
4053  lxo^l=ixo^l+2*kr(idim,^d);
4054  jxo^l=ixo^l+kr(idim,^d);
4055  hxo^l=ixo^l-kr(idim,^d);
4056  kxo^l=ixo^l-2*kr(idim,^d);
4057  tmp(ixo^s)=tmp(ixo^s)+&
4058  (-tmp2(lxo^s)+16.0d0*tmp2(jxo^s)-30.0d0*tmp2(ixo^s)+16.0d0*tmp2(hxo^s)-tmp2(kxo^s)) &
4059  /(12.0d0 * dxlevel(idim)**2)
4060  end do
4061  else
4062  tmp(ixo^s)=zero
4063  tmp2(ixi^s)=bf(ixi^s,idir)
4064  do idim=1,ndim
4065  jxo^l=ixo^l+kr(idim,^d);
4066  hxo^l=ixo^l-kr(idim,^d);
4067  tmp(ixo^s)=tmp(ixo^s)+&
4068  (tmp2(jxo^s)-2.0d0*tmp2(ixo^s)+tmp2(hxo^s))/dxlevel(idim)**2
4069  end do
4070  end if
4071 
4072  ! Multiply by eta
4073  tmp(ixo^s)=tmp(ixo^s)*eta(ixo^s)
4074 
4075  ! Subtract grad(eta) x J = eps_ijk d_j eta J_k if eta is non-constant
4076  if (twofl_eta<zero)then
4077  do jdir=1,ndim; do kdir=idirmin,3
4078  if (lvc(idir,jdir,kdir)/=0)then
4079  if (lvc(idir,jdir,kdir)==1)then
4080  tmp(ixo^s)=tmp(ixo^s)-gradeta(ixo^s,jdir)*current(ixo^s,kdir)
4081  else
4082  tmp(ixo^s)=tmp(ixo^s)+gradeta(ixo^s,jdir)*current(ixo^s,kdir)
4083  end if
4084  end if
4085  end do; end do
4086  end if
4087 
4088  ! Add sources related to eta*laplB-grad(eta) x J to B and e
4089  w(ixo^s,mag(idir))=w(ixo^s,mag(idir))+qdt*tmp(ixo^s)
4090  if (phys_energy) then
4091  w(ixo^s,e_c_)=w(ixo^s,e_c_)+qdt*tmp(ixo^s)*bf(ixo^s,idir)
4092  if(phys_solve_eaux) then
4093  w(ixo^s,eaux_c_)=w(ixo^s,eaux_c_)+qdt*tmp(ixo^s)*bf(ixo^s,idir)
4094  end if
4095  end if
4096  end do ! idir
4097 
4098  if (phys_energy) then
4099  ! de/dt+=eta*J**2
4100  tmp(ixo^s)=qdt*eta(ixo^s)*sum(current(ixo^s,:)**2,dim=ndim+1)
4101  w(ixo^s,e_c_)=w(ixo^s,e_c_)+tmp(ixo^s)
4102  if(phys_solve_eaux) then
4103  ! add eta*J**2 source term in the internal energy equation
4104  w(ixo^s,eaux_c_)=w(ixo^s,eaux_c_)+tmp(ixo^s)
4105  end if
4106  end if
4107 
4108  if (fix_small_values) call twofl_handle_small_values(.false.,w,x,ixi^l,ixo^l,'add_source_res1')
4109 
4110  end subroutine add_source_res1
4111 
4112  !> Add resistive source to w within ixO
4113  !> Uses 5 point stencil (2 neighbours) in each direction, conservative
4114  subroutine add_source_res2(qdt,ixI^L,ixO^L,wCT,w,x)
4116  use mod_usr_methods
4117  use mod_geometry
4118 
4119  integer, intent(in) :: ixI^L, ixO^L
4120  double precision, intent(in) :: qdt
4121  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
4122  double precision, intent(inout) :: w(ixI^S,1:nw)
4123 
4124  ! For ndir=2 only 3rd component of J can exist, ndir=1 is impossible for MHD
4125  double precision :: current(ixI^S,7-2*ndir:3),eta(ixI^S),curlj(ixI^S,1:3)
4126  double precision :: tmpvec(ixI^S,1:3),tmp(ixO^S)
4127  integer :: ixA^L,idir,idirmin,idirmin1
4128 
4129  ixa^l=ixo^l^ladd2;
4130 
4131  if (iximin^d>ixamin^d.or.iximax^d<ixamax^d|.or.) &
4132  call mpistop("Error in add_source_res2: Non-conforming input limits")
4133 
4134  ixa^l=ixo^l^ladd1;
4135  ! Calculate current density within ixL: J=curl B, thus J_i=eps_ijk*d_j B_k
4136  ! Determine exact value of idirmin while doing the loop.
4137  call get_current(wct,ixi^l,ixa^l,idirmin,current)
4138 
4139  if (twofl_eta>zero)then
4140  eta(ixa^s)=twofl_eta
4141  else
4142  call usr_special_resistivity(wct,ixi^l,ixa^l,idirmin,x,current,eta)
4143  end if
4144 
4145  ! dB/dt= -curl(J*eta), thus B_i=B_i-eps_ijk d_j Jeta_k
4146  tmpvec(ixa^s,1:ndir)=zero
4147  do idir=idirmin,3
4148  tmpvec(ixa^s,idir)=current(ixa^s,idir)*eta(ixa^s)
4149  end do
4150  curlj=0.d0
4151  call curlvector(tmpvec,ixi^l,ixo^l,curlj,idirmin1,1,3)
4152  if(stagger_grid.and.ndim==2.and.ndir==3) then
4153  ! if 2.5D
4154  w(ixo^s,mag(ndir)) = w(ixo^s,mag(ndir))-qdt*curlj(ixo^s,ndir)
4155  else
4156  w(ixo^s,mag(1:ndir)) = w(ixo^s,mag(1:ndir))-qdt*curlj(ixo^s,1:ndir)
4157  end if
4158 
4159  if(phys_energy) then
4160  ! de/dt= +div(B x Jeta) = eta J^2 - B dot curl(eta J)
4161  ! de1/dt= eta J^2 - B1 dot curl(eta J)
4162  tmp(ixo^s)=eta(ixo^s)*sum(current(ixo^s,:)**2,dim=ndim+1)
4163  w(ixo^s,e_c_)=w(ixo^s,e_c_)+qdt*(tmp(ixo^s)-&
4164  sum(wct(ixo^s,mag(1:ndir))*curlj(ixo^s,1:ndir),dim=ndim+1))
4165  if(phys_solve_eaux) then
4166  ! add eta*J**2 source term in the internal energy equation
4167  w(ixo^s,eaux_c_)=w(ixo^s,eaux_c_)+tmp(ixo^s)
4168  end if
4169  end if
4170 
4171  if (fix_small_values) call twofl_handle_small_values(.false.,w,x,ixi^l,ixo^l,'add_source_res2')
4172  end subroutine add_source_res2
4173 
4174  !> Add Hyper-resistive source to w within ixO
4175  !> Uses 9 point stencil (4 neighbours) in each direction.
4176  subroutine add_source_hyperres(qdt,ixI^L,ixO^L,wCT,w,x)
4178  use mod_geometry
4179 
4180  integer, intent(in) :: ixI^L, ixO^L
4181  double precision, intent(in) :: qdt
4182  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
4183  double precision, intent(inout) :: w(ixI^S,1:nw)
4184  !.. local ..
4185  double precision :: current(ixI^S,7-2*ndir:3)
4186  double precision :: tmpvec(ixI^S,1:3),tmpvec2(ixI^S,1:3),tmp(ixI^S),ehyper(ixI^S,1:3)
4187  integer :: ixA^L,idir,jdir,kdir,idirmin,idirmin1
4188 
4189  ixa^l=ixo^l^ladd3;
4190  if (iximin^d>ixamin^d.or.iximax^d<ixamax^d|.or.) &
4191  call mpistop("Error in add_source_hyperres: Non-conforming input limits")
4192 
4193  call get_current(wct,ixi^l,ixa^l,idirmin,current)
4194  tmpvec(ixa^s,1:ndir)=zero
4195  do jdir=idirmin,3
4196  tmpvec(ixa^s,jdir)=current(ixa^s,jdir)
4197  end do
4198 
4199  ixa^l=ixo^l^ladd2;
4200  call curlvector(tmpvec,ixi^l,ixa^l,tmpvec2,idirmin1,1,3)
4201 
4202  ixa^l=ixo^l^ladd1;
4203  tmpvec(ixa^s,1:ndir)=zero
4204  call curlvector(tmpvec2,ixi^l,ixa^l,tmpvec,idirmin1,1,3)
4205  ehyper(ixa^s,1:ndir) = - tmpvec(ixa^s,1:ndir)*twofl_eta_hyper
4206 
4207  ixa^l=ixo^l;
4208  tmpvec2(ixa^s,1:ndir)=zero
4209  call curlvector(ehyper,ixi^l,ixa^l,tmpvec2,idirmin1,1,3)
4210 
4211  do idir=1,ndir
4212  w(ixo^s,mag(idir)) = w(ixo^s,mag(idir))-tmpvec2(ixo^s,idir)*qdt
4213  end do
4214 
4215  if (phys_energy) then
4216  ! de/dt= +div(B x Ehyper)
4217  ixa^l=ixo^l^ladd1;
4218  tmpvec2(ixa^s,1:ndir)=zero
4219  do idir=1,ndir; do jdir=1,ndir; do kdir=idirmin,3
4220  tmpvec2(ixa^s,idir) = tmpvec(ixa^s,idir)&
4221  + lvc(idir,jdir,kdir)*wct(ixa^s,mag(jdir))*ehyper(ixa^s,kdir)
4222  end do; end do; end do
4223  tmp(ixo^s)=zero
4224  call divvector(tmpvec2,ixi^l,ixo^l,tmp)
4225  w(ixo^s,e_c_)=w(ixo^s,e_c_)+tmp(ixo^s)*qdt
4226  end if
4227 
4228  if (fix_small_values) call twofl_handle_small_values(.false.,w,x,ixi^l,ixo^l,'add_source_hyperres')
4229 
4230  end subroutine add_source_hyperres
4231 
4232  subroutine add_source_glm(qdt,ixI^L,ixO^L,wCT,w,x)
4233  ! Add divB related sources to w within ixO
4234  ! corresponding to Dedner JCP 2002, 175, 645 _equation 24_
4235  ! giving the EGLM-MHD scheme
4237  use mod_geometry
4238 
4239  integer, intent(in) :: ixI^L, ixO^L
4240  double precision, intent(in) :: qdt, wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
4241  double precision, intent(inout) :: w(ixI^S,1:nw)
4242  double precision:: divb(ixI^S)
4243  integer :: idim,idir
4244  double precision :: gradPsi(ixI^S)
4245 
4246  ! We calculate now div B
4247  call get_divb(wct,ixi^l,ixo^l,divb, twofl_divb_4thorder)
4248 
4249  ! dPsi/dt = - Ch^2/Cp^2 Psi
4250  if (twofl_glm_alpha < zero) then
4251  w(ixo^s,psi_) = abs(twofl_glm_alpha)*wct(ixo^s,psi_)
4252  else
4253  ! implicit update of Psi variable
4254  ! equation (27) in Mignone 2010 J. Com. Phys. 229, 2117
4255  if(slab_uniform) then
4256  w(ixo^s,psi_) = dexp(-qdt*cmax_global*twofl_glm_alpha/minval(dxlevel(:)))*w(ixo^s,psi_)
4257  else
4258  w(ixo^s,psi_) = dexp(-qdt*cmax_global*twofl_glm_alpha/minval(block%ds(ixo^s,:),dim=ndim+1))*w(ixo^s,psi_)
4259  end if
4260  end if
4261 
4262  ! gradient of Psi
4263  do idim=1,ndim
4264  select case(typegrad)
4265  case("central")
4266  call gradient(wct(ixi^s,psi_),ixi^l,ixo^l,idim,gradpsi)
4267  case("limited")
4268  call gradients(wct(ixi^s,psi_),ixi^l,ixo^l,idim,gradpsi)
4269  end select
4270  if (phys_total_energy) then
4271  ! e = e -qdt (b . grad(Psi))
4272  w(ixo^s,e_c_) = w(ixo^s,e_c_)-qdt*wct(ixo^s,mag(idim))*gradpsi(ixo^s)
4273  end if
4274  end do
4275 
4276  ! m = m - qdt b div b
4277  do idir=1,ndir
4278  w(ixo^s,mom_c(idir))=w(ixo^s,mom_c(idir))-qdt*twofl_mag_i_all(w,ixi^l,ixo^l,idir)*divb(ixo^s)
4279  end do
4280 
4281  if (fix_small_values) call twofl_handle_small_values(.false.,w,x,ixi^l,ixo^l,'add_source_glm')
4282 
4283  end subroutine add_source_glm
4284 
4285  !> Add divB related sources to w within ixO corresponding to Powel
4286  subroutine add_source_powel(qdt,ixI^L,ixO^L,wCT,w,x)
4288 
4289  integer, intent(in) :: ixI^L, ixO^L
4290  double precision, intent(in) :: qdt, wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
4291  double precision, intent(inout) :: w(ixI^S,1:nw)
4292  double precision :: divb(ixI^S),v(ixI^S,1:ndir)
4293  integer :: idir
4294 
4295  ! We calculate now div B
4296  call get_divb(wct,ixi^l,ixo^l,divb, twofl_divb_4thorder)
4297 
4298  ! calculate velocity
4299  call twofl_get_v_c(wct,x,ixi^l,ixo^l,v)
4300 
4301  if (phys_total_energy) then
4302  ! e = e - qdt (v . b) * div b
4303  w(ixo^s,e_c_)=w(ixo^s,e_c_)-&
4304  qdt*sum(v(ixo^s,:)*wct(ixo^s,mag(:)),dim=ndim+1)*divb(ixo^s)
4305  end if
4306 
4307  ! b = b - qdt v * div b
4308  do idir=1,ndir
4309  w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*v(ixo^s,idir)*divb(ixo^s)
4310  end do
4311 
4312  ! m = m - qdt b div b
4313  do idir=1,ndir
4314  w(ixo^s,mom_c(idir))=w(ixo^s,mom_c(idir))-qdt*twofl_mag_i_all(w,ixi^l,ixo^l,idir)*divb(ixo^s)
4315  end do
4316 
4317  if (fix_small_values) call twofl_handle_small_values(.false.,w,x,ixi^l,ixo^l,'add_source_powel')
4318 
4319  end subroutine add_source_powel
4320 
4321  subroutine add_source_janhunen(qdt,ixI^L,ixO^L,wCT,w,x)
4322  ! Add divB related sources to w within ixO
4323  ! corresponding to Janhunen, just the term in the induction equation.
4325 
4326  integer, intent(in) :: ixI^L, ixO^L
4327  double precision, intent(in) :: qdt, wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
4328  double precision, intent(inout) :: w(ixI^S,1:nw)
4329  double precision :: divb(ixI^S),vel(ixI^S)
4330  integer :: idir
4331 
4332  ! We calculate now div B
4333  call get_divb(wct,ixi^l,ixo^l,divb, twofl_divb_4thorder)
4334 
4335  ! b = b - qdt v * div b
4336  do idir=1,ndir
4337  call twofl_get_v_c_idim(wct,x,ixi^l,ixo^l,idir,vel)
4338  w(ixo^s,mag(idir))=w(ixo^s,mag(idir))-qdt*vel(ixo^s)*divb(ixo^s)
4339  end do
4340 
4341  if (fix_small_values) call twofl_handle_small_values(.false.,w,x,ixi^l,ixo^l,'add_source_janhunen')
4342 
4343  end subroutine add_source_janhunen
4344 
4345  subroutine add_source_linde(qdt,ixI^L,ixO^L,wCT,w,x)
4346  ! Add Linde's divB related sources to wnew within ixO
4348  use mod_geometry
4349 
4350  integer, intent(in) :: ixI^L, ixO^L
4351  double precision, intent(in) :: qdt, wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
4352  double precision, intent(inout) :: w(ixI^S,1:nw)
4353  integer :: idim, idir, ixp^L, i^D, iside
4354  double precision :: divb(ixI^S),graddivb(ixI^S)
4355  logical, dimension(-1:1^D&) :: leveljump
4356 
4357  ! Calculate div B
4358  ixp^l=ixo^l^ladd1;
4359  call get_divb(wct,ixi^l,ixp^l,divb, twofl_divb_4thorder)
4360 
4361  ! for AMR stability, retreat one cell layer from the boarders of level jump
4362  {do i^db=-1,1\}
4363  if(i^d==0|.and.) cycle
4364  if(neighbor_type(i^d,block%igrid)==2 .or. neighbor_type(i^d,block%igrid)==4) then
4365  leveljump(i^d)=.true.
4366  else
4367  leveljump(i^d)=.false.
4368  end if
4369  {end do\}
4370 
4371  ixp^l=ixo^l;
4372  do idim=1,ndim
4373  select case(idim)
4374  {case(^d)
4375  do iside=1,2
4376  i^dd=kr(^dd,^d)*(2*iside-3);
4377  if (leveljump(i^dd)) then
4378  if (iside==1) then
4379  ixpmin^d=ixomin^d-i^d
4380  else
4381  ixpmax^d=ixomax^d-i^d
4382  end if
4383  end if
4384  end do
4385  \}
4386  end select
4387  end do
4388 
4389  ! Add Linde's diffusive terms
4390  do idim=1,ndim
4391  ! Calculate grad_idim(divb)
4392  select case(typegrad)
4393  case("central")
4394  call gradient(divb,ixi^l,ixp^l,idim,graddivb)
4395  case("limited")
4396  call gradients(divb,ixi^l,ixp^l,idim,graddivb)
4397  end select
4398 
4399  ! Multiply by Linde's eta*dt = divbdiff*(c_max*dx)*dt = divbdiff*dx**2
4400  if (slab_uniform) then
4401  graddivb(ixp^s)=graddivb(ixp^s)*divbdiff/(^d&1.0d0/dxlevel(^d)**2+)
4402  else
4403  graddivb(ixp^s)=graddivb(ixp^s)*divbdiff &
4404  /(^d&1.0d0/block%ds(ixp^s,^d)**2+)
4405  end if
4406 
4407  w(ixp^s,mag(idim))=w(ixp^s,mag(idim))+graddivb(ixp^s)
4408 
4409  if (typedivbdiff=='all' .and. phys_total_energy) then
4410  ! e += B_idim*eta*grad_idim(divb)
4411  w(ixp^s,e_c_)=w(ixp^s,e_c_)+wct(ixp^s,mag(idim))*graddivb(ixp^s)
4412  end if
4413  end do
4414 
4415  if (fix_small_values) call twofl_handle_small_values(.false.,w,x,ixi^l,ixo^l,'add_source_linde')
4416 
4417  end subroutine add_source_linde
4418 
4419  !> Calculate div B within ixO
4420  subroutine get_divb(w,ixI^L,ixO^L,divb, fourthorder)
4421 
4423  use mod_geometry
4424 
4425  integer, intent(in) :: ixi^l, ixo^l
4426  double precision, intent(in) :: w(ixi^s,1:nw)
4427  double precision, intent(inout) :: divb(ixi^s)
4428  logical, intent(in), optional :: fourthorder
4429 
4430  double precision :: bvec(ixi^s,1:ndir)
4431  double precision :: divb_corner(ixi^s), sign
4432  double precision :: aux_vol(ixi^s)
4433  integer :: ixc^l, idir, ic^d, ix^l
4434 
4435  if(stagger_grid) then
4436  divb=0.d0
4437  do idir=1,ndim
4438  ixc^l=ixo^l-kr(idir,^d);
4439  divb(ixo^s)=divb(ixo^s)+block%ws(ixo^s,idir)*block%surfaceC(ixo^s,idir)-&
4440  block%ws(ixc^s,idir)*block%surfaceC(ixc^s,idir)
4441  end do
4442  divb(ixo^s)=divb(ixo^s)/block%dvolume(ixo^s)
4443  else
4444  bvec(ixi^s,:)=w(ixi^s,mag(:))
4445  select case(typediv)
4446  case("central")
4447  call divvector(bvec,ixi^l,ixo^l,divb,fourthorder)
4448  case("limited")
4449  call divvectors(bvec,ixi^l,ixo^l,divb)
4450  end select
4451  end if
4452 
4453  end subroutine get_divb
4454 
4455  !> get dimensionless div B = |divB| * volume / area / |B|
4456  subroutine get_normalized_divb(w,ixI^L,ixO^L,divb)
4457 
4459 
4460  integer, intent(in) :: ixi^l, ixo^l
4461  double precision, intent(in) :: w(ixi^s,1:nw)
4462  double precision :: divb(ixi^s), dsurface(ixi^s)
4463 
4464  double precision :: invb(ixo^s)
4465  integer :: ixa^l,idims
4466 
4467  call get_divb(w,ixi^l,ixo^l,divb)
4468  invb(ixo^s)=sqrt(twofl_mag_en_all(w,ixi^l,ixo^l))
4469  where(invb(ixo^s)/=0.d0)
4470  invb(ixo^s)=1.d0/invb(ixo^s)
4471  end where
4472  if(slab_uniform) then
4473  divb(ixo^s)=0.5d0*abs(divb(ixo^s))*invb(ixo^s)/sum(1.d0/dxlevel(:))
4474  else
4475  ixamin^d=ixomin^d-1;
4476  ixamax^d=ixomax^d-1;
4477  dsurface(ixo^s)= sum(block%surfaceC(ixo^s,:),dim=ndim+1)
4478  do idims=1,ndim
4479  ixa^l=ixo^l-kr(idims,^d);
4480  dsurface(ixo^s)=dsurface(ixo^s)+block%surfaceC(ixa^s,idims)
4481  end do
4482  divb(ixo^s)=abs(divb(ixo^s))*invb(ixo^s)*&
4483  block%dvolume(ixo^s)/dsurface(ixo^s)
4484  end if
4485 
4486  end subroutine get_normalized_divb
4487 
4488  !> Calculate idirmin and the idirmin:3 components of the common current array
4489  !> make sure that dxlevel(^D) is set correctly.
4490  subroutine get_current(w,ixI^L,ixO^L,idirmin,current)
4492  use mod_geometry
4493 
4494  integer, intent(in) :: ixo^l, ixi^l
4495  double precision, intent(in) :: w(ixi^s,1:nw)
4496  integer, intent(out) :: idirmin
4497  integer :: idir, idirmin0
4498 
4499  ! For ndir=2 only 3rd component of J can exist, ndir=1 is impossible for MHD
4500  double precision :: current(ixi^s,7-2*ndir:3),bvec(ixi^s,1:ndir)
4501 
4502  idirmin0 = 7-2*ndir
4503 
4504  bvec(ixi^s,1:ndir)=w(ixi^s,mag(1:ndir))
4505 
4506  call curlvector(bvec,ixi^l,ixo^l,current,idirmin,idirmin0,ndir)
4507 
4508  if(b0field) current(ixo^s,idirmin0:3)=current(ixo^s,idirmin0:3)+&
4509  block%J0(ixo^s,idirmin0:3)
4510 
4511  end subroutine get_current
4512 
4513  ! copied from gravity
4514  !> w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO
4515  subroutine gravity_add_source(qdt,ixI^L,ixO^L,wCT,w,x,&
4516  energy,qsourcesplit,active)
4518  use mod_usr_methods
4519 
4520  integer, intent(in) :: ixI^L, ixO^L
4521  double precision, intent(in) :: qdt, x(ixI^S,1:ndim)
4522  double precision, intent(in) :: wCT(ixI^S,1:nw)
4523  double precision, intent(inout) :: w(ixI^S,1:nw)
4524  logical, intent(in) :: energy,qsourcesplit
4525  logical, intent(inout) :: active
4526  double precision :: vel(ixI^S)
4527  integer :: idim
4528 
4529  double precision :: gravity_field(ixI^S,ndim)
4530 
4531  if(qsourcesplit .eqv. grav_split) then
4532  active = .true.
4533 
4534  if (.not. associated(usr_gravity)) then
4535  write(*,*) "mod_usr.t: please point usr_gravity to a subroutine"
4536  write(*,*) "like the phys_gravity in mod_usr_methods.t"
4537  call mpistop("gravity_add_source: usr_gravity not defined")
4538  else
4539  call usr_gravity(ixi^l,ixo^l,wct,x,gravity_field)
4540  end if
4541 
4542  do idim = 1, ndim
4543  w(ixo^s,mom_n(idim)) = w(ixo^s,mom_n(idim)) &
4544  + qdt * gravity_field(ixo^s,idim) * wct(ixo^s,rho_n_)
4545  w(ixo^s,mom_c(idim)) = w(ixo^s,mom_c(idim)) &
4546  + qdt * gravity_field(ixo^s,idim) * wct(ixo^s,rho_c_)
4547  if(energy) then
4548 #if !defined(E_RM_W0) || E_RM_W0 == 1
4549  call twofl_get_v_n_idim(wct,x,ixi^l,ixo^l,idim,vel)
4550  w(ixo^s,e_n_)=w(ixo^s,e_n_) &
4551  + qdt * gravity_field(ixo^s,idim) * vel(ixo^s) * wct(ixo^s,rho_n_)
4552  call twofl_get_v_c_idim(wct,x,ixi^l,ixo^l,idim,vel)
4553  w(ixo^s,e_c_)=w(ixo^s,e_c_) &
4554  + qdt * gravity_field(ixo^s,idim) * vel(ixo^s) * wct(ixo^s,rho_c_)
4555 #else
4556  w(ixo^s,e_n_)=w(ixo^s,e_n_) &
4557  + qdt * gravity_field(ixo^s,idim) * wct(ixo^s,mom_n(idim))
4558  w(ixo^s,e_c_)=w(ixo^s,e_c_) &
4559  + qdt * gravity_field(ixo^s,idim) * wct(ixo^s,mom_c(idim))
4560 #endif
4561 
4562 
4563  end if
4564  end do
4565  end if
4566 
4567  end subroutine gravity_add_source
4568 
4569  subroutine gravity_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
4571  use mod_usr_methods
4572 
4573  integer, intent(in) :: ixI^L, ixO^L
4574  double precision, intent(in) :: dx^D, x(ixI^S,1:ndim), w(ixI^S,1:nw)
4575  double precision, intent(inout) :: dtnew
4576 
4577  double precision :: dxinv(1:ndim), max_grav
4578  integer :: idim
4579 
4580  double precision :: gravity_field(ixI^S,ndim)
4581 
4582  ^d&dxinv(^d)=one/dx^d;
4583 
4584  if(.not. associated(usr_gravity)) then
4585  write(*,*) "mod_usr.t: please point usr_gravity to a subroutine"
4586  write(*,*) "like the phys_gravity in mod_usr_methods.t"
4587  call mpistop("gravity_get_dt: usr_gravity not defined")
4588  else
4589  call usr_gravity(ixi^l,ixo^l,w,x,gravity_field)
4590  end if
4591 
4592  do idim = 1, ndim
4593  max_grav = maxval(abs(gravity_field(ixo^s,idim)))
4594  max_grav = max(max_grav, epsilon(1.0d0))
4595  dtnew = min(dtnew, 1.0d0 / sqrt(max_grav * dxinv(idim)))
4596  end do
4597 
4598  end subroutine gravity_get_dt
4599 
4600 
4601  !> If resistivity is not zero, check diffusion time limit for dt
4602  subroutine twofl_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
4604  use mod_usr_methods
4606  !use mod_viscosity, only: viscosity_get_dt
4607  !use mod_gravity, only: gravity_get_dt
4608 
4609  integer, intent(in) :: ixI^L, ixO^L
4610  double precision, intent(inout) :: dtnew
4611  double precision, intent(in) :: dx^D
4612  double precision, intent(in) :: w(ixI^S,1:nw)
4613  double precision, intent(in) :: x(ixI^S,1:ndim)
4614 
4615  integer :: idirmin,idim
4616  double precision :: dxarr(ndim)
4617  double precision :: current(ixI^S,7-2*ndir:3),eta(ixI^S)
4618 
4619  dtnew = bigdouble
4620 
4621  ^d&dxarr(^d)=dx^d;
4622  if (twofl_eta>zero)then
4623  dtnew=dtdiffpar*minval(dxarr(1:ndim))**2/twofl_eta
4624  else if (twofl_eta<zero)then
4625  call get_current(w,ixi^l,ixo^l,idirmin,current)
4626  call usr_special_resistivity(w,ixi^l,ixo^l,idirmin,x,current,eta)
4627  dtnew=bigdouble
4628  do idim=1,ndim
4629  if(slab_uniform) then
4630  dtnew=min(dtnew,&
4631  dtdiffpar/(smalldouble+maxval(eta(ixo^s)/dxarr(idim)**2)))
4632  else
4633  dtnew=min(dtnew,&
4634  dtdiffpar/(smalldouble+maxval(eta(ixo^s)/block%ds(ixo^s,idim)**2)))
4635  end if
4636  end do
4637  end if
4638 
4639  if(twofl_eta_hyper>zero) then
4640  if(slab_uniform) then
4641  dtnew=min(dtdiffpar*minval(dxarr(1:ndim))**4/twofl_eta_hyper,dtnew)
4642  else
4643  dtnew=min(dtdiffpar*minval(block%ds(ixo^s,1:ndim))**4/twofl_eta_hyper,dtnew)
4644  end if
4645  end if
4646 
4647  ! the timestep related to coll terms: 1/(rho_n rho_c alpha)
4648  if(dtcollpar>0d0 .and. has_collisions()) then
4649  call coll_get_dt(w,x,ixi^l,ixo^l,dtnew)
4650  endif
4651 
4652  if(twofl_radiative_cooling_c) then
4653  call cooling_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x,rc_fl_c)
4654  end if
4655  if(twofl_radiative_cooling_n) then
4656  call cooling_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x,rc_fl_n)
4657  end if
4658 !
4659 ! if(twofl_viscosity) then
4660 ! call viscosity_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
4661 ! end if
4662 !
4663  if(twofl_gravity) then
4664  call gravity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
4665  end if
4666  if(twofl_hyperdiffusivity) then
4667  call hyperdiffusivity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
4668  end if
4669 
4670 
4671  end subroutine twofl_get_dt
4672 
4673  pure function has_collisions() result(res)
4674  logical :: res
4675  res = .not. twofl_alpha_coll_constant .or. twofl_alpha_coll >0d0
4676  end function has_collisions
4677 
4678  subroutine coll_get_dt(w,x,ixI^L,ixO^L,dtnew)
4680  integer, intent(in) :: ixi^l, ixo^l
4681  double precision, intent(in) :: w(ixi^s,1:nw)
4682  double precision, intent(in) :: x(ixi^s,1:ndim)
4683  double precision, intent(inout) :: dtnew
4684 
4685  double precision :: rhon(ixi^s), rhoc(ixi^s), alpha(ixi^s)
4686  double precision, allocatable :: gamma_rec(:^d&), gamma_ion(:^D&)
4687  double precision :: max_coll_rate
4688 
4689  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
4690  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
4691 
4692  call get_alpha_coll(ixi^l, ixo^l, w, x, alpha)
4693  max_coll_rate = maxval(alpha(ixo^s) * max(rhon(ixo^s), rhoc(ixo^s)))
4694 
4695  if(twofl_coll_inc_ionrec) then
4696  allocate(gamma_ion(ixi^s), gamma_rec(ixi^s))
4697  call get_gamma_ion_rec(ixi^l, ixo^l, w, x, gamma_rec, gamma_ion)
4698  max_coll_rate=max(max_coll_rate, maxval(gamma_ion(ixo^s)), maxval(gamma_rec(ixo^s)))
4699  deallocate(gamma_ion, gamma_rec)
4700  endif
4701  dtnew = min(dtcollpar/max_coll_rate, dtnew)
4702 
4703  end subroutine coll_get_dt
4704 
4705  ! Add geometrical source terms to w
4706  subroutine twofl_add_source_geom(qdt,ixI^L,ixO^L,wCT,w,x)
4708  use mod_geometry
4709 
4710  integer, intent(in) :: ixI^L, ixO^L
4711  double precision, intent(in) :: qdt, x(ixI^S,1:ndim)
4712  double precision, intent(inout) :: wCT(ixI^S,1:nw), w(ixI^S,1:nw)
4713 
4714  integer :: iw,idir, h1x^L{^NOONED, h2x^L}
4715  double precision :: tmp(ixI^S),tmp1(ixI^S),tmp2(ixI^S),rho(ixI^S)
4716 
4717  integer :: mr_,mphi_ ! Polar var. names
4718  integer :: br_,bphi_
4719 
4720  ! charges
4721 
4722  mr_=mom_c(1); mphi_=mom_c(1)-1+phi_ ! Polar var. names
4723  br_=mag(1); bphi_=mag(1)-1+phi_
4724  call get_rhoc_tot(wct,x,ixi^l,ixo^l,rho)
4725 
4726  select case (coordinate)
4727  case (cylindrical)
4728  if (angmomfix) then
4729  call mpistop("angmomfix not implemented yet in MHD")
4730  endif
4731  call twofl_get_p_c_total(wct,x,ixi^l,ixo^l,tmp)
4732 
4733  if(phi_>0) then
4734  w(ixo^s,mr_)=w(ixo^s,mr_)+qdt/x(ixo^s,1)*(tmp(ixo^s)-&
4735  wct(ixo^s,bphi_)**2+wct(ixo^s,mphi_)**2/rho(ixo^s))
4736  w(ixo^s,mphi_)=w(ixo^s,mphi_)+qdt/x(ixo^s,1)*(&
4737  -wct(ixo^s,mphi_)*wct(ixo^s,mr_)/rho(ixo^s) &
4738  +wct(ixo^s,bphi_)*wct(ixo^s,br_))
4739  if(.not.stagger_grid) then
4740  w(ixo^s,bphi_)=w(ixo^s,bphi_)+qdt/x(ixo^s,1)*&
4741  (wct(ixo^s,bphi_)*wct(ixo^s,mr_) &
4742  -wct(ixo^s,br_)*wct(ixo^s,mphi_)) &
4743  /rho(ixo^s)
4744  end if
4745  else
4746  w(ixo^s,mr_)=w(ixo^s,mr_)+qdt/x(ixo^s,1)*tmp(ixo^s)
4747  end if
4748  if(twofl_glm) w(ixo^s,br_)=w(ixo^s,br_)+qdt*wct(ixo^s,psi_)/x(ixo^s,1)
4749  case (spherical)
4750  h1x^l=ixo^l-kr(1,^d); {^nooned h2x^l=ixo^l-kr(2,^d);}
4751  call twofl_get_p_c_total(wct,x,ixi^l,ixo^l,tmp1)
4752  tmp(ixo^s)=tmp1(ixo^s)
4753  if(b0field) then
4754  tmp2(ixo^s)=sum(block%B0(ixo^s,:,0)*wct(ixo^s,mag(:)),dim=ndim+1)
4755  tmp(ixo^s)=tmp(ixo^s)+tmp2(ixo^s)
4756  end if
4757  ! m1
4758  tmp(ixo^s)=tmp(ixo^s)*x(ixo^s,1) &
4759  *(block%surfaceC(ixo^s,1)-block%surfaceC(h1x^s,1))/block%dvolume(ixo^s)
4760  if(ndir>1) then
4761  do idir=2,ndir
4762  tmp(ixo^s)=tmp(ixo^s)+wct(ixo^s,mom_c(idir))**2/rho(ixo^s)-wct(ixo^s,mag(idir))**2
4763  if(b0field) tmp(ixo^s)=tmp(ixo^s)-2.0d0*block%B0(ixo^s,idir,0)*wct(ixo^s,mag(idir))
4764  end do
4765  end if
4766  w(ixo^s,mom_c(1))=w(ixo^s,mom_c(1))+qdt*tmp(ixo^s)/x(ixo^s,1)
4767  ! b1
4768  if(twofl_glm) then
4769  w(ixo^s,mag(1))=w(ixo^s,mag(1))+qdt/x(ixo^s,1)*2.0d0*wct(ixo^s,psi_)
4770  end if
4771 
4772  {^nooned
4773  ! m2
4774  tmp(ixo^s)=tmp1(ixo^s)
4775  if(b0field) then
4776  tmp(ixo^s)=tmp(ixo^s)+tmp2(ixo^s)
4777  end if
4778  ! This will make hydrostatic p=const an exact solution
4779  w(ixo^s,mom_c(2))=w(ixo^s,mom_c(2))+qdt*tmp(ixo^s) &
4780  *(block%surfaceC(ixo^s,2)-block%surfaceC(h2x^s,2)) &
4781  /block%dvolume(ixo^s)
4782  tmp(ixo^s)=-(wct(ixo^s,mom_c(1))*wct(ixo^s,mom_c(2))/rho(ixo^s) &
4783  -wct(ixo^s,mag(1))*wct(ixo^s,mag(2)))
4784  if (b0field) then
4785  tmp(ixo^s)=tmp(ixo^s)+block%B0(ixo^s,1,0)*wct(ixo^s,mag(2)) &
4786  +wct(ixo^s,mag(1))*block%B0(ixo^s,2,0)
4787  end if
4788  if(ndir==3) then
4789  tmp(ixo^s)=tmp(ixo^s)+(wct(ixo^s,mom_c(3))**2/rho(ixo^s) &
4790  -wct(ixo^s,mag(3))**2)*dcos(x(ixo^s,2))/dsin(x(ixo^s,2))
4791  if (b0field) then
4792  tmp(ixo^s)=tmp(ixo^s)-2.0d0*block%B0(ixo^s,3,0)*wct(ixo^s,mag(3))&
4793  *dcos(x(ixo^s,2))/dsin(x(ixo^s,2))
4794  end if
4795  end if
4796  w(ixo^s,mom_c(2))=w(ixo^s,mom_c(2))+qdt*tmp(ixo^s)/x(ixo^s,1)
4797  ! b2
4798  if(.not.stagger_grid) then
4799  tmp(ixo^s)=(wct(ixo^s,mom_c(1))*wct(ixo^s,mag(2)) &
4800  -wct(ixo^s,mom_c(2))*wct(ixo^s,mag(1)))/rho(ixo^s)
4801  if(b0field) then
4802  tmp(ixo^s)=tmp(ixo^s)+(wct(ixo^s,mom_c(1))*block%B0(ixo^s,2,0) &
4803  -wct(ixo^s,mom_c(2))*block%B0(ixo^s,1,0))/rho(ixo^s)
4804  end if
4805  if(twofl_glm) then
4806  tmp(ixo^s)=tmp(ixo^s) &
4807  + dcos(x(ixo^s,2))/dsin(x(ixo^s,2))*wct(ixo^s,psi_)
4808  end if
4809  w(ixo^s,mag(2))=w(ixo^s,mag(2))+qdt*tmp(ixo^s)/x(ixo^s,1)
4810  end if
4811  }
4812 
4813  if(ndir==3) then
4814  ! m3
4815  if(.not.angmomfix) then
4816  tmp(ixo^s)=-(wct(ixo^s,mom_c(3))*wct(ixo^s,mom_c(1))/rho(ixo^s) &
4817  -wct(ixo^s,mag(3))*wct(ixo^s,mag(1))) {^nooned &
4818  -(wct(ixo^s,mom_c(2))*wct(ixo^s,mom_c(3))/rho(ixo^s) &
4819  -wct(ixo^s,mag(2))*wct(ixo^s,mag(3))) &
4820  *dcos(x(ixo^s,2))/dsin(x(ixo^s,2)) }
4821  if (b0field) then
4822  tmp(ixo^s)=tmp(ixo^s)+block%B0(ixo^s,1,0)*wct(ixo^s,mag(3)) &
4823  +wct(ixo^s,mag(1))*block%B0(ixo^s,3,0) {^nooned &
4824  +(block%B0(ixo^s,2,0)*wct(ixo^s,mag(3)) &
4825  +wct(ixo^s,mag(2))*block%B0(ixo^s,3,0)) &
4826  *dcos(x(ixo^s,2))/dsin(x(ixo^s,2)) }
4827  end if
4828  w(ixo^s,mom_c(3))=w(ixo^s,mom_c(3))+qdt*tmp(ixo^s)/x(ixo^s,1)
4829  else
4830  call mpistop("angmomfix not implemented yet in MHD")
4831  end if
4832  ! b3
4833  if(.not.stagger_grid) then
4834  tmp(ixo^s)=(wct(ixo^s,mom_c(1))*wct(ixo^s,mag(3)) &
4835  -wct(ixo^s,mom_c(3))*wct(ixo^s,mag(1)))/rho(ixo^s) {^nooned &
4836  -(wct(ixo^s,mom_c(3))*wct(ixo^s,mag(2)) &
4837  -wct(ixo^s,mom_c(2))*wct(ixo^s,mag(3)))*dcos(x(ixo^s,2)) &
4838  /(rho(ixo^s)*dsin(x(ixo^s,2))) }
4839  if (b0field) then
4840  tmp(ixo^s)=tmp(ixo^s)+(wct(ixo^s,mom_c(1))*block%B0(ixo^s,3,0) &
4841  -wct(ixo^s,mom_c(3))*block%B0(ixo^s,1,0))/rho(ixo^s){^nooned &
4842  -(wct(ixo^s,mom_c(3))*block%B0(ixo^s,2,0) &
4843  -wct(ixo^s,mom_c(2))*block%B0(ixo^s,3,0))*dcos(x(ixo^s,2)) &
4844  /(rho(ixo^s)*dsin(x(ixo^s,2))) }
4845  end if
4846  w(ixo^s,mag(3))=w(ixo^s,mag(3))+qdt*tmp(ixo^s)/x(ixo^s,1)
4847  end if
4848  end if
4849  end select
4850 
4851  ! neutrals
4852  !TODO no dust: see and implement them from hd/mod_hd_phys !
4853  !uncomment cartesian expansion
4854  call get_rhon_tot(wct,x,ixi^l,ixo^l,rho)
4855  call twofl_get_pthermal_n(wct, x, ixi^l, ixo^l, tmp1)
4856 
4857  select case (coordinate)
4858 ! case(Cartesian_expansion)
4859 ! !the user provides the functions of exp_factor and del_exp_factor
4860 ! if(associated(usr_set_surface)) call usr_set_surface(ixI^L,x,block%dx,exp_factor,del_exp_factor,exp_factor_primitive)
4861 ! tmp(ixO^S) = tmp1(ixO^S)*del_exp_factor(ixO^S)/exp_factor(ixO^S)
4862 ! w(ixO^S,mom(1)) = w(ixO^S,mom(1)) + qdt*tmp(ixO^S)
4863 
4864  case (cylindrical)
4865  mr_ = mom_n(r_)
4866  if (phi_ > 0) then
4867  where (rho(ixo^s) > 0d0)
4868  tmp(ixo^s) = tmp1(ixo^s) + wct(ixo^s, mphi_)**2 / rho(ixo^s)
4869  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * tmp(ixo^s) / x(ixo^s, r_)
4870  end where
4871  ! s[mphi]=(-mphi*mr/rho)/radius
4872  if(.not. angmomfix) then
4873  where (rho(ixo^s) > 0d0)
4874  tmp(ixo^s) = -wct(ixo^s, mphi_) * wct(ixo^s, mr_) / rho(ixo^s)
4875  w(ixo^s, mphi_) = w(ixo^s, mphi_) + qdt * tmp(ixo^s) / x(ixo^s, r_)
4876  end where
4877  end if
4878  else
4879  ! s[mr]=2pthermal/radius
4880  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * tmp1(ixo^s) / x(ixo^s, r_)
4881  end if
4882  case (spherical)
4883  if(phi_>0) mphi_ = mom_n(phi_)
4884  h1x^l=ixo^l-kr(1,^d); {^nooned h2x^l=ixo^l-kr(2,^d);}
4885  ! s[mr]=((mtheta**2+mphi**2)/rho+2*p)/r
4886  tmp(ixo^s) = tmp1(ixo^s) * x(ixo^s, 1) &
4887  *(block%surfaceC(ixo^s, 1) - block%surfaceC(h1x^s, 1)) &
4888  /block%dvolume(ixo^s)
4889  if (ndir > 1) then
4890  do idir = 2, ndir
4891  tmp(ixo^s) = tmp(ixo^s) + wct(ixo^s, mom_n(idir))**2 / rho(ixo^s)
4892  end do
4893  end if
4894  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * tmp(ixo^s) / x(ixo^s, 1)
4895 
4896  {^nooned
4897  ! s[mtheta]=-(mr*mtheta/rho)/r+cot(theta)*(mphi**2/rho+p)/r
4898  tmp(ixo^s) = tmp1(ixo^s) * x(ixo^s, 1) &
4899  * (block%surfaceC(ixo^s, 2) - block%surfaceC(h2x^s, 2)) &
4900  / block%dvolume(ixo^s)
4901  if (ndir == 3) then
4902  tmp(ixo^s) = tmp(ixo^s) + (wct(ixo^s, mom_n(3))**2 / rho(ixo^s)) / tan(x(ixo^s, 2))
4903  end if
4904  if (.not. angmomfix) then
4905  tmp(ixo^s) = tmp(ixo^s) - (wct(ixo^s, mom_n(2)) * wct(ixo^s, mr_)) / rho(ixo^s)
4906  end if
4907  w(ixo^s, mom_n(2)) = w(ixo^s, mom_n(2)) + qdt * tmp(ixo^s) / x(ixo^s, 1)
4908 
4909  if (ndir == 3) then
4910  ! s[mphi]=-(mphi*mr/rho)/r-cot(theta)*(mtheta*mphi/rho)/r
4911  if (.not. angmomfix) then
4912  tmp(ixo^s) = -(wct(ixo^s, mom_n(3)) * wct(ixo^s, mr_)) / rho(ixo^s)&
4913  - (wct(ixo^s, mom_n(2)) * wct(ixo^s, mom_n(3))) / rho(ixo^s) / tan(x(ixo^s, 2))
4914  w(ixo^s, mom_n(3)) = w(ixo^s, mom_n(3)) + qdt * tmp(ixo^s) / x(ixo^s, 1)
4915  end if
4916  end if
4917  }
4918  end select
4919 
4920 ! if (hd_viscosity) call visc_add_source_geom(qdt,ixI^L,ixO^L,wCT,w,x)
4921 !
4922 ! if (hd_rotating_frame) then
4923 ! if (hd_dust) then
4924 ! call mpistop("Rotating frame not implemented yet with dust")
4925 ! else
4926 ! call rotating_frame_add_source(qdt,ixI^L,ixO^L,wCT,w,x)
4927 ! end if
4928 ! end if
4929 !
4930 
4931  contains
4932  subroutine twofl_get_p_c_total(w,x,ixI^L,ixO^L,p)
4934 
4935  integer, intent(in) :: ixI^L, ixO^L
4936  double precision, intent(in) :: w(ixI^S,nw)
4937  double precision, intent(in) :: x(ixI^S,1:ndim)
4938  double precision, intent(out) :: p(ixI^S)
4939 
4940  call twofl_get_pthermal_c(w,x,ixi^l,ixo^l,p)
4941 
4942  p(ixo^s) = p(ixo^s) + 0.5d0 * sum(w(ixo^s, mag(:))**2, dim=ndim+1)
4943 
4944  end subroutine twofl_get_p_c_total
4945 
4946  end subroutine twofl_add_source_geom
4947 
4948  subroutine twofl_get_temp_c_pert_from_etot(w, x, ixI^L, ixO^L, res)
4950  integer, intent(in) :: ixI^L, ixO^L
4951  double precision, intent(in) :: w(ixI^S, 1:nw)
4952  double precision, intent(in) :: x(ixI^S, 1:ndim)
4953  double precision, intent(out):: res(ixI^S)
4954 
4955  ! store pe1 in res
4956  res(ixo^s)=(gamma_1*(w(ixo^s,e_c_)&
4957  - twofl_kin_en_c(w,ixi^l,ixo^l)&
4958  - twofl_mag_en(w,ixi^l,ixo^l)))
4959  if(has_equi_pe_c0) then
4960  res(ixo^s) = res(ixo^s) + block%equi_vars(ixo^s,equi_pe_c0_,b0i)
4961  if(has_equi_rho_c0) then
4962  res(ixo^s) = res(ixo^s)/(rc * (w(ixo^s,rho_c_)+ block%equi_vars(ixo^s,equi_rho_c0_,b0i))) - &
4963  block%equi_vars(ixo^s,equi_pe_c0_,b0i)/(rc * block%equi_vars(ixo^s,equi_rho_c0_,b0i))
4964  else
4965  ! infinite equi temperature with p0 and 0 density
4966  res(ixo^s) = 0d0
4967  endif
4968  else
4969  res(ixo^s) = res(ixo^s)/(rc * w(ixo^s,rho_c_))
4970  endif
4971 
4972  end subroutine twofl_get_temp_c_pert_from_etot
4973 
4974  !> Compute 2 times total magnetic energy
4975  function twofl_mag_en_all(w, ixI^L, ixO^L) result(mge)
4977  integer, intent(in) :: ixi^l, ixo^l
4978  double precision, intent(in) :: w(ixi^s, nw)
4979  double precision :: mge(ixo^s)
4980 
4981  if (b0field) then
4982  mge(ixo^s) = sum((w(ixo^s, mag(:))+block%B0(ixo^s,:,b0i))**2, dim=ndim+1)
4983  else
4984  mge(ixo^s) = sum(w(ixo^s, mag(:))**2, dim=ndim+1)
4985  end if
4986  end function twofl_mag_en_all
4987 
4988  !> Compute full magnetic field by direction
4989  function twofl_mag_i_all(w, ixI^L, ixO^L,idir) result(mgf)
4991  integer, intent(in) :: ixi^l, ixo^l, idir
4992  double precision, intent(in) :: w(ixi^s, nw)
4993  double precision :: mgf(ixo^s)
4994 
4995  if (b0field) then
4996  mgf(ixo^s) = w(ixo^s, mag(idir))+block%B0(ixo^s,idir,b0i)
4997  else
4998  mgf(ixo^s) = w(ixo^s, mag(idir))
4999  end if
5000  end function twofl_mag_i_all
5001 
5002  !> Compute evolving magnetic energy
5003  function twofl_mag_en(w, ixI^L, ixO^L) result(mge)
5004  use mod_global_parameters, only: nw, ndim
5005  integer, intent(in) :: ixi^l, ixo^l
5006  double precision, intent(in) :: w(ixi^s, nw)
5007  double precision :: mge(ixo^s)
5008 
5009  mge(ixo^s) = 0.5d0 * sum(w(ixo^s, mag(:))**2, dim=ndim+1)
5010  end function twofl_mag_en
5011 
5012  !> compute kinetic energy of neutrals
5013  function twofl_kin_en_n(w, ixI^L, ixO^L) result(ke)
5014  use mod_global_parameters, only: nw, ndim,block
5015  integer, intent(in) :: ixi^l, ixo^l
5016  double precision, intent(in) :: w(ixi^s, nw)
5017  double precision :: ke(ixo^s)
5018 
5019  if(has_equi_rho_n0) then
5020  ke(ixo^s) = 0.5d0 * sum(w(ixo^s, mom_n(:))**2, dim=ndim+1) / (w(ixo^s, rho_n_) + block%equi_vars(ixo^s,equi_rho_n0_,0))
5021  else
5022  ke(ixo^s) = 0.5d0 * sum(w(ixo^s, mom_n(:))**2, dim=ndim+1) / w(ixo^s, rho_n_)
5023  endif
5024 
5025  end function twofl_kin_en_n
5026 
5027  subroutine twofl_get_temp_n_pert_from_etot(w, x, ixI^L, ixO^L, res)
5029  integer, intent(in) :: ixI^L, ixO^L
5030  double precision, intent(in) :: w(ixI^S, 1:nw)
5031  double precision, intent(in) :: x(ixI^S, 1:ndim)
5032  double precision, intent(out):: res(ixI^S)
5033 
5034  ! store pe1 in res
5035  res(ixo^s)=(gamma_1*(w(ixo^s,e_c_)- twofl_kin_en_c(w,ixi^l,ixo^l)))
5036  if(has_equi_pe_n0) then
5037  res(ixo^s) = res(ixo^s) + block%equi_vars(ixo^s,equi_pe_n0_,b0i)
5038  if(has_equi_rho_n0) then
5039  res(ixo^s) = res(ixo^s)/(rn * (w(ixo^s,rho_n_)+ block%equi_vars(ixo^s,equi_rho_n0_,b0i))) - &
5040  block%equi_vars(ixo^s,equi_pe_n0_,b0i)/(rn * block%equi_vars(ixo^s,equi_rho_n0_,b0i))
5041  else
5042  ! infinite equi temperature with p0 and 0 density
5043  res(ixo^s) = 0d0
5044  endif
5045  else
5046  res(ixo^s) = res(ixo^s)/(rn * w(ixo^s,rho_n_))
5047  endif
5048 
5049  end subroutine twofl_get_temp_n_pert_from_etot
5050 
5051  !> compute kinetic energy of charges
5052  !> w are conserved variables
5053  function twofl_kin_en_c(w, ixI^L, ixO^L) result(ke)
5054  use mod_global_parameters, only: nw, ndim,block
5055  integer, intent(in) :: ixi^l, ixo^l
5056  double precision, intent(in) :: w(ixi^s, nw)
5057  double precision :: ke(ixo^s)
5058 
5059  if(has_equi_rho_c0) then
5060  ke(ixo^s) = 0.5d0 * sum(w(ixo^s, mom_c(:))**2, dim=ndim+1) / (w(ixo^s, rho_c_) + block%equi_vars(ixo^s,equi_rho_c0_,0))
5061  else
5062  ke(ixo^s) = 0.5d0 * sum(w(ixo^s, mom_c(:))**2, dim=ndim+1) / w(ixo^s, rho_c_)
5063  endif
5064  end function twofl_kin_en_c
5065 
5066  subroutine twofl_getv_hall(w,x,ixI^L,ixO^L,vHall)
5068 
5069  integer, intent(in) :: ixI^L, ixO^L
5070  double precision, intent(in) :: w(ixI^S,nw)
5071  double precision, intent(in) :: x(ixI^S,1:ndim)
5072  double precision, intent(inout) :: vHall(ixI^S,1:3)
5073 
5074  integer :: idir, idirmin
5075  double precision :: current(ixI^S,7-2*ndir:3)
5076  double precision :: rho(ixI^S)
5077 
5078  call get_rhoc_tot(w,x,ixi^l,ixo^l,rho)
5079  ! Calculate current density and idirmin
5080  call get_current(w,ixi^l,ixo^l,idirmin,current)
5081  vhall(ixo^s,1:3) = zero
5082  vhall(ixo^s,idirmin:3) = - twofl_etah*current(ixo^s,idirmin:3)
5083  do idir = idirmin, 3
5084  vhall(ixo^s,idir) = vhall(ixo^s,idir)/rho(ixo^s)
5085  end do
5086 
5087  end subroutine twofl_getv_hall
5088 
5089 ! the following not used
5090 ! subroutine twofl_getdt_Hall(w,x,ixI^L,ixO^L,dx^D,dthall)
5091 ! use mod_global_parameters
5092 !
5093 ! integer, intent(in) :: ixI^L, ixO^L
5094 ! double precision, intent(in) :: dx^D
5095 ! double precision, intent(in) :: w(ixI^S,1:nw)
5096 ! double precision, intent(in) :: x(ixI^S,1:ndim)
5097 ! double precision, intent(out) :: dthall
5098 ! !.. local ..
5099 ! double precision :: dxarr(ndim)
5100 ! double precision :: bmag(ixI^S)
5101 !
5102 ! dthall=bigdouble
5103 !
5104 ! ! because we have that in cmax now:
5105 ! return
5106 !
5107 ! ^D&dxarr(^D)=dx^D;
5108 !
5109 ! if (.not. B0field) then
5110 ! bmag(ixO^S)=sqrt(sum(w(ixO^S,mag(:))**2, dim=ndim+1))
5111 ! bmag(ixO^S)=sqrt(sum((w(ixO^S,mag(:)) + block%B0(ixO^S,1:ndir,b0i))**2))
5112 ! end if
5113 !
5114 ! if(slab_uniform) then
5115 ! dthall=dtdiffpar*minval(dxarr(1:ndim))**2.0d0/(twofl_etah*maxval(bmag(ixO^S)/w(ixO^S,rho_c_)))
5116 ! else
5117 ! dthall=dtdiffpar*minval(block%ds(ixO^S,1:ndim))**2.0d0/(twofl_etah*maxval(bmag(ixO^S)/w(ixO^S,rho_c_)))
5118 ! end if
5119 !
5120 ! end subroutine twofl_getdt_Hall
5121 
5122  subroutine twofl_modify_wlr(ixI^L,ixO^L,qt,wLC,wRC,wLp,wRp,s,idir)
5124  use mod_usr_methods
5125  integer, intent(in) :: ixI^L, ixO^L, idir
5126  double precision, intent(in) :: qt
5127  double precision, intent(inout) :: wLC(ixI^S,1:nw), wRC(ixI^S,1:nw)
5128  double precision, intent(inout) :: wLp(ixI^S,1:nw), wRp(ixI^S,1:nw)
5129  type(state) :: s
5130  double precision :: dB(ixI^S), dPsi(ixI^S)
5131 
5132  if(stagger_grid) then
5133  wlc(ixo^s,mag(idir))=s%ws(ixo^s,idir)
5134  wrc(ixo^s,mag(idir))=s%ws(ixo^s,idir)
5135  wlp(ixo^s,mag(idir))=s%ws(ixo^s,idir)
5136  wrp(ixo^s,mag(idir))=s%ws(ixo^s,idir)
5137  else
5138  ! Solve the Riemann problem for the linear 2x2 system for normal
5139  ! B-field and GLM_Psi according to Dedner 2002:
5140  ! This implements eq. (42) in Dedner et al. 2002 JcP 175
5141  ! Gives the Riemann solution on the interface
5142  ! for the normal B component and Psi in the GLM-MHD system.
5143  ! 23/04/2013 Oliver Porth
5144  db(ixo^s) = wrp(ixo^s,mag(idir)) - wlp(ixo^s,mag(idir))
5145  dpsi(ixo^s) = wrp(ixo^s,psi_) - wlp(ixo^s,psi_)
5146 
5147  wlp(ixo^s,mag(idir)) = 0.5d0 * (wrp(ixo^s,mag(idir)) + wlp(ixo^s,mag(idir))) &
5148  - 0.5d0/cmax_global * dpsi(ixo^s)
5149  wlp(ixo^s,psi_) = 0.5d0 * (wrp(ixo^s,psi_) + wlp(ixo^s,psi_)) &
5150  - 0.5d0*cmax_global * db(ixo^s)
5151 
5152  wrp(ixo^s,mag(idir)) = wlp(ixo^s,mag(idir))
5153  wrp(ixo^s,psi_) = wlp(ixo^s,psi_)
5154 
5155  if(phys_total_energy) then
5156  wrc(ixo^s,e_c_)=wrc(ixo^s,e_c_)-half*wrc(ixo^s,mag(idir))**2
5157  wlc(ixo^s,e_c_)=wlc(ixo^s,e_c_)-half*wlc(ixo^s,mag(idir))**2
5158  end if
5159  wrc(ixo^s,mag(idir)) = wlp(ixo^s,mag(idir))
5160  wrc(ixo^s,psi_) = wlp(ixo^s,psi_)
5161  wlc(ixo^s,mag(idir)) = wlp(ixo^s,mag(idir))
5162  wlc(ixo^s,psi_) = wlp(ixo^s,psi_)
5163  ! modify total energy according to the change of magnetic field
5164  if(phys_total_energy) then
5165  wrc(ixo^s,e_c_)=wrc(ixo^s,e_c_)+half*wrc(ixo^s,mag(idir))**2
5166  wlc(ixo^s,e_c_)=wlc(ixo^s,e_c_)+half*wlc(ixo^s,mag(idir))**2
5167  end if
5168  end if
5169 
5170  if(associated(usr_set_wlr)) call usr_set_wlr(ixi^l,ixo^l,qt,wlc,wrc,wlp,wrp,s,idir)
5171 
5172  end subroutine twofl_modify_wlr
5173 
5174  subroutine twofl_boundary_adjust(igrid,psb)
5176  integer, intent(in) :: igrid
5177  type(state), target :: psb(max_blocks)
5178 
5179  integer :: iB, idims, iside, ixO^L, i^D
5180 
5181  block=>ps(igrid)
5182  ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
5183  do idims=1,ndim
5184  ! to avoid using as yet unknown corner info in more than 1D, we
5185  ! fill only interior mesh ranges of the ghost cell ranges at first,
5186  ! and progressively enlarge the ranges to include corners later
5187  do iside=1,2
5188  i^d=kr(^d,idims)*(2*iside-3);
5189  if (neighbor_type(i^d,igrid)/=1) cycle
5190  ib=(idims-1)*2+iside
5191  if(.not.boundary_divbfix(ib)) cycle
5192  if(any(typeboundary(:,ib)==bc_special)) then
5193  ! MF nonlinear force-free B field extrapolation and data driven
5194  ! require normal B of the first ghost cell layer to be untouched by
5195  ! fixdivB=0 process, set boundary_divbfix_skip(iB)=1 in par file
5196  select case (idims)
5197  {case (^d)
5198  if (iside==2) then
5199  ! maximal boundary
5200  ixomin^dd=ixghi^d+1-nghostcells+boundary_divbfix_skip(2*^d)^d%ixOmin^dd=ixglo^dd;
5201  ixomax^dd=ixghi^dd;
5202  else
5203  ! minimal boundary
5204  ixomin^dd=ixglo^dd;
5205  ixomax^dd=ixglo^d-1+nghostcells-boundary_divbfix_skip(2*^d-1)^d%ixOmax^dd=ixghi^dd;
5206  end if \}
5207  end select
5208  call fixdivb_boundary(ixg^ll,ixo^l,psb(igrid)%w,psb(igrid)%x,ib)
5209  end if
5210  end do
5211  end do
5212 
5213  end subroutine twofl_boundary_adjust
5214 
5215  subroutine fixdivb_boundary(ixG^L,ixO^L,w,x,iB)
5217 
5218  integer, intent(in) :: ixG^L,ixO^L,iB
5219  double precision, intent(inout) :: w(ixG^S,1:nw)
5220  double precision, intent(in) :: x(ixG^S,1:ndim)
5221 
5222  double precision :: dx1x2,dx1x3,dx2x1,dx2x3,dx3x1,dx3x2
5223  integer :: ix^D,ixF^L
5224 
5225  select case(ib)
5226  case(1)
5227  ! 2nd order CD for divB=0 to set normal B component better
5228  {^iftwod
5229  ixfmin1=ixomin1+1
5230  ixfmax1=ixomax1+1
5231  ixfmin2=ixomin2+1
5232  ixfmax2=ixomax2-1
5233  if(slab_uniform) then
5234  dx1x2=dxlevel(1)/dxlevel(2)
5235  do ix1=ixfmax1,ixfmin1,-1
5236  w(ix1-1,ixfmin2:ixfmax2,mag(1))=w(ix1+1,ixfmin2:ixfmax2,mag(1)) &
5237  +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
5238  w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
5239  enddo
5240  else
5241  do ix1=ixfmax1,ixfmin1,-1
5242  w(ix1-1,ixfmin2:ixfmax2,mag(1))=( (w(ix1+1,ixfmin2:ixfmax2,mag(1))+&
5243  w(ix1,ixfmin2:ixfmax2,mag(1)))*block%surfaceC(ix1,ixfmin2:ixfmax2,1)&
5244  +(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
5245  block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
5246  -(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
5247  block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
5248  /block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
5249  end do
5250  end if
5251  }
5252  {^ifthreed
5253  ixfmin1=ixomin1+1
5254  ixfmax1=ixomax1+1
5255  ixfmin2=ixomin2+1
5256  ixfmax2=ixomax2-1
5257  ixfmin3=ixomin3+1
5258  ixfmax3=ixomax3-1
5259  if(slab_uniform) then
5260  dx1x2=dxlevel(1)/dxlevel(2)
5261  dx1x3=dxlevel(1)/dxlevel(3)
5262  do ix1=ixfmax1,ixfmin1,-1
5263  w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
5264  w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
5265  +dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
5266  w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
5267  +dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
5268  w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
5269  end do
5270  else
5271  do ix1=ixfmax1,ixfmin1,-1
5272  w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
5273  ( (w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
5274  w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
5275  block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
5276  +(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
5277  w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
5278  block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
5279  -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
5280  w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
5281  block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
5282  +(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
5283  w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
5284  block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
5285  -(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
5286  w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
5287  block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
5288  /block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
5289  w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
5290  end do
5291  end if
5292  }
5293  case(2)
5294  {^iftwod
5295  ixfmin1=ixomin1-1
5296  ixfmax1=ixomax1-1
5297  ixfmin2=ixomin2+1
5298  ixfmax2=ixomax2-1
5299  if(slab_uniform) then
5300  dx1x2=dxlevel(1)/dxlevel(2)
5301  do ix1=ixfmin1,ixfmax1
5302  w(ix1+1,ixfmin2:ixfmax2,mag(1))=w(ix1-1,ixfmin2:ixfmax2,mag(1)) &
5303  -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))-&
5304  w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))
5305  enddo
5306  else
5307  do ix1=ixfmin1,ixfmax1
5308  w(ix1+1,ixfmin2:ixfmax2,mag(1))=( (w(ix1-1,ixfmin2:ixfmax2,mag(1))+&
5309  w(ix1,ixfmin2:ixfmax2,mag(1)))*block%surfaceC(ix1-1,ixfmin2:ixfmax2,1)&
5310  -(w(ix1,ixfmin2+1:ixfmax2+1,mag(2))+w(ix1,ixfmin2:ixfmax2,mag(2)))*&
5311  block%surfaceC(ix1,ixfmin2:ixfmax2,2)&
5312  +(w(ix1,ixfmin2:ixfmax2,mag(2))+w(ix1,ixfmin2-1:ixfmax2-1,mag(2)))*&
5313  block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,2) )&
5314  /block%surfaceC(ix1,ixfmin2:ixfmax2,1)-w(ix1,ixfmin2:ixfmax2,mag(1))
5315  end do
5316  end if
5317  }
5318  {^ifthreed
5319  ixfmin1=ixomin1-1
5320  ixfmax1=ixomax1-1
5321  ixfmin2=ixomin2+1
5322  ixfmax2=ixomax2-1
5323  ixfmin3=ixomin3+1
5324  ixfmax3=ixomax3-1
5325  if(slab_uniform) then
5326  dx1x2=dxlevel(1)/dxlevel(2)
5327  dx1x3=dxlevel(1)/dxlevel(3)
5328  do ix1=ixfmin1,ixfmax1
5329  w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
5330  w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)) &
5331  -dx1x2*(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))-&
5332  w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2))) &
5333  -dx1x3*(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))-&
5334  w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))
5335  end do
5336  else
5337  do ix1=ixfmin1,ixfmax1
5338  w(ix1+1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))=&
5339  ( (w(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))+&
5340  w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1)))*&
5341  block%surfaceC(ix1-1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)&
5342  -(w(ix1,ixfmin2+1:ixfmax2+1,ixfmin3:ixfmax3,mag(2))+&
5343  w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2)))*&
5344  block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,2)&
5345  +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(2))+&
5346  w(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,mag(2)))*&
5347  block%surfaceC(ix1,ixfmin2-1:ixfmax2-1,ixfmin3:ixfmax3,2)&
5348  -(w(ix1,ixfmin2:ixfmax2,ixfmin3+1:ixfmax3+1,mag(3))+&
5349  w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3)))*&
5350  block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,3)&
5351  +(w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(3))+&
5352  w(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,mag(3)))*&
5353  block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3-1:ixfmax3-1,3) )&
5354  /block%surfaceC(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,1)-&
5355  w(ix1,ixfmin2:ixfmax2,ixfmin3:ixfmax3,mag(1))
5356  end do
5357  end if
5358  }
5359  case(3)
5360  {^iftwod
5361  ixfmin1=ixomin1+1
5362  ixfmax1=ixomax1-1
5363  ixfmin2=ixomin2+1
5364  ixfmax2=ixomax2+1
5365  if(slab_uniform) then
5366  dx2x1=dxlevel(2)/dxlevel(1)
5367  do ix2=ixfmax2,ixfmin2,-1
5368  w(ixfmin1:ixfmax1,ix2-1,mag(2))=w(ixfmin1:ixfmax1,ix2+1,mag(2)) &
5369  +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
5370  w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
5371  enddo
5372  else
5373  do ix2=ixfmax2,ixfmin2,-1
5374  w(ixfmin1:ixfmax1,ix2-1,mag(2))=( (w(ixfmin1:ixfmax1,ix2+1,mag(2))+&
5375  w(ixfmin1:ixfmax1,ix2,mag(2)))*block%surfaceC(ixfmin1:ixfmax1,ix2,2)&
5376  +(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
5377  block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
5378  -(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
5379  block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
5380  /block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
5381  end do
5382  end if
5383  }
5384  {^ifthreed
5385  ixfmin1=ixomin1+1
5386  ixfmax1=ixomax1-1
5387  ixfmin3=ixomin3+1
5388  ixfmax3=ixomax3-1
5389  ixfmin2=ixomin2+1
5390  ixfmax2=ixomax2+1
5391  if(slab_uniform) then
5392  dx2x1=dxlevel(2)/dxlevel(1)
5393  dx2x3=dxlevel(2)/dxlevel(3)
5394  do ix2=ixfmax2,ixfmin2,-1
5395  w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
5396  ix2+1,ixfmin3:ixfmax3,mag(2)) &
5397  +dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
5398  w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
5399  +dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
5400  w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
5401  end do
5402  else
5403  do ix2=ixfmax2,ixfmin2,-1
5404  w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))=&
5405  ( (w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))+&
5406  w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
5407  block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)&
5408  +(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
5409  w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
5410  block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
5411  -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
5412  w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
5413  block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
5414  +(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
5415  w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
5416  block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
5417  -(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
5418  w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
5419  block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
5420  /block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)-&
5421  w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
5422  end do
5423  end if
5424  }
5425  case(4)
5426  {^iftwod
5427  ixfmin1=ixomin1+1
5428  ixfmax1=ixomax1-1
5429  ixfmin2=ixomin2-1
5430  ixfmax2=ixomax2-1
5431  if(slab_uniform) then
5432  dx2x1=dxlevel(2)/dxlevel(1)
5433  do ix2=ixfmin2,ixfmax2
5434  w(ixfmin1:ixfmax1,ix2+1,mag(2))=w(ixfmin1:ixfmax1,ix2-1,mag(2)) &
5435  -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))-&
5436  w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))
5437  end do
5438  else
5439  do ix2=ixfmin2,ixfmax2
5440  w(ixfmin1:ixfmax1,ix2+1,mag(2))=( (w(ixfmin1:ixfmax1,ix2-1,mag(2))+&
5441  w(ixfmin1:ixfmax1,ix2,mag(2)))*block%surfaceC(ixfmin1:ixfmax1,ix2-1,2)&
5442  -(w(ixfmin1+1:ixfmax1+1,ix2,mag(1))+w(ixfmin1:ixfmax1,ix2,mag(1)))*&
5443  block%surfaceC(ixfmin1:ixfmax1,ix2,1)&
5444  +(w(ixfmin1:ixfmax1,ix2,mag(1))+w(ixfmin1-1:ixfmax1-1,ix2,mag(1)))*&
5445  block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,1) )&
5446  /block%surfaceC(ixfmin1:ixfmax1,ix2,2)-w(ixfmin1:ixfmax1,ix2,mag(2))
5447  end do
5448  end if
5449  }
5450  {^ifthreed
5451  ixfmin1=ixomin1+1
5452  ixfmax1=ixomax1-1
5453  ixfmin3=ixomin3+1
5454  ixfmax3=ixomax3-1
5455  ixfmin2=ixomin2-1
5456  ixfmax2=ixomax2-1
5457  if(slab_uniform) then
5458  dx2x1=dxlevel(2)/dxlevel(1)
5459  dx2x3=dxlevel(2)/dxlevel(3)
5460  do ix2=ixfmin2,ixfmax2
5461  w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=w(ixfmin1:ixfmax1,&
5462  ix2-1,ixfmin3:ixfmax3,mag(2)) &
5463  -dx2x1*(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))-&
5464  w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1))) &
5465  -dx2x3*(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))-&
5466  w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))
5467  end do
5468  else
5469  do ix2=ixfmin2,ixfmax2
5470  w(ixfmin1:ixfmax1,ix2+1,ixfmin3:ixfmax3,mag(2))=&
5471  ( (w(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,mag(2))+&
5472  w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2)))*&
5473  block%surfaceC(ixfmin1:ixfmax1,ix2-1,ixfmin3:ixfmax3,2)&
5474  -(w(ixfmin1+1:ixfmax1+1,ix2,ixfmin3:ixfmax3,mag(1))+&
5475  w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1)))*&
5476  block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,1)&
5477  +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(1))+&
5478  w(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,mag(1)))*&
5479  block%surfaceC(ixfmin1-1:ixfmax1-1,ix2,ixfmin3:ixfmax3,1)&
5480  -(w(ixfmin1:ixfmax1,ix2,ixfmin3+1:ixfmax3+1,mag(3))+&
5481  w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3)))*&
5482  block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,3)&
5483  +(w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(3))+&
5484  w(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,mag(3)))*&
5485  block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3-1:ixfmax3-1,3) )&
5486  /block%surfaceC(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,2)-&
5487  w(ixfmin1:ixfmax1,ix2,ixfmin3:ixfmax3,mag(2))
5488  end do
5489  end if
5490  }
5491  {^ifthreed
5492  case(5)
5493  ixfmin1=ixomin1+1
5494  ixfmax1=ixomax1-1
5495  ixfmin2=ixomin2+1
5496  ixfmax2=ixomax2-1
5497  ixfmin3=ixomin3+1
5498  ixfmax3=ixomax3+1
5499  if(slab_uniform) then
5500  dx3x1=dxlevel(3)/dxlevel(1)
5501  dx3x2=dxlevel(3)/dxlevel(2)
5502  do ix3=ixfmax3,ixfmin3,-1
5503  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=w(ixfmin1:ixfmax1,&
5504  ixfmin2:ixfmax2,ix3+1,mag(3)) &
5505  +dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
5506  w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
5507  +dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
5508  w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
5509  end do
5510  else
5511  do ix3=ixfmax3,ixfmin3,-1
5512  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))=&
5513  ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))+&
5514  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
5515  block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)&
5516  +(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
5517  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
5518  block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
5519  -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
5520  w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
5521  block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
5522  +(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
5523  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
5524  block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
5525  -(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
5526  w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
5527  block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
5528  /block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)-&
5529  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
5530  end do
5531  end if
5532  case(6)
5533  ixfmin1=ixomin1+1
5534  ixfmax1=ixomax1-1
5535  ixfmin2=ixomin2+1
5536  ixfmax2=ixomax2-1
5537  ixfmin3=ixomin3-1
5538  ixfmax3=ixomax3-1
5539  if(slab_uniform) then
5540  dx3x1=dxlevel(3)/dxlevel(1)
5541  dx3x2=dxlevel(3)/dxlevel(2)
5542  do ix3=ixfmin3,ixfmax3
5543  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=w(ixfmin1:ixfmax1,&
5544  ixfmin2:ixfmax2,ix3-1,mag(3)) &
5545  -dx3x1*(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))-&
5546  w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1))) &
5547  -dx3x2*(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))-&
5548  w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))
5549  end do
5550  else
5551  do ix3=ixfmin3,ixfmax3
5552  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3+1,mag(3))=&
5553  ( (w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,mag(3))+&
5554  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3)))*&
5555  block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3-1,3)&
5556  -(w(ixfmin1+1:ixfmax1+1,ixfmin2:ixfmax2,ix3,mag(1))+&
5557  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1)))*&
5558  block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,1)&
5559  +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(1))+&
5560  w(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,mag(1)))*&
5561  block%surfaceC(ixfmin1-1:ixfmax1-1,ixfmin2:ixfmax2,ix3,1)&
5562  -(w(ixfmin1:ixfmax1,ixfmin2+1:ixfmax2+1,ix3,mag(2))+&
5563  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2)))*&
5564  block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,2)&
5565  +(w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(2))+&
5566  w(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,mag(2)))*&
5567  block%surfaceC(ixfmin1:ixfmax1,ixfmin2-1:ixfmax2-1,ix3,2) )&
5568  /block%surfaceC(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,3)-&
5569  w(ixfmin1:ixfmax1,ixfmin2:ixfmax2,ix3,mag(3))
5570  end do
5571  end if
5572  }
5573  case default
5574  call mpistop("Special boundary is not defined for this region")
5575  end select
5576 
5577  end subroutine fixdivb_boundary
5578 
5579  {^nooned
5580  subroutine twofl_clean_divb_multigrid(qdt, qt, active)
5581  use mod_forest
5584  use mod_geometry
5585 
5586  double precision, intent(in) :: qdt !< Current time step
5587  double precision, intent(in) :: qt !< Current time
5588  logical, intent(inout) :: active !< Output if the source is active
5589  integer :: iigrid, igrid, id
5590  integer :: n, nc, lvl, ix^l, ixc^l, idim
5591  type(tree_node), pointer :: pnode
5592  double precision :: tmp(ixg^t), grad(ixg^t, ndim)
5593  double precision :: res
5594  double precision, parameter :: max_residual = 1d-3
5595  double precision, parameter :: residual_reduction = 1d-10
5596  integer, parameter :: max_its = 50
5597  double precision :: residual_it(max_its), max_divb
5598 
5599  mg%operator_type = mg_laplacian
5600 
5601  ! Set boundary conditions
5602  do n = 1, 2*ndim
5603  idim = (n+1)/2
5604  select case (typeboundary(mag(idim), n))
5605  case (bc_symm)
5606  ! d/dx B = 0, take phi = 0
5607  mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
5608  mg%bc(n, mg_iphi)%bc_value = 0.0_dp
5609  case (bc_asymm)
5610  ! B = 0, so grad(phi) = 0
5611  mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
5612  mg%bc(n, mg_iphi)%bc_value = 0.0_dp
5613  case (bc_cont)
5614  mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
5615  mg%bc(n, mg_iphi)%bc_value = 0.0_dp
5616  case (bc_special)
5617  ! Assume Dirichlet boundary conditions, derivative zero
5618  mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
5619  mg%bc(n, mg_iphi)%bc_value = 0.0_dp
5620  case (bc_periodic)
5621  ! Nothing to do here
5622  case default
5623  print *, "divb_multigrid warning: unknown b.c.: ", &
5624  typeboundary(mag(idim), n)
5625  mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
5626  mg%bc(n, mg_iphi)%bc_value = 0.0_dp
5627  end select
5628  end do
5629 
5630  ix^l=ixm^ll^ladd1;
5631  max_divb = 0.0d0
5632 
5633  ! Store divergence of B as right-hand side
5634  do iigrid = 1, igridstail
5635  igrid = igrids(iigrid);
5636  pnode => igrid_to_node(igrid, mype)%node
5637  id = pnode%id
5638  lvl = mg%boxes(id)%lvl
5639  nc = mg%box_size_lvl(lvl)
5640 
5641  ! Geometry subroutines expect this to be set
5642  block => ps(igrid)
5643  ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
5644 
5645  call get_divb(ps(igrid)%w(ixg^t, 1:nw), ixg^ll, ixm^ll, tmp, &
5647  mg%boxes(id)%cc({1:nc}, mg_irhs) = tmp(ixm^t)
5648  max_divb = max(max_divb, maxval(abs(tmp(ixm^t))))
5649  end do
5650 
5651  ! Solve laplacian(phi) = divB
5652  if(stagger_grid) then
5653  call mpi_allreduce(mpi_in_place, max_divb, 1, mpi_double_precision, &
5654  mpi_max, icomm, ierrmpi)
5655 
5656  if (mype == 0) print *, "Performing multigrid divB cleaning"
5657  if (mype == 0) print *, "iteration vs residual"
5658  ! Solve laplacian(phi) = divB
5659  do n = 1, max_its
5660  call mg_fas_fmg(mg, n>1, max_res=residual_it(n))
5661  if (mype == 0) write(*, "(I4,E11.3)") n, residual_it(n)
5662  if (residual_it(n) < residual_reduction * max_divb) exit
5663  end do
5664  if (mype == 0 .and. n > max_its) then
5665  print *, "divb_multigrid warning: not fully converged"
5666  print *, "current amplitude of divb: ", residual_it(max_its)
5667  print *, "multigrid smallest grid: ", &
5668  mg%domain_size_lvl(:, mg%lowest_lvl)
5669  print *, "note: smallest grid ideally has <= 8 cells"
5670  print *, "multigrid dx/dy/dz ratio: ", mg%dr(:, 1)/mg%dr(1, 1)
5671  print *, "note: dx/dy/dz should be similar"
5672  end if
5673  else
5674  do n = 1, max_its
5675  call mg_fas_vcycle(mg, max_res=res)
5676  if (res < max_residual) exit
5677  end do
5678  if (res > max_residual) call mpistop("divb_multigrid: no convergence")
5679  end if
5680 
5681 
5682  ! Correct the magnetic field
5683  do iigrid = 1, igridstail
5684  igrid = igrids(iigrid);
5685  pnode => igrid_to_node(igrid, mype)%node
5686  id = pnode%id
5687 
5688  ! Geometry subroutines expect this to be set
5689  block => ps(igrid)
5690  ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
5691 
5692  ! Compute the gradient of phi
5693  tmp(ix^s) = mg%boxes(id)%cc({:,}, mg_iphi)
5694 
5695  if(stagger_grid) then
5696  do idim =1, ndim
5697  ixcmin^d=ixmlo^d-kr(idim,^d);
5698  ixcmax^d=ixmhi^d;
5699  call gradientx(tmp,ps(igrid)%x,ixg^ll,ixc^l,idim,grad(ixg^t,idim),.false.)
5700  ! Apply the correction B* = B - gradient(phi)
5701  ps(igrid)%ws(ixc^s,idim)=ps(igrid)%ws(ixc^s,idim)-grad(ixc^s,idim)
5702  end do
5703  ! store cell-center magnetic energy
5704  tmp(ixm^t) = sum(ps(igrid)%w(ixm^t, mag(1:ndim))**2, dim=ndim+1)
5705  ! change cell-center magnetic field
5706  call twofl_face_to_center(ixm^ll,ps(igrid))
5707  else
5708  do idim = 1, ndim
5709  call gradient(tmp,ixg^ll,ixm^ll,idim,grad(ixg^t, idim))
5710  end do
5711  ! store cell-center magnetic energy
5712  tmp(ixm^t) = sum(ps(igrid)%w(ixm^t, mag(1:ndim))**2, dim=ndim+1)
5713  ! Apply the correction B* = B - gradient(phi)
5714  ps(igrid)%w(ixm^t, mag(1:ndim)) = &
5715  ps(igrid)%w(ixm^t, mag(1:ndim)) - grad(ixm^t, :)
5716  end if
5717 
5718  if(phys_total_energy) then
5719  ! Determine magnetic energy difference
5720  tmp(ixm^t) = 0.5_dp * (sum(ps(igrid)%w(ixm^t, &
5721  mag(1:ndim))**2, dim=ndim+1) - tmp(ixm^t))
5722  ! Keep thermal pressure the same
5723  ps(igrid)%w(ixm^t, e_c_) = ps(igrid)%w(ixm^t, e_c_) + tmp(ixm^t)
5724  end if
5725  end do
5726 
5727  active = .true.
5728 
5729  end subroutine twofl_clean_divb_multigrid
5730  }
5731 
5732  subroutine twofl_update_faces(ixI^L,ixO^L,qt,qdt,wprim,fC,fE,sCT,s,vcts)
5734 
5735  integer, intent(in) :: ixI^L, ixO^L
5736  double precision, intent(in) :: qt,qdt
5737  ! cell-center primitive variables
5738  double precision, intent(in) :: wprim(ixI^S,1:nw)
5739  type(state) :: sCT, s
5740  type(ct_velocity) :: vcts
5741  double precision, intent(in) :: fC(ixI^S,1:nwflux,1:ndim)
5742  double precision, intent(inout) :: fE(ixI^S,7-2*ndim:3)
5743 
5744  select case(type_ct)
5745  case('average')
5746  call update_faces_average(ixi^l,ixo^l,qt,qdt,fc,fe,sct,s)
5747  case('uct_contact')
5748  call update_faces_contact(ixi^l,ixo^l,qt,qdt,wprim,fc,fe,sct,s,vcts)
5749  case('uct_hll')
5750  call update_faces_hll(ixi^l,ixo^l,qt,qdt,fe,sct,s,vcts)
5751  case default
5752  call mpistop('choose average, uct_contact,or uct_hll for type_ct!')
5753  end select
5754 
5755  end subroutine twofl_update_faces
5756 
5757  !> get electric field though averaging neighors to update faces in CT
5758  subroutine update_faces_average(ixI^L,ixO^L,qt,qdt,fC,fE,sCT,s)
5760  use mod_usr_methods
5761 
5762  integer, intent(in) :: ixI^L, ixO^L
5763  double precision, intent(in) :: qt, qdt
5764  type(state) :: sCT, s
5765  double precision, intent(in) :: fC(ixI^S,1:nwflux,1:ndim)
5766  double precision, intent(inout) :: fE(ixI^S,7-2*ndim:3)
5767 
5768  integer :: hxC^L,ixC^L,jxC^L,ixCm^L
5769  integer :: idim1,idim2,idir,iwdim1,iwdim2
5770  double precision :: circ(ixI^S,1:ndim)
5771  ! non-ideal electric field on cell edges
5772  double precision, dimension(ixI^S,7-2*ndim:3) :: E_resi
5773 
5774  associate(bfaces=>s%ws,x=>s%x)
5775 
5776  ! Calculate contribution to FEM of each edge,
5777  ! that is, estimate value of line integral of
5778  ! electric field in the positive idir direction.
5779  ixcmax^d=ixomax^d;
5780  ixcmin^d=ixomin^d-1;
5781 
5782  ! if there is resistivity, get eta J
5783  if(twofl_eta/=zero) call get_resistive_electric_field(ixi^l,ixo^l,sct,s,e_resi)
5784 
5785  fe=zero
5786 
5787  do idim1=1,ndim
5788  iwdim1 = mag(idim1)
5789  do idim2=1,ndim
5790  iwdim2 = mag(idim2)
5791  do idir=7-2*ndim,3! Direction of line integral
5792  ! Allow only even permutations
5793  if (lvc(idim1,idim2,idir)==1) then
5794  ! Assemble indices
5795  jxc^l=ixc^l+kr(idim1,^d);
5796  hxc^l=ixc^l+kr(idim2,^d);
5797  ! Interpolate to edges
5798  fe(ixc^s,idir)=quarter*(fc(ixc^s,iwdim1,idim2)+fc(jxc^s,iwdim1,idim2)&
5799  -fc(ixc^s,iwdim2,idim1)-fc(hxc^s,iwdim2,idim1))
5800 
5801  ! add resistive electric field at cell edges E=-vxB+eta J
5802  if(twofl_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+e_resi(ixc^s,idir)
5803  fe(ixc^s,idir)=qdt*s%dsC(ixc^s,idir)*fe(ixc^s,idir)
5804 
5805  if (.not.slab) then
5806  where(abs(x(ixc^s,r_)+half*dxlevel(r_))<1.0d-9)
5807  fe(ixc^s,idir)=zero
5808  end where
5809  end if
5810  end if
5811  end do
5812  end do
5813  end do
5814 
5815  ! allow user to change inductive electric field, especially for boundary driven applications
5816  if(associated(usr_set_electric_field)) &
5817  call usr_set_electric_field(ixi^l,ixo^l,qt,qdt,fe,sct)
5818 
5819  circ(ixi^s,1:ndim)=zero
5820 
5821  ! Calculate circulation on each face
5822 
5823  do idim1=1,ndim ! Coordinate perpendicular to face
5824  do idim2=1,ndim
5825  do idir=7-2*ndim,3 ! Direction of line integral
5826  ! Assemble indices
5827  hxc^l=ixc^l-kr(idim2,^d);
5828  ! Add line integrals in direction idir
5829  circ(ixc^s,idim1)=circ(ixc^s,idim1)&
5830  +lvc(idim1,idim2,idir)&
5831  *(fe(ixc^s,idir)&
5832  -fe(hxc^s,idir))
5833  end do
5834  end do
5835  end do
5836 
5837  ! Divide by the area of the face to get dB/dt
5838  do idim1=1,ndim
5839  ixcmax^d=ixomax^d;
5840  ixcmin^d=ixomin^d-kr(idim1,^d);
5841  where(s%surfaceC(ixc^s,idim1) > 1.0d-9*s%dvolume(ixc^s))
5842  circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
5843  elsewhere
5844  circ(ixc^s,idim1)=zero
5845  end where
5846  ! Time update
5847  bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
5848  end do
5849 
5850  end associate
5851 
5852  end subroutine update_faces_average
5853 
5854  !> update faces using UCT contact mode by Gardiner and Stone 2005 JCP 205, 509
5855  subroutine update_faces_contact(ixI^L,ixO^L,qt,qdt,wp,fC,fE,sCT,s,vcts)
5857  use mod_usr_methods
5858 
5859  integer, intent(in) :: ixI^L, ixO^L
5860  double precision, intent(in) :: qt, qdt
5861  ! cell-center primitive variables
5862  double precision, intent(in) :: wp(ixI^S,1:nw)
5863  type(state) :: sCT, s
5864  type(ct_velocity) :: vcts
5865  double precision, intent(in) :: fC(ixI^S,1:nwflux,1:ndim)
5866  double precision, intent(inout) :: fE(ixI^S,7-2*ndim:3)
5867 
5868  double precision :: circ(ixI^S,1:ndim)
5869  ! electric field at cell centers
5870  double precision :: ECC(ixI^S,7-2*ndim:3)
5871  ! gradient of E at left and right side of a cell face
5872  double precision :: EL(ixI^S),ER(ixI^S)
5873  ! gradient of E at left and right side of a cell corner
5874  double precision :: ELC(ixI^S),ERC(ixI^S)
5875  ! non-ideal electric field on cell edges
5876  double precision, dimension(ixI^S,7-2*ndim:3) :: E_resi, E_ambi
5877  ! total magnetic field at cell centers
5878  double precision :: Btot(ixI^S,1:ndim)
5879  integer :: hxC^L,ixC^L,jxC^L,ixA^L,ixB^L
5880  integer :: idim1,idim2,idir,iwdim1,iwdim2
5881 
5882  associate(bfaces=>s%ws,x=>s%x,w=>s%w,vnorm=>vcts%vnorm)
5883 
5884  if(b0field) then
5885  btot(ixi^s,1:ndim)=wp(ixi^s,mag(1:ndim))+block%B0(ixi^s,1:ndim,0)
5886  else
5887  btot(ixi^s,1:ndim)=wp(ixi^s,mag(1:ndim))
5888  end if
5889  ecc=0.d0
5890  ! Calculate electric field at cell centers
5891  do idim1=1,ndim; do idim2=1,ndim; do idir=7-2*ndim,3
5892  if(lvc(idim1,idim2,idir)==1)then
5893  ecc(ixi^s,idir)=ecc(ixi^s,idir)+btot(ixi^s,idim1)*wp(ixi^s,mom_c(idim2))
5894  else if(lvc(idim1,idim2,idir)==-1) then
5895  ecc(ixi^s,idir)=ecc(ixi^s,idir)-btot(ixi^s,idim1)*wp(ixi^s,mom_c(idim2))
5896  endif
5897  enddo; enddo; enddo
5898 
5899  ! if there is resistivity, get eta J
5900  if(twofl_eta/=zero) call get_resistive_electric_field(ixi^l,ixo^l,sct,s,e_resi)
5901  ! Calculate contribution to FEM of each edge,
5902  ! that is, estimate value of line integral of
5903  ! electric field in the positive idir direction.
5904  fe=zero
5905  ! evaluate electric field along cell edges according to equation (41)
5906  do idim1=1,ndim
5907  iwdim1 = mag(idim1)
5908  do idim2=1,ndim
5909  iwdim2 = mag(idim2)
5910  do idir=7-2*ndim,3 ! Direction of line integral
5911  ! Allow only even permutations
5912  if (lvc(idim1,idim2,idir)==1) then
5913  ixcmax^d=ixomax^d;
5914  ixcmin^d=ixomin^d+kr(idir,^d)-1;
5915  ! Assemble indices
5916  jxc^l=ixc^l+kr(idim1,^d);
5917  hxc^l=ixc^l+kr(idim2,^d);
5918  ! average cell-face electric field to cell edges
5919  fe(ixc^s,idir)=quarter*&
5920  (fc(ixc^s,iwdim1,idim2)+fc(jxc^s,iwdim1,idim2)&
5921  -fc(ixc^s,iwdim2,idim1)-fc(hxc^s,iwdim2,idim1))
5922 
5923  ! add slope in idim2 direction from equation (50)
5924  ixamin^d=ixcmin^d;
5925  ixamax^d=ixcmax^d+kr(idim1,^d);
5926  el(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(ixa^s,idir)
5927  hxc^l=ixa^l+kr(idim2,^d);
5928  er(ixa^s)=fc(ixa^s,iwdim1,idim2)-ecc(hxc^s,idir)
5929  where(vnorm(ixc^s,idim1)>0.d0)
5930  elc(ixc^s)=el(ixc^s)
5931  else where(vnorm(ixc^s,idim1)<0.d0)
5932  elc(ixc^s)=el(jxc^s)
5933  else where
5934  elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
5935  end where
5936  hxc^l=ixc^l+kr(idim2,^d);
5937  where(vnorm(hxc^s,idim1)>0.d0)
5938  erc(ixc^s)=er(ixc^s)
5939  else where(vnorm(hxc^s,idim1)<0.d0)
5940  erc(ixc^s)=er(jxc^s)
5941  else where
5942  erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
5943  end where
5944  fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
5945 
5946  ! add slope in idim1 direction from equation (50)
5947  jxc^l=ixc^l+kr(idim2,^d);
5948  ixamin^d=ixcmin^d;
5949  ixamax^d=ixcmax^d+kr(idim2,^d);
5950  el(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(ixa^s,idir)
5951  hxc^l=ixa^l+kr(idim1,^d);
5952  er(ixa^s)=-fc(ixa^s,iwdim2,idim1)-ecc(hxc^s,idir)
5953  where(vnorm(ixc^s,idim2)>0.d0)
5954  elc(ixc^s)=el(ixc^s)
5955  else where(vnorm(ixc^s,idim2)<0.d0)
5956  elc(ixc^s)=el(jxc^s)
5957  else where
5958  elc(ixc^s)=0.5d0*(el(ixc^s)+el(jxc^s))
5959  end where
5960  hxc^l=ixc^l+kr(idim1,^d);
5961  where(vnorm(hxc^s,idim2)>0.d0)
5962  erc(ixc^s)=er(ixc^s)
5963  else where(vnorm(hxc^s,idim2)<0.d0)
5964  erc(ixc^s)=er(jxc^s)
5965  else where
5966  erc(ixc^s)=0.5d0*(er(ixc^s)+er(jxc^s))
5967  end where
5968  fe(ixc^s,idir)=fe(ixc^s,idir)+0.25d0*(elc(ixc^s)+erc(ixc^s))
5969 
5970  ! add current component of electric field at cell edges E=-vxB+eta J
5971  if(twofl_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+e_resi(ixc^s,idir)
5972  ! times time step and edge length
5973  fe(ixc^s,idir)=fe(ixc^s,idir)*qdt*s%dsC(ixc^s,idir)
5974  if (.not.slab) then
5975  where(abs(x(ixc^s,r_)+half*dxlevel(r_))<1.0d-9)
5976  fe(ixc^s,idir)=zero
5977  end where
5978  end if
5979  end if
5980  end do
5981  end do
5982  end do
5983 
5984  ! allow user to change inductive electric field, especially for boundary driven applications
5985  if(associated(usr_set_electric_field)) &
5986  call usr_set_electric_field(ixi^l,ixo^l,qt,qdt,fe,sct)
5987 
5988  circ(ixi^s,1:ndim)=zero
5989 
5990  ! Calculate circulation on each face
5991  do idim1=1,ndim ! Coordinate perpendicular to face
5992  ixcmax^d=ixomax^d;
5993  ixcmin^d=ixomin^d-kr(idim1,^d);
5994  do idim2=1,ndim
5995  do idir=7-2*ndim,3 ! Direction of line integral
5996  ! Assemble indices
5997  hxc^l=ixc^l-kr(idim2,^d);
5998  ! Add line integrals in direction idir
5999  circ(ixc^s,idim1)=circ(ixc^s,idim1)&
6000  +lvc(idim1,idim2,idir)&
6001  *(fe(ixc^s,idir)&
6002  -fe(hxc^s,idir))
6003  end do
6004  end do
6005  ! Divide by the area of the face to get dB/dt
6006  ixcmax^d=ixomax^d;
6007  ixcmin^d=ixomin^d-kr(idim1,^d);
6008  where(s%surfaceC(ixc^s,idim1) > 1.0d-9*s%dvolume(ixc^s))
6009  circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
6010  elsewhere
6011  circ(ixc^s,idim1)=zero
6012  end where
6013  ! Time update cell-face magnetic field component
6014  bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
6015  end do
6016 
6017  end associate
6018 
6019  end subroutine update_faces_contact
6020 
6021  !> update faces
6022  subroutine update_faces_hll(ixI^L,ixO^L,qt,qdt,fE,sCT,s,vcts)
6025  use mod_usr_methods
6026 
6027  integer, intent(in) :: ixI^L, ixO^L
6028  double precision, intent(in) :: qt, qdt
6029  double precision, intent(inout) :: fE(ixI^S,7-2*ndim:3)
6030  type(state) :: sCT, s
6031  type(ct_velocity) :: vcts
6032 
6033  double precision :: vtilL(ixI^S,2)
6034  double precision :: vtilR(ixI^S,2)
6035  double precision :: bfacetot(ixI^S,ndim)
6036  double precision :: btilL(s%ixGs^S,ndim)
6037  double precision :: btilR(s%ixGs^S,ndim)
6038  double precision :: cp(ixI^S,2)
6039  double precision :: cm(ixI^S,2)
6040  double precision :: circ(ixI^S,1:ndim)
6041  ! non-ideal electric field on cell edges
6042  double precision, dimension(ixI^S,7-2*ndim:3) :: E_resi, E_ambi
6043  integer :: hxC^L,ixC^L,ixCp^L,jxC^L,ixCm^L
6044  integer :: idim1,idim2,idir
6045 
6046  associate(bfaces=>s%ws,bfacesct=>sct%ws,x=>s%x,vbarc=>vcts%vbarC,cbarmin=>vcts%cbarmin,&
6047  cbarmax=>vcts%cbarmax)
6048 
6049  ! Calculate contribution to FEM of each edge,
6050  ! that is, estimate value of line integral of
6051  ! electric field in the positive idir direction.
6052 
6053  ! Loop over components of electric field
6054 
6055  ! idir: electric field component we need to calculate
6056  ! idim1: directions in which we already performed the reconstruction
6057  ! idim2: directions in which we perform the reconstruction
6058 
6059  ! if there is resistivity, get eta J
6060  if(twofl_eta/=zero) call get_resistive_electric_field(ixi^l,ixo^l,sct,s,e_resi)
6061  fe=zero
6062 
6063  do idir=7-2*ndim,3
6064  ! Indices
6065  ! idir: electric field component
6066  ! idim1: one surface
6067  ! idim2: the other surface
6068  ! cyclic permutation: idim1,idim2,idir=1,2,3
6069  ! Velocity components on the surface
6070  ! follow cyclic premutations:
6071  ! Sx(1),Sx(2)=y,z ; Sy(1),Sy(2)=z,x ; Sz(1),Sz(2)=x,y
6072 
6073  ixcmax^d=ixomax^d;
6074  ixcmin^d=ixomin^d-1+kr(idir,^d);
6075 
6076  ! Set indices and directions
6077  idim1=mod(idir,3)+1
6078  idim2=mod(idir+1,3)+1
6079 
6080  jxc^l=ixc^l+kr(idim1,^d);
6081  ixcp^l=ixc^l+kr(idim2,^d);
6082 
6083  ! Reconstruct transverse transport velocities
6084  call reconstruct(ixi^l,ixc^l,idim2,vbarc(ixi^s,idim1,1),&
6085  vtill(ixi^s,2),vtilr(ixi^s,2))
6086 
6087  call reconstruct(ixi^l,ixc^l,idim1,vbarc(ixi^s,idim2,2),&
6088  vtill(ixi^s,1),vtilr(ixi^s,1))
6089 
6090  ! Reconstruct magnetic fields
6091  ! Eventhough the arrays are larger, reconstruct works with
6092  ! the limits ixG.
6093  if(b0field) then
6094  bfacetot(ixi^s,idim1)=bfacesct(ixi^s,idim1)+block%B0(ixi^s,idim1,idim1)
6095  bfacetot(ixi^s,idim2)=bfacesct(ixi^s,idim2)+block%B0(ixi^s,idim2,idim2)
6096  else
6097  bfacetot(ixi^s,idim1)=bfacesct(ixi^s,idim1)
6098  bfacetot(ixi^s,idim2)=bfacesct(ixi^s,idim2)
6099  end if
6100  call reconstruct(ixi^l,ixc^l,idim2,bfacetot(ixi^s,idim1),&
6101  btill(ixi^s,idim1),btilr(ixi^s,idim1))
6102 
6103  call reconstruct(ixi^l,ixc^l,idim1,bfacetot(ixi^s,idim2),&
6104  btill(ixi^s,idim2),btilr(ixi^s,idim2))
6105 
6106  ! Take the maximum characteristic
6107 
6108  cm(ixc^s,1)=max(cbarmin(ixcp^s,idim1),cbarmin(ixc^s,idim1))
6109  cp(ixc^s,1)=max(cbarmax(ixcp^s,idim1),cbarmax(ixc^s,idim1))
6110 
6111  cm(ixc^s,2)=max(cbarmin(jxc^s,idim2),cbarmin(ixc^s,idim2))
6112  cp(ixc^s,2)=max(cbarmax(jxc^s,idim2),cbarmax(ixc^s,idim2))
6113 
6114 
6115  ! Calculate eletric field
6116  fe(ixc^s,idir)=-(cp(ixc^s,1)*vtill(ixc^s,1)*btill(ixc^s,idim2) &
6117  + cm(ixc^s,1)*vtilr(ixc^s,1)*btilr(ixc^s,idim2) &
6118  - cp(ixc^s,1)*cm(ixc^s,1)*(btilr(ixc^s,idim2)-btill(ixc^s,idim2)))&
6119  /(cp(ixc^s,1)+cm(ixc^s,1)) &
6120  +(cp(ixc^s,2)*vtill(ixc^s,2)*btill(ixc^s,idim1) &
6121  + cm(ixc^s,2)*vtilr(ixc^s,2)*btilr(ixc^s,idim1) &
6122  - cp(ixc^s,2)*cm(ixc^s,2)*(btilr(ixc^s,idim1)-btill(ixc^s,idim1)))&
6123  /(cp(ixc^s,2)+cm(ixc^s,2))
6124 
6125  ! add current component of electric field at cell edges E=-vxB+eta J
6126  if(twofl_eta/=zero) fe(ixc^s,idir)=fe(ixc^s,idir)+e_resi(ixc^s,idir)
6127  fe(ixc^s,idir)=qdt*s%dsC(ixc^s,idir)*fe(ixc^s,idir)
6128 
6129  if (.not.slab) then
6130  where(abs(x(ixc^s,r_)+half*dxlevel(r_)).lt.1.0d-9)
6131  fe(ixc^s,idir)=zero
6132  end where
6133  end if
6134 
6135  end do
6136 
6137  ! allow user to change inductive electric field, especially for boundary driven applications
6138  if(associated(usr_set_electric_field)) &
6139  call usr_set_electric_field(ixi^l,ixo^l,qt,qdt,fe,sct)
6140 
6141  circ(ixi^s,1:ndim)=zero
6142 
6143  ! Calculate circulation on each face: interal(fE dot dl)
6144 
6145  do idim1=1,ndim ! Coordinate perpendicular to face
6146  ixcmax^d=ixomax^d;
6147  ixcmin^d=ixomin^d-kr(idim1,^d);
6148  do idim2=1,ndim
6149  do idir=7-2*ndim,3 ! Direction of line integral
6150  ! Assemble indices
6151  hxc^l=ixc^l-kr(idim2,^d);
6152  ! Add line integrals in direction idir
6153  circ(ixc^s,idim1)=circ(ixc^s,idim1)&
6154  +lvc(idim1,idim2,idir)&
6155  *(fe(ixc^s,idir)&
6156  -fe(hxc^s,idir))
6157  end do
6158  end do
6159  end do
6160 
6161  ! Divide by the area of the face to get dB/dt
6162  do idim1=1,ndim
6163  ixcmax^d=ixomax^d;
6164  ixcmin^d=ixomin^d-kr(idim1,^d);
6165  where(s%surfaceC(ixc^s,idim1) > 1.0d-9*s%dvolume(ixc^s))
6166  circ(ixc^s,idim1)=circ(ixc^s,idim1)/s%surfaceC(ixc^s,idim1)
6167  elsewhere
6168  circ(ixc^s,idim1)=zero
6169  end where
6170  ! Time update
6171  bfaces(ixc^s,idim1)=bfaces(ixc^s,idim1)-circ(ixc^s,idim1)
6172  end do
6173 
6174  end associate
6175  end subroutine update_faces_hll
6176 
6177  !> calculate eta J at cell edges
6178  subroutine get_resistive_electric_field(ixI^L,ixO^L,sCT,s,jce)
6180  use mod_usr_methods
6181  use mod_geometry
6182 
6183  integer, intent(in) :: ixI^L, ixO^L
6184  type(state), intent(in) :: sCT, s
6185  ! current on cell edges
6186  double precision :: jce(ixI^S,7-2*ndim:3)
6187 
6188  ! current on cell centers
6189  double precision :: jcc(ixI^S,7-2*ndir:3)
6190  ! location at cell faces
6191  double precision :: xs(ixGs^T,1:ndim)
6192  ! resistivity
6193  double precision :: eta(ixI^S)
6194  double precision :: gradi(ixGs^T)
6195  integer :: ix^D,ixC^L,ixA^L,ixB^L,idir,idirmin,idim1,idim2
6196 
6197  associate(x=>s%x,dx=>s%dx,w=>s%w,wct=>sct%w,wcts=>sct%ws)
6198  ! calculate current density at cell edges
6199  jce=0.d0
6200  do idim1=1,ndim
6201  do idim2=1,ndim
6202  do idir=7-2*ndim,3
6203  if (lvc(idim1,idim2,idir)==0) cycle
6204  ixcmax^d=ixomax^d;
6205  ixcmin^d=ixomin^d+kr(idir,^d)-1;
6206  ixbmax^d=ixcmax^d-kr(idir,^d)+1;
6207  ixbmin^d=ixcmin^d;
6208  ! current at transverse faces
6209  xs(ixb^s,:)=x(ixb^s,:)
6210  xs(ixb^s,idim2)=x(ixb^s,idim2)+half*dx(ixb^s,idim2)
6211  call gradientx(wcts(ixgs^t,idim2),xs,ixgs^ll,ixc^l,idim1,gradi,.true.)
6212  if (lvc(idim1,idim2,idir)==1) then
6213  jce(ixc^s,idir)=jce(ixc^s,idir)+gradi(ixc^s)
6214  else
6215  jce(ixc^s,idir)=jce(ixc^s,idir)-gradi(ixc^s)
6216  end if
6217  end do
6218  end do
6219  end do
6220  ! get resistivity
6221  if(twofl_eta>zero)then
6222  jce(ixi^s,:)=jce(ixi^s,:)*twofl_eta
6223  else
6224  ixa^l=ixo^l^ladd1;
6225  call get_current(wct,ixi^l,ixa^l,idirmin,jcc)
6226  call usr_special_resistivity(wct,ixi^l,ixa^l,idirmin,x,jcc,eta)
6227  ! calcuate eta on cell edges
6228  do idir=7-2*ndim,3
6229  ixcmax^d=ixomax^d;
6230  ixcmin^d=ixomin^d+kr(idir,^d)-1;
6231  jcc(ixc^s,idir)=0.d0
6232  {do ix^db=0,1\}
6233  if({ ix^d==1 .and. ^d==idir | .or.}) cycle
6234  ixamin^d=ixcmin^d+ix^d;
6235  ixamax^d=ixcmax^d+ix^d;
6236  jcc(ixc^s,idir)=jcc(ixc^s,idir)+eta(ixa^s)
6237  {end do\}
6238  jcc(ixc^s,idir)=jcc(ixc^s,idir)*0.25d0
6239  jce(ixc^s,idir)=jce(ixc^s,idir)*jcc(ixc^s,idir)
6240  enddo
6241  end if
6242 
6243  end associate
6244  end subroutine get_resistive_electric_field
6245 
6246  !> calculate cell-center values from face-center values
6247  subroutine twofl_face_to_center(ixO^L,s)
6249  ! Non-staggered interpolation range
6250  integer, intent(in) :: ixo^l
6251  type(state) :: s
6252 
6253  integer :: fxo^l, gxo^l, hxo^l, jxo^l, kxo^l, idim
6254 
6255  associate(w=>s%w, ws=>s%ws)
6256 
6257  ! calculate cell-center values from face-center values in 2nd order
6258  do idim=1,ndim
6259  ! Displace index to the left
6260  ! Even if ixI^L is the full size of the w arrays, this is ok
6261  ! because the staggered arrays have an additional place to the left.
6262  hxo^l=ixo^l-kr(idim,^d);
6263  ! Interpolate to cell barycentre using arithmetic average
6264  ! This might be done better later, to make the method less diffusive.
6265  w(ixo^s,mag(idim))=half/s%surface(ixo^s,idim)*&
6266  (ws(ixo^s,idim)*s%surfaceC(ixo^s,idim)&
6267  +ws(hxo^s,idim)*s%surfaceC(hxo^s,idim))
6268  end do
6269 
6270  ! calculate cell-center values from face-center values in 4th order
6271  !do idim=1,ndim
6272  ! gxO^L=ixO^L-2*kr(idim,^D);
6273  ! hxO^L=ixO^L-kr(idim,^D);
6274  ! jxO^L=ixO^L+kr(idim,^D);
6275 
6276  ! ! Interpolate to cell barycentre using fourth order central formula
6277  ! w(ixO^S,mag(idim))=(0.0625d0/s%surface(ixO^S,idim))*&
6278  ! ( -ws(gxO^S,idim)*s%surfaceC(gxO^S,idim) &
6279  ! +9.0d0*ws(hxO^S,idim)*s%surfaceC(hxO^S,idim) &
6280  ! +9.0d0*ws(ixO^S,idim)*s%surfaceC(ixO^S,idim) &
6281  ! -ws(jxO^S,idim)*s%surfaceC(jxO^S,idim) )
6282  !end do
6283 
6284  ! calculate cell-center values from face-center values in 6th order
6285  !do idim=1,ndim
6286  ! fxO^L=ixO^L-3*kr(idim,^D);
6287  ! gxO^L=ixO^L-2*kr(idim,^D);
6288  ! hxO^L=ixO^L-kr(idim,^D);
6289  ! jxO^L=ixO^L+kr(idim,^D);
6290  ! kxO^L=ixO^L+2*kr(idim,^D);
6291 
6292  ! ! Interpolate to cell barycentre using sixth order central formula
6293  ! w(ixO^S,mag(idim))=(0.00390625d0/s%surface(ixO^S,idim))* &
6294  ! ( +3.0d0*ws(fxO^S,idim)*s%surfaceC(fxO^S,idim) &
6295  ! -25.0d0*ws(gxO^S,idim)*s%surfaceC(gxO^S,idim) &
6296  ! +150.0d0*ws(hxO^S,idim)*s%surfaceC(hxO^S,idim) &
6297  ! +150.0d0*ws(ixO^S,idim)*s%surfaceC(ixO^S,idim) &
6298  ! -25.0d0*ws(jxO^S,idim)*s%surfaceC(jxO^S,idim) &
6299  ! +3.0d0*ws(kxO^S,idim)*s%surfaceC(kxO^S,idim) )
6300  !end do
6301 
6302  end associate
6303 
6304  end subroutine twofl_face_to_center
6305 
6306  !> calculate magnetic field from vector potential
6307  subroutine b_from_vector_potential(ixIs^L, ixI^L, ixO^L, ws, x)
6310 
6311  integer, intent(in) :: ixis^l, ixi^l, ixo^l
6312  double precision, intent(inout) :: ws(ixis^s,1:nws)
6313  double precision, intent(in) :: x(ixi^s,1:ndim)
6314 
6315  double precision :: adummy(ixis^s,1:3)
6316 
6317  call b_from_vector_potentiala(ixis^l, ixi^l, ixo^l, ws, x, adummy)
6318 
6319  end subroutine b_from_vector_potential
6320 
6321  subroutine hyperdiffusivity_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
6324  integer, intent(in) :: ixI^L, ixO^L
6325  double precision, intent(in) :: w(ixI^S,1:nw)
6326  double precision, intent(in) :: x(ixI^S,1:ndim)
6327  double precision, intent(in) :: dx^D
6328  double precision, intent(inout) :: dtnew
6329 
6330  double precision :: nu(ixI^S),tmp(ixI^S),rho(ixI^S),temp(ixI^S)
6331  double precision :: divv(ixI^S,1:ndim)
6332  double precision :: vel(ixI^S,1:ndir)
6333  double precision :: csound(ixI^S),csound_dim(ixI^S,1:ndim)
6334  double precision :: dxarr(ndim)
6335  double precision :: maxCoef
6336  integer :: ixOO^L, hxb^L, hx^L, ii, jj
6337 
6338 
6339  ^d&dxarr(^d)=dx^d;
6340  maxcoef = smalldouble
6341 
6342  ! charges
6343  call twofl_get_v_c(w,x,ixi^l,ixi^l,vel)
6344  call get_rhoc_tot(w,x,ixi^l,ixi^l,rho)
6345  call twofl_get_csound2_c_from_conserved(w,x,ixi^l,ixi^l,csound)
6346  csound(ixi^s) = sqrt(csound(ixi^s)) + sqrt(twofl_mag_en_all(w,ixi^l,ixi^l) /rho(ixi^s))
6347  csound(ixi^s) = csound(ixi^s) + sqrt(sum(vel(ixi^s,1:ndir)**2 ,dim=ndim+1))
6348  do ii=1,ndim
6349  call div_vel_coeff(ixi^l, ixoo^l, vel, ii, divv(ixi^s,ii))
6350  hxmin^d=iximin^d+1;
6351  hxmax^d=iximax^d-1;
6352  hxb^l=hx^l-kr(ii,^d);
6353  csound_dim(hx^s,ii) = (csound(hxb^s)+csound(hx^s))/2d0
6354  enddo
6355  call twofl_get_temp_c_pert_from_etot(w, x, ixi^l, ixi^l, temp)
6356  do ii=1,ndim
6357  !TODO the following is copied
6358  !rho_c
6359  call hyp_coeff(ixi^l, ixoo^l, w(ixi^s,rho_c_), ii, tmp(ixi^s))
6360  nu(ixo^s) = c_hyp(rho_c_) * csound_dim(ixo^s,ii) * dxlevel(ii) * tmp(ixo^s) + &
6361  c_shk(rho_c_) * (dxlevel(ii)**2) *divv(ixo^s,ii)
6362  maxcoef = max(maxcoef,maxval(nu(ixo^s)))
6363 
6364  !TH c
6365  call hyp_coeff(ixi^l, ixoo^l, temp(ixi^s), ii, tmp(ixi^s))
6366  nu(ixo^s) = c_hyp(e_c_) * csound_dim(ixo^s,ii) * dxlevel(ii) * tmp(ixo^s) + &
6367  c_shk(e_c_) * (dxlevel(ii)**2) *divv(ixo^s,ii)
6368  nu(ixo^s) = nu(ixo^s) * rho(ixo^s) * rc/(twofl_gamma-1d0)
6369  maxcoef = max(maxcoef,maxval(nu(ixo^s)))
6370 
6371  !visc c
6372  do jj=1,ndir
6373  call hyp_coeff(ixi^l, ixoo^l, vel(ixi^s,jj), ii, tmp(ixi^s))
6374  nu(ixo^s) = c_hyp(mom_c(jj)) * csound_dim(ixo^s,ii) * dxlevel(ii) * tmp(ixo^s) + &
6375  c_shk(mom_c(jj)) * (dxlevel(ii)**2) *divv(ixo^s,ii)
6376  nu(ixo^s) = nu(ixo^s) * rho(ixo^s)
6377  maxcoef = max(maxcoef,maxval(nu(ixo^s)))
6378  enddo
6379 
6380  ! Ohmic
6381  do jj=1,ndir
6382  if(ii .ne. jj) then
6383  call hyp_coeff(ixi^l, ixoo^l, w(ixi^s,mag(jj)), ii, tmp(ixi^s))
6384  nu(ixo^s) = c_hyp(mag(jj)) * csound_dim(ixo^s,ii) * dxlevel(ii) * tmp(ixo^s) + &
6385  c_shk(mag(jj)) * (dxlevel(ii)**2) *divv(ixo^s,ii)
6386  maxcoef = max(maxcoef,maxval(nu(ixo^s)))
6387  endif
6388  enddo
6389 
6390  enddo
6391 
6392  !TODO the following is copied, as charges, and as in add_source!
6393  ! neutrals
6394  call twofl_get_v_n(w,x,ixi^l,ixi^l,vel)
6395  call twofl_get_csound_n(w,x,ixi^l,ixi^l,csound)
6396  csound(ixi^s) = csound(ixi^s) + sqrt(sum(vel(ixi^s,1:ndir)**2 ,dim=ndim+1))
6397  do ii=1,ndim
6398  call div_vel_coeff(ixi^l, ixoo^l, vel, ii, divv(ixi^s,ii))
6399  hxmin^d=iximin^d+1;
6400  hxmax^d=iximax^d-1;
6401  hxb^l=hx^l-kr(ii,^d);
6402  csound_dim(hx^s,ii) = (csound(hxb^s)+csound(hx^s))/2d0
6403  enddo
6404  call get_rhon_tot(w,x,ixi^l,ixo^l,rho)
6405  call twofl_get_temp_n_pert_from_etot(w, x, ixi^l, ixi^l, temp)
6406  do ii=1,ndim
6407  !rho_n
6408  call hyp_coeff(ixi^l, ixoo^l, w(ixi^s,rho_n_), ii, tmp(ixi^s))
6409  nu(ixo^s) = c_hyp(rho_n_) * csound_dim(ixo^s,ii) * dxlevel(ii) * tmp(ixo^s) + &
6410  c_shk(rho_n_) * (dxlevel(ii)**2) *divv(ixoo^s,ii)
6411  maxcoef = max(maxcoef,maxval(nu(ixo^s)))
6412 
6413  !TH n
6414  call hyp_coeff(ixi^l, ixoo^l, temp(ixi^s), ii, tmp(ixi^s))
6415  nu(ixo^s) = c_hyp(e_n_) * csound_dim(ixo^s,ii) * dxlevel(ii) * tmp(ixo^s) + &
6416  c_shk(e_n_) * (dxlevel(ii)**2) *divv(ixo^s,ii)
6417  nu(ixo^s) = nu(ixo^s) * rho(ixo^s) * rn/(twofl_gamma-1d0)
6418  maxcoef = max(maxcoef,maxval(nu(ixo^s)))
6419 
6420  !visc n
6421  do jj=1,ndir
6422  call hyp_coeff(ixi^l, ixoo^l, vel(ixi^s,jj), ii, tmp(ixi^s))
6423  nu(ixo^s) = c_hyp(mom_n(jj)) * csound_dim(ixo^s,ii) * dxlevel(ii) * tmp(ixo^s) + &
6424  c_shk(mom_n(jj)) * (dxlevel(ii)**2) *divv(ixo^s,ii)
6425  nu(ixo^s) = nu(ixo^s) * rho(ixo^s)
6426  maxcoef = max(maxcoef,maxval(nu(ixo^s)))
6427  enddo
6428  enddo
6429 
6430  dtnew=min(dtdiffpar*minval(dxarr(1:ndim))**2/maxcoef,dtnew)
6431  end subroutine hyperdiffusivity_get_dt
6432 
6433  subroutine add_source_hyperdiffusive(qdt,ixI^L,ixO^L,w,wCT,x)
6436 
6437  integer, intent(in) :: ixI^L, ixO^L
6438  double precision, intent(in) :: qdt, x(ixI^S,1:ndim)
6439  double precision, intent(inout) :: w(ixI^S,1:nw)
6440  double precision, intent(in) :: wCT(ixI^S,1:nw)
6441 
6442  double precision :: divv(ixI^S,1:ndim)
6443  double precision :: vel(ixI^S,1:ndir)
6444  double precision :: csound(ixI^S),csound_dim(ixI^S,1:ndim)
6445  integer :: ii,ixOO^L,hxb^L,hx^L
6446  double precision :: rho(ixI^S)
6447 
6448  call twofl_get_v_c(wct,x,ixi^l,ixi^l,vel)
6449  call get_rhoc_tot(wct,x,ixi^l,ixi^l,rho)
6450  call twofl_get_csound2_c_from_conserved(wct,x,ixi^l,ixi^l,csound)
6451  csound(ixi^s) = sqrt(csound(ixi^s)) + sqrt(twofl_mag_en_all(wct,ixi^l,ixi^l) /rho(ixi^s))
6452  csound(ixi^s) = csound(ixi^s) + sqrt(sum(vel(ixi^s,1:ndir)**2 ,dim=ndim+1))
6453  do ii=1,ndim
6454  call div_vel_coeff(ixi^l, ixoo^l, vel, ii, divv(ixi^s,ii))
6455  hxmin^d=iximin^d+1;
6456  hxmax^d=iximax^d-1;
6457  hxb^l=hx^l-kr(ii,^d);
6458  csound_dim(hx^s,ii) = (csound(hxb^s)+csound(hx^s))/2d0
6459  enddo
6461  call add_viscosity_hyper_source(rho,mom_c(1), e_c_)
6462  call add_th_cond_c_hyper_source(rho)
6463  call add_ohmic_hyper_source()
6464 
6465  call twofl_get_v_n(wct,x,ixi^l,ixi^l,vel)
6466  call twofl_get_csound_n(wct,x,ixi^l,ixi^l,csound)
6467  csound(ixi^s) = csound(ixi^s) + sqrt(sum(vel(ixi^s,1:ndir)**2 ,dim=ndim+1))
6468  do ii=1,ndim
6469  call div_vel_coeff(ixi^l, ixoo^l, vel, ii, divv(ixi^s,ii))
6470  hxmin^d=iximin^d+1;
6471  hxmax^d=iximax^d-1;
6472  hxb^l=hx^l-kr(ii,^d);
6473  csound_dim(hx^s,ii) = (csound(hxb^s)+csound(hx^s))/2d0
6474  enddo
6476  call get_rhon_tot(wct,x,ixi^l,ixi^l,rho)
6477  call add_viscosity_hyper_source(rho,mom_n(1), e_n_)
6478  call add_th_cond_n_hyper_source(rho)
6479 
6480  contains
6481 
6482  subroutine add_density_hyper_source(index_rho)
6483  integer, intent(in) :: index_rho
6484 
6485  double precision :: nu(ixI^S), tmp(ixI^S)
6486 
6487  do ii=1,ndim
6488  call hyp_coeff(ixi^l, ixoo^l, wct(ixi^s,index_rho), ii, tmp(ixi^s))
6489  nu(ixoo^s) = c_hyp(index_rho) * csound_dim(ixoo^s,ii) * dxlevel(ii) * tmp(ixoo^s) + &
6490  c_shk(index_rho) * (dxlevel(ii)**2) *divv(ixoo^s,ii)
6491  !print*, "IXOO HYP ", ixOO^L, " IDIMM ", ii
6492  call second_same_deriv(ixi^l, ixoo^l, nu(ixi^s), wct(ixi^s,index_rho), ii, tmp)
6493 
6494  w(ixo^s,index_rho) = w(ixo^s,index_rho) + qdt * tmp(ixo^s)
6495  !print*, "RHO ", index_rho, maxval(abs(tmp(ixO^S)))
6496  enddo
6497  end subroutine add_density_hyper_source
6498 
6499  subroutine add_th_cond_c_hyper_source(var2)
6500  double precision, intent(in) :: var2(ixI^S)
6501  double precision :: nu(ixI^S), tmp(ixI^S), var(ixI^S)
6502  call twofl_get_temp_c_pert_from_etot(wct, x, ixi^l, ixi^l, var)
6503  do ii=1,ndim
6504  call hyp_coeff(ixi^l, ixoo^l, var(ixi^s), ii, tmp(ixi^s))
6505  nu(ixoo^s) = c_hyp(e_c_) * csound_dim(ixoo^s,ii) * dxlevel(ii) * tmp(ixoo^s) + &
6506  c_shk(e_c_) * (dxlevel(ii)**2) *divv(ixoo^s,ii)
6507  call second_same_deriv2(ixi^l, ixoo^l, nu(ixi^s), var2(ixi^s) ,var(ixi^s), ii, tmp)
6508  w(ixo^s,e_c_) = w(ixo^s,e_c_) + qdt * tmp(ixo^s) * rc/(twofl_gamma-1d0)
6509  !print*, "TH C ", maxval(abs(tmp(ixO^S)))
6510  enddo
6511  end subroutine add_th_cond_c_hyper_source
6512 
6513  subroutine add_th_cond_n_hyper_source(var2)
6514  double precision, intent(in) :: var2(ixI^S)
6515  double precision :: nu(ixI^S), tmp(ixI^S), var(ixI^S)
6516  call twofl_get_temp_n_pert_from_etot(wct, x, ixi^l, ixi^l, var)
6517  do ii=1,ndim
6518  call hyp_coeff(ixi^l, ixoo^l, var(ixi^s), ii, tmp(ixi^s))
6519  nu(ixoo^s) = c_hyp(e_n_) * csound_dim(ixoo^s,ii) * dxlevel(ii) * tmp(ixoo^s) + &
6520  c_shk(e_n_) * (dxlevel(ii)**2) *divv(ixoo^s,ii)
6521  call second_same_deriv2(ixi^l, ixoo^l, nu(ixi^s), var2(ixi^s) ,var(ixi^s), ii, tmp)
6522  w(ixo^s,e_n_) = w(ixo^s,e_n_) + qdt * tmp(ixo^s) * rn/(twofl_gamma-1d0)
6523  !print*, "TH N ", maxval(abs(tmp(ixO^S)))
6524  enddo
6525  end subroutine add_th_cond_n_hyper_source
6526 
6527  subroutine add_viscosity_hyper_source(rho,index_mom1, index_e)
6528  double precision, intent(in) :: rho(ixI^S)
6529  integer, intent(in) :: index_mom1, index_e
6530 
6531  double precision :: nu(ixI^S,1:ndir,1:ndim), tmp(ixI^S),tmp2(ixI^S)
6532  integer :: jj
6533 
6534  do jj=1,ndir
6535  do ii=1,ndim
6536  call hyp_coeff(ixi^l, ixoo^l, vel(ixi^s,jj), ii, tmp(ixi^s))
6537  nu(ixoo^s,jj,ii) = c_hyp(index_mom1-1+jj) * csound_dim(ixoo^s,ii) * dxlevel(ii) * tmp(ixoo^s) + &
6538  c_shk(index_mom1-1+jj) * (dxlevel(ii)**2) *divv(ixoo^s,ii)
6539  enddo
6540  enddo
6541 
6542  do jj=1,ndir
6543  do ii=1,ndim
6544  call second_same_deriv2(ixi^l, ixoo^l, nu(ixi^s,jj,ii), rho(ixi^s), vel(ixi^s,jj), ii, tmp)
6545  call second_same_deriv2(ixi^l, ixoo^l, nu(ixi^s,jj,ii), wct(ixi^s,index_mom1-1+jj), vel(ixi^s,jj), ii, tmp2)
6546  if(ii .eq. jj) then
6547  w(ixo^s,index_mom1-1+jj) = w(ixo^s,index_mom1-1+jj) + qdt * tmp(ixo^s)
6548  w(ixo^s,index_e) = w(ixo^s,index_e) + qdt * tmp2(ixo^s)
6549 
6550  else
6551  w(ixo^s,index_mom1-1+jj) = w(ixo^s,index_mom1-1+jj) + 0.5*qdt * tmp(ixo^s)
6552  w(ixo^s,index_e) = w(ixo^s,index_e) + 0.5*qdt * tmp2(ixo^s)
6553  call second_cross_deriv2(ixi^l, ixoo^l, nu(ixi^s,ii,jj), rho(ixi^s), vel(ixi^s,ii), jj, ii, tmp)
6554  w(ixo^s,index_mom1-1+jj) = w(ixo^s,index_mom1-1+jj) + 0.5*qdt * tmp(ixo^s)
6555  call second_cross_deriv2(ixi^l, ixoo^l, nu(ixi^s,jj,ii), wct(ixi^s,index_mom1-1+jj), vel(ixi^s,jj), ii, jj, tmp2)
6556  w(ixo^s,index_e) = w(ixo^s,index_e) + 0.5*qdt * tmp2(ixo^s)
6557  endif
6558 
6559  enddo
6560  enddo
6561 
6562  end subroutine add_viscosity_hyper_source
6563 
6564  subroutine add_ohmic_hyper_source()
6565  double precision :: nu(ixI^S,1:ndir,1:ndim), tmp(ixI^S)
6566  integer :: jj
6567 
6568  do jj=1,ndir
6569  do ii=1,ndim
6570  if(ii .ne. jj) then
6571  call hyp_coeff(ixi^l, ixoo^l, wct(ixi^s,mag(jj)), ii, tmp(ixi^s))
6572  nu(ixoo^s,jj,ii) = c_hyp(mag(jj)) * csound_dim(ixoo^s,ii) * dxlevel(ii) * tmp(ixoo^s) + &
6573  c_shk(mag(jj)) * (dxlevel(ii)**2) *divv(ixoo^s,ii)
6574  endif
6575  enddo
6576  enddo
6577 
6578  do jj=1,ndir
6579  do ii=1,ndim
6580  if(ii .ne. jj) then
6581  !mag field
6582  call second_same_deriv(ixi^l, ixoo^l, nu(ixi^s,jj,ii), wct(ixi^s,mag(jj)), ii, tmp)
6583  w(ixo^s,mag(jj)) = w(ixo^s,mag(jj)) + qdt * tmp(ixo^s)
6584  call second_cross_deriv(ixi^l, ixoo^l, nu(ixi^s,ii,jj), wct(ixi^s,mag(ii)), jj, ii, tmp)
6585  w(ixo^s,mag(jj)) = w(ixo^s,mag(jj)) + qdt * tmp(ixo^s)
6586  !in the total energy
6587  call second_same_deriv(ixi^l, ixoo^l, nu(ixi^s,jj,ii), wct(ixi^s,mag(jj)), ii, tmp)
6588  w(ixo^s,e_c_) = w(ixo^s,e_c_) + qdt * tmp(ixo^s)
6589  call second_cross_deriv2(ixi^l, ixoo^l, nu(ixi^s,ii,jj), wct(ixi^s,mag(jj)), wct(ixi^s,mag(ii)), jj, ii, tmp)
6590  w(ixo^s,e_c_) = w(ixo^s,e_c_) + qdt * tmp(ixo^s)
6591  endif
6592 
6593  enddo
6594  enddo
6595 
6596  end subroutine add_ohmic_hyper_source
6597 
6598  end subroutine add_source_hyperdiffusive
6599 
6600  function dump_hyperdiffusivity_coef_x(ixI^L,ixO^L, w, x, nwc) result(wnew)
6603  integer, intent(in) :: ixI^L, ixO^L, nwc
6604  double precision, intent(in) :: w(ixI^S, 1:nw)
6605  double precision, intent(in) :: x(ixI^S,1:ndim)
6606  double precision :: wnew(ixO^S, 1:nwc)
6607 
6608  if(nw .ne. nwc) call mpistop("nw != nwc")
6609  wnew(ixo^s,1:nw) = dump_hyperdiffusivity_coef_dim(ixi^l,ixo^l, w, x, 1)
6610 
6611  end function dump_hyperdiffusivity_coef_x
6612 
6613  function dump_hyperdiffusivity_coef_y(ixI^L,ixO^L, w, x, nwc) result(wnew)
6616  integer, intent(in) :: ixi^l, ixo^l, nwc
6617  double precision, intent(in) :: w(ixi^s, 1:nw)
6618  double precision, intent(in) :: x(ixi^s,1:ndim)
6619  double precision :: wnew(ixo^s, 1:nwc)
6620 
6621  if(nw .ne. nwc) call mpistop("nw != nwc")
6622  wnew(ixo^s,1:nw) = dump_hyperdiffusivity_coef_dim(ixi^l,ixo^l, w, x, 2)
6623 
6624  end function dump_hyperdiffusivity_coef_y
6625 
6626  function dump_hyperdiffusivity_coef_z(ixI^L,ixO^L, w, x, nwc) result(wnew)
6629  integer, intent(in) :: ixi^l, ixo^l, nwc
6630  double precision, intent(in) :: w(ixi^s, 1:nw)
6631  double precision, intent(in) :: x(ixi^s,1:ndim)
6632  double precision :: wnew(ixo^s, 1:nwc)
6633 
6634  if(nw .ne. nwc) call mpistop("nw != nwc")
6635  wnew(ixo^s,1:nw) = dump_hyperdiffusivity_coef_dim(ixi^l,ixo^l, w, x, 3)
6636 
6637  end function dump_hyperdiffusivity_coef_z
6638 
6639  function dump_hyperdiffusivity_coef_dim(ixI^L,ixOP^L, w, x, ii) result(wnew)
6642  integer, intent(in) :: ixi^l, ixop^l, ii
6643  double precision, intent(in) :: w(ixi^s, 1:nw)
6644  double precision, intent(in) :: x(ixi^s,1:ndim)
6645  double precision :: wnew(ixop^s, 1:nw)
6646 
6647  double precision :: nu(ixi^s),tmp(ixi^s),rho(ixi^s),temp(ixi^s)
6648  double precision :: divv(ixi^s)
6649  double precision :: vel(ixi^s,1:ndir)
6650  double precision :: csound(ixi^s),csound_dim(ixi^s)
6651  double precision :: dxarr(ndim)
6652  integer :: ixoo^l, hxb^l, hx^l, jj, ixo^l
6653 
6654  ! this is done because of save_physical_boundary = true
6655  ixomin^d=max(ixopmin^d,iximin^d+3);
6656  ixomax^d=min(ixopmax^d,iximax^d-3);
6657 
6658  wnew(ixop^s,1:nw) = 0d0
6659 
6660  ! charges
6661  call twofl_get_temp_c_pert_from_etot(w, x, ixi^l, ixi^l, temp)
6662  call twofl_get_v_c(w,x,ixi^l,ixi^l,vel)
6663  call get_rhoc_tot(w,x,ixi^l,ixi^l,rho)
6664  call twofl_get_csound2_c_from_conserved(w,x,ixi^l,ixi^l,csound)
6665  csound(ixi^s) = sqrt(csound(ixi^s)) + sqrt(twofl_mag_en_all(w,ixi^l,ixi^l) /rho(ixi^s))
6666  csound(ixi^s) = csound(ixi^s) + sqrt(sum(vel(ixi^s,1:ndir)**2 ,dim=ndim+1))
6667  !for dim
6668  call div_vel_coeff(ixi^l, ixoo^l, vel, ii, divv(ixi^s))
6669  hxmin^d=iximin^d+1;
6670  hxmax^d=iximax^d-1;
6671  hxb^l=hx^l-kr(ii,^d);
6672  csound_dim(hx^s) = (csound(hxb^s)+csound(hx^s))/2d0
6673 
6674  !TODO the following is copied
6675  !rho_c
6676  call hyp_coeff(ixi^l, ixoo^l, w(ixi^s,rho_c_), ii, tmp(ixi^s))
6677  nu(ixo^s) = c_hyp(rho_c_) * csound_dim(ixo^s) * dxlevel(ii) * tmp(ixo^s) + &
6678  c_shk(rho_c_) * (dxlevel(ii)**2) *divv(ixo^s)
6679 
6680  wnew(ixo^s,rho_c_) = nu(ixo^s)
6681 
6682  !TH c
6683  call hyp_coeff(ixi^l, ixoo^l, temp(ixi^s), ii, tmp(ixi^s))
6684  nu(ixo^s) = c_hyp(e_c_) * csound_dim(ixo^s) * dxlevel(ii) * tmp(ixo^s) + &
6685  c_shk(e_c_) * (dxlevel(ii)**2) *divv(ixo^s)
6686  nu(ixo^s) = nu(ixo^s) * rho(ixo^s) * rc/(twofl_gamma-1d0)
6687  wnew(ixo^s,e_c_) = nu(ixo^s)
6688 
6689  !visc c
6690  do jj=1,ndir
6691  call hyp_coeff(ixi^l, ixoo^l, vel(ixi^s,jj), ii, tmp(ixi^s))
6692  nu(ixo^s) = c_hyp(mom_c(jj)) * csound_dim(ixo^s) * dxlevel(ii) * tmp(ixo^s) + &
6693  c_shk(mom_c(jj)) * (dxlevel(ii)**2) *divv(ixo^s)
6694  nu(ixo^s) = nu(ixo^s) * rho(ixo^s)
6695  wnew(ixo^s,mom_c(jj)) = nu(ixo^s)
6696  enddo
6697 
6698  ! Ohmic
6699  do jj=1,ndir
6700  if(ii .ne. jj) then
6701  call hyp_coeff(ixi^l, ixoo^l, w(ixi^s,mag(jj)), ii, tmp(ixi^s))
6702  nu(ixo^s) = c_hyp(mag(jj)) * csound_dim(ixo^s) * dxlevel(ii) * tmp(ixo^s) + &
6703  c_shk(mag(jj)) * (dxlevel(ii)**2) *divv(ixo^s)
6704  wnew(ixo^s,mag(jj)) = nu(ixo^s)
6705  endif
6706  enddo
6707 
6708  !end for dim
6709 
6710  ! neutrals
6711  call get_rhon_tot(w,x,ixi^l,ixo^l,rho)
6712  call twofl_get_temp_n_pert_from_etot(w, x, ixi^l, ixi^l, temp)
6713  call twofl_get_v_n(w,x,ixi^l,ixi^l,vel)
6714  call twofl_get_csound_n(w,x,ixi^l,ixi^l,csound)
6715  csound(ixi^s) = csound(ixi^s) + sqrt(sum(vel(ixi^s,1:ndir)**2 ,dim=ndim+1))
6716  !for dim
6717  call div_vel_coeff(ixi^l, ixoo^l, vel, ii, divv(ixi^s))
6718  hxb^l=ixoo^l-kr(ii,^d);
6719  csound_dim(ixoo^s) = (csound(hxb^s)+csound(ixoo^s))/2d0
6720  !rho_n
6721  call hyp_coeff(ixi^l, ixoo^l, w(ixi^s,rho_n_), ii, tmp(ixi^s))
6722  nu(ixo^s) = c_hyp(rho_n_) * csound_dim(ixo^s) * dxlevel(ii) * tmp(ixo^s) + &
6723  c_shk(rho_n_) * (dxlevel(ii)**2) *divv(ixoo^s)
6724  wnew(ixo^s,rho_n_) = nu(ixo^s)
6725 
6726  !TH n
6727  call hyp_coeff(ixi^l, ixoo^l, temp(ixi^s), ii, tmp(ixi^s))
6728  nu(ixo^s) = c_hyp(e_n_) * csound_dim(ixo^s) * dxlevel(ii) * tmp(ixo^s) + &
6729  c_shk(e_n_) * (dxlevel(ii)**2) *divv(ixo^s)
6730  nu(ixo^s) = nu(ixo^s) * rho(ixo^s) * rn/(twofl_gamma-1d0)
6731  wnew(ixo^s,e_n_) = nu(ixo^s)
6732 
6733  !visc n
6734  do jj=1,ndir
6735  call hyp_coeff(ixi^l, ixoo^l, vel(ixi^s,jj), ii, tmp(ixi^s))
6736  nu(ixo^s) = c_hyp(mom_n(jj)) * csound_dim(ixo^s) * dxlevel(ii) * tmp(ixo^s) + &
6737  c_shk(mom_n(jj)) * (dxlevel(ii)**2) *divv(ixo^s)
6738  nu(ixo^s) = nu(ixo^s) * rho(ixo^s)
6739  wnew(ixo^s,mom_n(jj)) = nu(ixo^s)
6740  enddo
6741  !end for dim
6742 
6743  end function dump_hyperdiffusivity_coef_dim
6744 
6745  function dump_coll_terms(ixI^L,ixO^L, w, x, nwc) result(wnew)
6747  integer, intent(in) :: ixi^l,ixo^l, nwc
6748  double precision, intent(in) :: w(ixi^s, 1:nw)
6749  double precision, intent(in) :: x(ixi^s,1:ndim)
6750  double precision :: wnew(ixo^s, 1:nwc)
6751  double precision :: tmp(ixi^s),tmp2(ixi^s)
6752 
6753  call get_alpha_coll(ixi^l, ixo^l, w, x, tmp(ixi^s))
6754  wnew(ixo^s,1)= tmp(ixo^s)
6755  call get_gamma_ion_rec(ixi^l, ixo^l, w, x, tmp(ixi^s), tmp2(ixi^s))
6756  wnew(ixo^s,2)= tmp(ixo^s)
6757  wnew(ixo^s,3)= tmp2(ixo^s)
6758 
6759  end function dump_coll_terms
6760 
6761  subroutine get_gamma_ion_rec(ixI^L, ixO^L, w, x, gamma_rec, gamma_ion)
6763 
6764  integer, intent(in) :: ixi^l, ixo^l
6765  double precision, intent(in) :: w(ixi^s,1:nw)
6766  double precision, intent(in) :: x(ixi^s,1:ndim)
6767  double precision, intent(out) :: gamma_rec(ixi^s),gamma_ion(ixi^s)
6768  ! calculations are done in S.I. units
6769  double precision, parameter :: a = 2.91e-14, & !m3/s
6770  k = 0.39, &
6771  xx = 0.232, &
6772  eion = 13.6 ! eV
6773  double precision, parameter :: echarge=1.6022d-19 !C
6774  double precision :: rho(ixi^s), tmp(ixi^s)
6775 
6776  call twofl_get_pthermal_c(w,x,ixi^l,ixo^l,tmp)
6777  call get_rhoc_tot(w,x,ixi^l,ixo^l,rho)
6778  tmp(ixo^s) = tmp(ixo^s)/(rc * rho(ixo^s))
6779 
6780  !transform to SI units
6781  tmp(ixo^s) = tmp(ixo^s) * unit_temperature * kb_si/echarge !* BK/ECHARGE means K to eV
6782  !number electrons rho_c = n_e * MH, in normalized units MH=1 and n = rho
6783  rho(ixo^s) = rho(ixo^s) * unit_numberdensity
6784  if(.not. si_unit) then
6785  !1/cm^3 = 1e9/m^3
6786  rho(ixo^s) = rho(ixo^s) * 1d9
6787  endif
6788  gamma_rec(ixo^s) = rho(ixo^s) /sqrt(tmp(ixo^s)) * 2.6e-19
6789  gamma_ion(ixo^s) = ((rho(ixo^s) * a) /(xx + eion/tmp(ixo^s))) * ((eion/tmp(ixo^s))**k) * exp(-eion/tmp(ixo^s))
6790  ! see Voronov table: valid for temp min = 1eV(approx 11605 K), Temp max = 20KeV
6791  !to normalized
6792  gamma_rec(ixo^s) = gamma_rec(ixo^s) * unit_time
6793  gamma_ion(ixo^s) = gamma_ion(ixo^s) * unit_time
6794 
6795  end subroutine get_gamma_ion_rec
6796 
6797  subroutine get_alpha_coll(ixI^L, ixO^L, w, x, alpha)
6799  integer, intent(in) :: ixI^L, ixO^L
6800  double precision, intent(in) :: w(ixI^S,1:nw)
6801  double precision, intent(in) :: x(ixI^S,1:ndim)
6802  double precision, intent(out) :: alpha(ixI^S)
6803  if(twofl_alpha_coll_constant) then
6804  alpha(ixo^s) = twofl_alpha_coll
6805  else
6806  call get_alpha_coll_plasma(ixi^l, ixo^l, w, x, alpha)
6807  endif
6808  end subroutine get_alpha_coll
6809 
6810  subroutine get_alpha_coll_plasma(ixI^L, ixO^L, w, x, alpha)
6812  integer, intent(in) :: ixi^l, ixo^l
6813  double precision, intent(in) :: w(ixi^s,1:nw)
6814  double precision, intent(in) :: x(ixi^s,1:ndim)
6815  double precision, intent(out) :: alpha(ixi^s)
6816  double precision :: pe(ixi^s),rho(ixi^s), tmp(ixi^s), tmp2(ixi^s)
6817 
6818  double precision :: sigma_in = 1e-19 ! m^2
6819  ! make calculation in SI physical units
6820 
6821  call twofl_get_pthermal_c(w,x,ixi^l,ixo^l,pe)
6822  call get_rhoc_tot(w,x,ixi^l,ixo^l,rho)
6823  tmp(ixo^s) = pe(ixo^s)/(rc * rho(ixo^s))
6824  call twofl_get_pthermal_n(w,x,ixi^l,ixo^l,pe)
6825  call get_rhon_tot(w,x,ixi^l,ixo^l,rho)
6826  tmp2(ixo^s) = pe(ixo^s)/(rn * rho(ixo^s))
6827  alpha(ixo^s) = (2d0/(mp_si**(3d0/2) * sqrt(dpi))*sqrt(0.5*(tmp(ixo^s)+tmp2(ixo^s))*unit_temperature*kb_si) * sigma_in)*unit_time * unit_density
6828  if(.not. si_unit) then
6829  alpha(ixo^s) = alpha(ixo^s) * 1d3 ! this comes from unit_density: g/cm^3 = 1e-3 kg/m^3
6830  endif
6831 
6832  end subroutine get_alpha_coll_plasma
6833 
6834  subroutine calc_mult_factor1(ixI^L, ixO^L, step_dt, JJ, res)
6835  integer, intent(in) :: ixI^L, ixO^L
6836  double precision, intent(in) :: step_dt
6837  double precision, intent(in) :: JJ(ixI^S)
6838  double precision, intent(out) :: res(ixI^S)
6839 
6840  res(ixo^s) = step_dt/(1d0 + step_dt * jj(ixo^s))
6841 
6842  end subroutine calc_mult_factor1
6843 
6844  subroutine calc_mult_factor2(ixI^L, ixO^L, step_dt, JJ, res)
6845  integer, intent(in) :: ixI^L, ixO^L
6846  double precision, intent(in) :: step_dt
6847  double precision, intent(in) :: JJ(ixI^S)
6848  double precision, intent(out) :: res(ixI^S)
6849 
6850  res(ixo^s) = (1d0 - exp(-step_dt * jj(ixo^s)))/jj(ixo^s)
6851 
6852  end subroutine calc_mult_factor2
6853 
6854  subroutine advance_implicit_grid(ixI^L, ixO^L, w, wout, x, dtfactor,qdt)
6856  integer, intent(in) :: ixI^L, ixO^L
6857  double precision, intent(in) :: qdt
6858  double precision, intent(in) :: dtfactor
6859  double precision, intent(in) :: w(ixI^S,1:nw)
6860  double precision, intent(in) :: x(ixI^S,1:ndim)
6861  double precision, intent(out) :: wout(ixI^S,1:nw)
6862 
6863  integer :: idir
6864  double precision :: tmp(ixI^S),tmp1(ixI^S),tmp2(ixI^S),tmp3(ixI^S),tmp4(ixI^S),tmp5(ixI^S)
6865  double precision :: v_c(ixI^S,ndir), v_n(ixI^S,ndir)
6866  double precision :: rhon(ixI^S), rhoc(ixI^S), alpha(ixI^S)
6867  double precision, allocatable :: gamma_rec(:^D&), gamma_ion(:^D&)
6868 
6869  !TODO latest changes sets already wout to w in implicit update (see where psb=psa)
6870  ! commment out setting mag and density when they are not modified here
6871 
6872  ! copy vars at the indices which are not updated here: mag. field
6873  wout(ixo^s,mag(:)) = w(ixo^s,mag(:))
6874 
6875  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
6876  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
6877  !update density
6878  if(twofl_coll_inc_ionrec) then
6879  allocate(gamma_ion(ixi^s), gamma_rec(ixi^s))
6880  call get_gamma_ion_rec(ixi^l, ixo^l, w, x, gamma_rec, gamma_ion)
6881  tmp2(ixo^s) = gamma_rec(ixo^s) + gamma_ion(ixo^s)
6882  call calc_mult_factor(ixi^l, ixo^l, dtfactor * qdt, tmp2, tmp3)
6883 
6884  if(.not. twofl_equi_ionrec) then
6885  tmp(ixo^s) = (-gamma_ion(ixo^s) * rhon(ixo^s) + &
6886  gamma_rec(ixo^s) * rhoc(ixo^s))
6887  else
6888  ! equilibrium density does not evolve through ion/rec
6889  tmp(ixo^s) = (-gamma_ion(ixo^s) * w(ixo^s,rho_n_) + &
6890  gamma_rec(ixo^s) * w(ixo^s,rho_c_))
6891  endif
6892  wout(ixo^s,rho_n_) = w(ixo^s,rho_n_) + tmp(ixo^s) * tmp3(ixo^s)
6893  wout(ixo^s,rho_c_) = w(ixo^s,rho_c_) - tmp(ixo^s) * tmp3(ixo^s)
6894  else
6895  wout(ixo^s,rho_n_) = w(ixo^s,rho_n_)
6896  wout(ixo^s,rho_c_) = w(ixo^s,rho_c_)
6897  endif
6898 
6899  call get_alpha_coll(ixi^l, ixo^l, w, x, alpha)
6900 
6901  !-J11 + J12 for momentum and kinetic energy
6902  tmp2(ixo^s) = alpha(ixo^s) * (rhon(ixo^s) + rhoc(ixo^s))
6903  if(twofl_coll_inc_ionrec) then
6904  tmp2(ixo^s) = tmp2(ixo^s) + gamma_ion(ixo^s) + gamma_rec(ixo^s)
6905  endif
6906  call calc_mult_factor(ixi^l, ixo^l, dtfactor * qdt, tmp2, tmp3)
6907 
6908  ! momentum update
6909  do idir=1,ndir
6910 
6911  tmp(ixo^s) = alpha(ixo^s)* (-rhoc(ixo^s) * w(ixo^s,mom_n(idir)) + rhon(ixo^s) * w(ixo^s,mom_c(idir)))
6912  if(twofl_coll_inc_ionrec) then
6913  tmp(ixo^s) = tmp(ixo^s) - gamma_ion(ixo^s) * w(ixo^s,mom_n(idir)) + gamma_rec(ixo^s) * w(ixo^s,mom_c(idir))
6914  endif
6915 
6916  wout(ixo^s,mom_n(idir)) = w(ixo^s,mom_n(idir)) + tmp(ixo^s) * tmp3(ixo^s)
6917  wout(ixo^s,mom_c(idir)) = w(ixo^s,mom_c(idir)) - tmp(ixo^s) * tmp3(ixo^s)
6918  enddo
6919 
6920  ! energy update
6921 
6922  ! kinetic energy update
6923  if(.not. phys_internal_e) then
6924  ! E_tot includes kinetic energy
6925  tmp1(ixo^s) = twofl_kin_en_n(w,ixi^l,ixo^l)
6926  tmp2(ixo^s) = twofl_kin_en_c(w,ixi^l,ixo^l)
6927  tmp4(ixo^s) = w(ixo^s,e_n_) - tmp1(ixo^s) !E_tot - E_kin
6928  tmp5(ixo^s) = w(ixo^s,e_c_) - tmp2(ixo^s)
6929  if(phys_total_energy) then
6930  tmp5(ixo^s) = tmp5(ixo^s) - twofl_mag_en(w,ixi^l,ixo^l)
6931  endif
6932 
6933  !!implicit update
6934  tmp(ixo^s) = alpha(ixo^s)*(-rhoc(ixo^s) * tmp1(ixo^s) + rhon(ixo^s) * tmp2(ixo^s))
6935  if(twofl_coll_inc_ionrec) then
6936  tmp(ixo^s) = tmp(ixo^s) - gamma_ion(ixo^s) * tmp1(ixo^s) + gamma_rec(ixo^s) * tmp2(ixo^s)
6937  endif
6938 
6939  wout(ixo^s,e_n_) = w(ixo^s,e_n_) + tmp(ixo^s) * tmp3(ixo^s)
6940  wout(ixo^s,e_c_) = w(ixo^s,e_c_) - tmp(ixo^s) * tmp3(ixo^s)
6941 
6942  else
6943  tmp4(ixo^s) = w(ixo^s,e_n_)
6944  tmp5(ixo^s) = w(ixo^s,e_c_)
6945  ! calculate velocities, using the already updated variables
6946  call twofl_get_v_n(wout,x,ixi^l,ixo^l,v_n)
6947  call twofl_get_v_c(wout,x,ixi^l,ixo^l,v_c)
6948  tmp1(ixo^s) = alpha(ixo^s) * rhoc(ixo^s) * rhon(ixo^s)
6949  tmp2(ixo^s) = tmp1(ixo^s)
6950  if(twofl_coll_inc_ionrec) then
6951  tmp1(ixo^s) = tmp1(ixo^s) + rhoc(ixo^s) * gamma_rec(ixo^s)
6952  tmp2(ixo^s) = tmp2(ixo^s) + rhon(ixo^s) * gamma_ion(ixo^s)
6953  endif
6954 
6955  tmp(ixo^s) = 0.5d0 * sum((v_c(ixo^s,1:ndir) - v_n(ixo^s,1:ndir))**2, dim=ndim+1) &
6956  * dtfactor * qdt
6957  wout(ixo^s,e_n_) = w(ixo^s,e_n_) + tmp(ixo^s)*tmp1(ixo^s)
6958  wout(ixo^s,e_c_) = w(ixo^s,e_c_) + tmp(ixo^s)*tmp2(ixo^s)
6959  endif
6960 
6961  !update internal energy
6962  if(twofl_coll_inc_te) then
6963  if(.not. twofl_equi_thermal) then
6964  if(has_equi_pe_n0) then
6965  tmp4(ixo^s) = tmp4(ixo^s) + block%equi_vars(ixo^s,equi_pe_n0_,0)*inv_gamma_1
6966  endif
6967  if(has_equi_pe_c0) then
6968  tmp5(ixo^s) = tmp5(ixo^s) + block%equi_vars(ixo^s,equi_pe_c0_,0)*inv_gamma_1
6969  endif
6970  endif
6971 
6972  tmp(ixo^s) = alpha(ixo^s) *(-rhoc(ixo^s)/rn * tmp4(ixo^s) + rhon(ixo^s)/rc * tmp5(ixo^s))
6973  tmp2(ixo^s) = alpha(ixo^s) * (rhon(ixo^s)/rc + rhoc(ixo^s)/rn)
6974  if(twofl_coll_inc_ionrec) then
6975  tmp2(ixo^s) = tmp2(ixo^s) + gamma_rec(ixo^s)/rc + gamma_ion(ixo^s)/rn
6976  tmp(ixo^s) = tmp(ixo^s) - gamma_ion(ixo^s)/rn * tmp4(ixo^s) + gamma_rec(ixo^s)/rc * tmp5(ixo^s)
6977  endif
6978 
6979  call calc_mult_factor(ixi^l, ixo^l, dtfactor * qdt, tmp2, tmp3)
6980 
6981  wout(ixo^s,e_n_) = wout(ixo^s,e_n_)+tmp(ixo^s)*tmp3(ixo^s)
6982  wout(ixo^s,e_c_) = wout(ixo^s,e_c_)-tmp(ixo^s)*tmp3(ixo^s)
6983  endif
6984  if(twofl_coll_inc_ionrec) then
6985  deallocate(gamma_ion, gamma_rec)
6986  endif
6987  end subroutine advance_implicit_grid
6988 
6989  !> Implicit solve of psb=psa+dtfactor*dt*F_im(psb)
6990  subroutine twofl_implicit_coll_terms_update(dtfactor,qdt,qtC,psb,psa)
6993 
6994  type(state), target :: psa(max_blocks)
6995  type(state), target :: psb(max_blocks)
6996  double precision, intent(in) :: qdt
6997  double precision, intent(in) :: qtC
6998  double precision, intent(in) :: dtfactor
6999 
7000  integer :: iigrid, igrid
7001  !print*, "IMPL call ", it
7002 
7003  call getbc(global_time,0.d0,psa,1,nw)
7004  !$OMP PARALLEL DO PRIVATE(igrid)
7005  do iigrid=1,igridstail; igrid=igrids(iigrid);
7006  ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
7007  block=>psa(igrid)
7008  call advance_implicit_grid(ixg^ll, ixg^ll, psa(igrid)%w, psb(igrid)%w, psa(igrid)%x, dtfactor,qdt)
7009  end do
7010  !$OMP END PARALLEL DO
7011 
7012  end subroutine twofl_implicit_coll_terms_update
7013 
7014  !> inplace update of psa==>F_im(psa)
7015  subroutine twofl_evaluate_implicit(qtC,psa)
7017  type(state), target :: psa(max_blocks)
7018  double precision, intent(in) :: qtC
7019 
7020  integer :: iigrid, igrid, level
7021 
7022  !$OMP PARALLEL DO PRIVATE(igrid)
7023  do iigrid=1,igridstail; igrid=igrids(iigrid);
7024  ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
7025  block=>psa(igrid)
7026  call coll_terms(ixg^ll,ixm^ll,psa(igrid)%w,psa(igrid)%x)
7027  end do
7028  !$OMP END PARALLEL DO
7029 
7030  end subroutine twofl_evaluate_implicit
7031 
7032  subroutine coll_terms(ixI^L,ixO^L,w,x)
7034  integer, intent(in) :: ixI^L, ixO^L
7035  double precision, intent(inout) :: w(ixI^S, 1:nw)
7036  double precision, intent(in) :: x(ixI^S,1:ndim)
7037 
7038  integer :: idir
7039  double precision :: tmp(ixI^S),tmp1(ixI^S),tmp2(ixI^S),tmp3(ixI^S),tmp4(ixI^S),tmp5(ixI^S)
7040  !double precision :: v_c(ixI^S,ndir), v_n(ixI^S,ndir)
7041  double precision, allocatable :: v_c(:^D&,:), v_n(:^D&,:)
7042  double precision :: rhon(ixI^S), rhoc(ixI^S), alpha(ixI^S)
7043  double precision, allocatable :: gamma_rec(:^D&), gamma_ion(:^D&)
7044 
7045 
7046  ! get velocity before overwrite density
7047  call get_rhon_tot(w,x,ixi^l,ixo^l,rhon)
7048  call get_rhoc_tot(w,x,ixi^l,ixo^l,rhoc)
7049  if(phys_internal_e) then
7050  ! get velocity before overwrite momentum
7051  allocate(v_n(ixi^s,ndir), v_c(ixi^s,ndir))
7052  call twofl_get_v_n(w,x,ixi^l,ixo^l,v_n)
7053  call twofl_get_v_c(w,x,ixi^l,ixo^l,v_c)
7054  else
7055  ! get ke before overwrite density and momentum
7056  tmp1(ixo^s) = twofl_kin_en_n(w,ixi^l,ixo^l)
7057  tmp2(ixo^s) = twofl_kin_en_c(w,ixi^l,ixo^l)
7058  endif
7059 
7060  !update density
7061  if(twofl_coll_inc_ionrec) then
7062  allocate(gamma_ion(ixi^s), gamma_rec(ixi^s))
7063  call get_gamma_ion_rec(ixi^l, ixo^l, w, x, gamma_rec, gamma_ion)
7064 
7065  if(.not. twofl_equi_ionrec) then
7066  tmp(ixo^s) = -gamma_ion(ixo^s) * rhon(ixo^s) + &
7067  gamma_rec(ixo^s) * rhoc(ixo^s)
7068  else
7069  ! equilibrium density does not evolve through ion/rec
7070  tmp(ixo^s) = -gamma_ion(ixo^s) * w(ixo^s,rho_n_) + &
7071  gamma_rec(ixo^s) * w(ixo^s,rho_c_)
7072  endif
7073  w(ixo^s,rho_n_) = tmp(ixo^s)
7074  w(ixo^s,rho_c_) = -tmp(ixo^s)
7075  else
7076  w(ixo^s,rho_n_) = 0d0
7077  w(ixo^s,rho_c_) = 0d0
7078 
7079  endif
7080 
7081  call get_alpha_coll(ixi^l, ixo^l, w, x, alpha)
7082 
7083  ! momentum update
7084  do idir=1,ndir
7085 
7086  tmp(ixo^s) = alpha(ixo^s)* (-rhoc(ixo^s) * w(ixo^s,mom_n(idir)) + rhon(ixo^s) * w(ixo^s,mom_c(idir)))
7087  if(twofl_coll_inc_ionrec) then
7088  tmp(ixo^s) = tmp(ixo^s) - gamma_ion(ixo^s) * w(ixo^s,mom_n(idir)) + gamma_rec(ixo^s) * w(ixo^s,mom_c(idir))
7089  endif
7090 
7091  w(ixo^s,mom_n(idir)) = tmp(ixo^s)
7092  w(ixo^s,mom_c(idir)) = -tmp(ixo^s)
7093  enddo
7094 
7095  ! energy update
7096 
7097  ! kinetic energy update
7098  if(.not. phys_internal_e) then
7099  ! E_tot includes kinetic energy
7100  tmp4(ixo^s) = w(ixo^s,e_n_) - tmp1(ixo^s) !E_tot - E_kin
7101  tmp5(ixo^s) = w(ixo^s,e_c_) - tmp2(ixo^s)
7102  if(phys_total_energy) then
7103  tmp5(ixo^s) = tmp5(ixo^s) - twofl_mag_en(w,ixi^l,ixo^l)
7104  endif
7105  ! tmp4 = eint_n, tmp5 = eint_c
7106  ! tmp1 = ke_n, tmp2 = ke_c
7107  tmp(ixo^s) = alpha(ixo^s)*(-rhoc(ixo^s) * tmp1(ixo^s) + rhon(ixo^s) * tmp2(ixo^s))
7108  if(twofl_coll_inc_ionrec) then
7109  tmp(ixo^s) = tmp(ixo^s) - gamma_ion(ixo^s) * tmp1(ixo^s) + gamma_rec(ixo^s) * tmp2(ixo^s)
7110  endif
7111 
7112  w(ixo^s,e_n_) = tmp(ixo^s)
7113  w(ixo^s,e_c_) = -tmp(ixo^s)
7114 
7115  else
7116  tmp4(ixo^s) = w(ixo^s,e_n_)
7117  tmp5(ixo^s) = w(ixo^s,e_c_)
7118  tmp1(ixo^s) = alpha(ixo^s) * rhoc(ixo^s) * rhon(ixo^s)
7119  tmp2(ixo^s) = tmp1(ixo^s)
7120  if(twofl_coll_inc_ionrec) then
7121  tmp1(ixo^s) = tmp1(ixo^s) + rhoc(ixo^s) * gamma_rec(ixo^s)
7122  tmp2(ixo^s) = tmp2(ixo^s) + rhon(ixo^s) * gamma_ion(ixo^s)
7123  endif
7124 
7125  tmp(ixo^s) = 0.5d0 * sum((v_c(ixo^s,1:ndir) - v_n(ixo^s,1:ndir))**2, dim=ndim+1)
7126  w(ixo^s,e_n_) = tmp(ixo^s)*tmp1(ixo^s)
7127  w(ixo^s,e_c_) = tmp(ixo^s)*tmp2(ixo^s)
7128  endif
7129 
7130  !update internal energy
7131  if(twofl_coll_inc_te) then
7132  if(.not. twofl_equi_thermal) then
7133  if(has_equi_pe_n0) then
7134  tmp4(ixo^s) = tmp4(ixo^s) + block%equi_vars(ixo^s,equi_pe_n0_,0)*inv_gamma_1
7135  endif
7136  if(has_equi_pe_c0) then
7137  tmp5(ixo^s) = tmp5(ixo^s) + block%equi_vars(ixo^s,equi_pe_c0_,0)*inv_gamma_1
7138  endif
7139  endif
7140 
7141  tmp(ixo^s) = alpha(ixo^s) *(-rhoc(ixo^s)/rn * tmp4(ixo^s) + rhon(ixo^s)/rc * tmp5(ixo^s))
7142  if(twofl_coll_inc_ionrec) then
7143  tmp(ixo^s) = tmp(ixo^s) - gamma_ion(ixo^s)/rn * tmp4(ixo^s) + gamma_rec(ixo^s)/rc * tmp5(ixo^s)
7144  endif
7145 
7146  w(ixo^s,e_n_) = w(ixo^s,e_n_)+tmp(ixo^s)
7147  w(ixo^s,e_c_) = w(ixo^s,e_c_)-tmp(ixo^s)
7148  endif
7149  if(twofl_coll_inc_ionrec) then
7150  deallocate(gamma_ion, gamma_rec)
7151  endif
7152  if(phys_internal_e) then
7153  deallocate(v_n, v_c)
7154  endif
7155  !set contribution to mag field
7156  w(ixo^s,mag(1:ndir)) = 0d0
7157 
7158  end subroutine coll_terms
7159 
7160  subroutine twofl_explicit_coll_terms_update(qdt,ixI^L,ixO^L,w,wCT,x)
7162 
7163  integer, intent(in) :: ixI^L, ixO^L
7164  double precision, intent(in) :: qdt, x(ixI^S,1:ndim)
7165  double precision, intent(inout) :: w(ixI^S,1:nw)
7166  double precision, intent(in) :: wCT(ixI^S,1:nw)
7167 
7168  integer :: idir
7169  double precision :: tmp(ixI^S),tmp1(ixI^S),tmp2(ixI^S),tmp3(ixI^S),tmp4(ixI^S),tmp5(ixI^S)
7170  double precision :: v_c(ixI^S,ndir), v_n(ixI^S,ndir)
7171  double precision :: rhon(ixI^S), rhoc(ixI^S), alpha(ixI^S)
7172  double precision, allocatable :: gamma_rec(:^D&), gamma_ion(:^D&)
7173 
7174  call get_rhon_tot(wct,x,ixi^l,ixo^l,rhon)
7175  call get_rhoc_tot(wct,x,ixi^l,ixo^l,rhoc)
7176  !update density
7177  if(twofl_coll_inc_ionrec) then
7178  allocate(gamma_ion(ixi^s), gamma_rec(ixi^s))
7179  call get_gamma_ion_rec(ixi^l, ixo^l, wct, x, gamma_rec, gamma_ion)
7180 
7181  if(.not. twofl_equi_ionrec) then
7182  tmp(ixo^s) = qdt *(-gamma_ion(ixo^s) * rhon(ixo^s) + &
7183  gamma_rec(ixo^s) * rhoc(ixo^s))
7184  else
7185  tmp(ixo^s) = qdt * (-gamma_ion(ixo^s) * wct(ixo^s,rho_n_) + &
7186  gamma_rec(ixo^s) * wct(ixo^s,rho_c_))
7187  endif
7188  w(ixo^s,rho_n_) = w(ixo^s,rho_n_) + tmp(ixo^s)
7189  w(ixo^s,rho_c_) = w(ixo^s,rho_c_) - tmp(ixo^s)
7190  endif
7191 
7192  call get_alpha_coll(ixi^l, ixo^l, wct, x, alpha)
7193 
7194  ! momentum update
7195  do idir=1,ndir
7196 
7197  tmp(ixo^s) = alpha(ixo^s)* (-rhoc(ixo^s) * wct(ixo^s,mom_n(idir)) + rhon(ixo^s) * wct(ixo^s,mom_c(idir)))
7198  if(twofl_coll_inc_ionrec) then
7199  tmp(ixo^s) = tmp(ixo^s) - gamma_ion(ixo^s) * wct(ixo^s,mom_n(idir)) + gamma_rec(ixo^s) * wct(ixo^s,mom_c(idir))
7200  endif
7201  tmp(ixo^s) =tmp(ixo^s) * qdt
7202 
7203  w(ixo^s,mom_n(idir)) = w(ixo^s,mom_n(idir)) + tmp(ixo^s)
7204  w(ixo^s,mom_c(idir)) = w(ixo^s,mom_c(idir)) - tmp(ixo^s)
7205  enddo
7206 
7207  ! energy update
7208 
7209  ! kinetic energy update
7210  if(.not. phys_internal_e) then
7211  ! E_tot includes kinetic energy
7212  tmp1(ixo^s) = twofl_kin_en_n(wct,ixi^l,ixo^l)
7213  tmp2(ixo^s) = twofl_kin_en_c(wct,ixi^l,ixo^l)
7214  tmp4(ixo^s) = wct(ixo^s,e_n_) - tmp1(ixo^s) !E_tot - E_kin
7215  tmp5(ixo^s) = wct(ixo^s,e_c_) - tmp2(ixo^s)
7216  if(phys_total_energy) then
7217  tmp5(ixo^s) = tmp5(ixo^s) - twofl_mag_en(wct,ixi^l,ixo^l)
7218  endif
7219 
7220  tmp(ixo^s) = alpha(ixo^s)*(-rhoc(ixo^s) * tmp1(ixo^s) + rhon(ixo^s) * tmp2(ixo^s))
7221  if(twofl_coll_inc_ionrec) then
7222  tmp(ixo^s) = tmp(ixo^s) - gamma_ion(ixo^s) * tmp1(ixo^s) + gamma_rec(ixo^s) * tmp2(ixo^s)
7223  endif
7224  tmp(ixo^s) =tmp(ixo^s) * qdt
7225 
7226  w(ixo^s,e_n_) = w(ixo^s,e_n_) + tmp(ixo^s)
7227  w(ixo^s,e_c_) = w(ixo^s,e_c_) - tmp(ixo^s)
7228 
7229  else
7230  tmp4(ixo^s) = w(ixo^s,e_n_)
7231  tmp5(ixo^s) = w(ixo^s,e_c_)
7232  call twofl_get_v_n(wct,x,ixi^l,ixo^l,v_n)
7233  call twofl_get_v_c(wct,x,ixi^l,ixo^l,v_c)
7234  tmp1(ixo^s) = alpha(ixo^s) * rhoc(ixo^s) * rhon(ixo^s)
7235  tmp2(ixo^s) = tmp1(ixo^s)
7236  if(twofl_coll_inc_ionrec) then
7237  tmp1(ixo^s) = tmp1(ixo^s) + rhoc(ixo^s) * gamma_rec(ixo^s)
7238  tmp2(ixo^s) = tmp2(ixo^s) + rhon(ixo^s) * gamma_ion(ixo^s)
7239  endif
7240 
7241  tmp(ixo^s) = 0.5d0 * sum((v_c(ixo^s,1:ndir) - v_n(ixo^s,1:ndir))**2, dim=ndim+1) * qdt
7242  w(ixo^s,e_n_) = w(ixo^s,e_n_) + tmp(ixo^s)*tmp1(ixo^s)
7243  w(ixo^s,e_c_) = w(ixo^s,e_c_) + tmp(ixo^s)*tmp2(ixo^s)
7244  endif
7245 
7246  !update internal energy
7247  if(twofl_coll_inc_te) then
7248  if(.not. twofl_equi_thermal) then
7249  if(has_equi_pe_n0) then
7250  tmp4(ixo^s) = tmp4(ixo^s) + block%equi_vars(ixo^s,equi_pe_n0_,0)*inv_gamma_1
7251  endif
7252  if(has_equi_pe_c0) then
7253  tmp5(ixo^s) = tmp5(ixo^s) + block%equi_vars(ixo^s,equi_pe_c0_,0)*inv_gamma_1
7254  endif
7255  endif
7256 
7257  tmp(ixo^s) = alpha(ixo^s) *(-rhoc(ixo^s)/rn * tmp4(ixo^s) + rhon(ixo^s)/rc * tmp5(ixo^s))
7258  if(twofl_coll_inc_ionrec) then
7259  tmp(ixo^s) = tmp(ixo^s) - gamma_ion(ixo^s)/rn * tmp4(ixo^s) + gamma_rec(ixo^s)/rc * tmp5(ixo^s)
7260  endif
7261 
7262  tmp(ixo^s) =tmp(ixo^s) * qdt
7263 
7264  w(ixo^s,e_n_) = w(ixo^s,e_n_)+tmp(ixo^s)
7265  w(ixo^s,e_c_) = w(ixo^s,e_c_)-tmp(ixo^s)
7266  endif
7267  if(twofl_coll_inc_ionrec) then
7268  deallocate(gamma_ion, gamma_rec)
7269  endif
7270  end subroutine twofl_explicit_coll_terms_update
7271 
7272 end module mod_twofl_phys
subroutine mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: comm_lib.t:194
subroutine twofl_get_csound2_primitive(w, x, ixIL, ixOL, csound2)
subroutine twofl_get_p_c_total(w, x, ixIL, ixOL, p)
subroutine add_density_hyper_source(index_rho)
Module for physical and numeric constants.
Definition: mod_constants.t:2
double precision, parameter bigdouble
A very large real number.
Definition: mod_constants.t:11
subroutine b_from_vector_potentiala(ixIsL, ixIL, ixOL, ws, x, A)
calculate magnetic field from vector potential A at cell edges
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 add_convert_method(phys_convert_vars, nwc, dataset_names, file_suffix)
Definition: mod_convert.t:89
Module for flux conservation near refinement boundaries.
Module with basic grid data structures.
Definition: mod_forest.t:2
type(tree_node_ptr), dimension(:,:), allocatable, save igrid_to_node
Array to go from an [igrid, ipe] index to a node pointer.
Definition: mod_forest.t:32
Module with geometry-related routines (e.g., divergence, curl)
Definition: mod_geometry.t:2
subroutine divvectors(qvec, ixIL, ixOL, divq)
Calculate divergence of a vector qvec within ixL using limited extrapolation to cell edges.
Definition: mod_geometry.t:571
integer coordinate
Definition: mod_geometry.t:6
integer, parameter spherical
Definition: mod_geometry.t:10
integer, parameter cylindrical
Definition: mod_geometry.t:9
subroutine gradient(q, ixIL, ixOL, idir, gradq)
Calculate gradient of a scalar q within ixL in direction idir.
Definition: mod_geometry.t:320
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...
Definition: mod_geometry.t:626
subroutine gradients(q, ixIL, ixOL, idir, gradq)
Calculate gradient of a scalar q within ixL in direction idir first use limiter to go from cell cente...
Definition: mod_geometry.t:421
subroutine divvector(qvec, ixIL, ixOL, divq, fourthorder, sixthorder)
Calculate divergence of a vector qvec within ixL.
Definition: mod_geometry.t:479
subroutine gradientx(q, x, ixIL, ixOL, idir, gradq, fourth_order)
Calculate gradient of a scalar q in direction idir at cell interfaces.
Definition: mod_geometry.t:364
update ghost cells of all blocks including physical boundaries
subroutine getbc(time, qdt, psb, nwstart, nwbc, req_diag)
do update ghost cells of all blocks including physical boundaries
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.
integer nstep
How many sub-steps the time integrator takes.
logical h_correction
If true, do H-correction to fix the carbuncle problem at grid-aligned shocks.
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.
double precision small_pressure
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.
logical use_imex_scheme
whether IMEX in use or not
integer istep
Index of the sub-step in a multi-step time integrator.
integer, dimension(3, 3) kr
Kronecker delta tensor.
double precision phys_trac_mask
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.
character(len=std_len) convert_type
Which format to use when converting.
double precision unit_pressure
Physical scaling factor for pressure.
integer, parameter ndim
Number of spatial dimensions for grid variables.
logical angmomfix
Enable to strictly conserve the angular momentum (works both in cylindrical and spherical coordinates...
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
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 b0i
background magnetic field location indicator
integer mype
The rank of the current MPI task.
character(len=std_len) typediv
integer, dimension(:), allocatable, parameter d
integer ndir
Number of spatial dimensions (components) for vector variables.
integer ixm
the mesh range (within a block with ghost cells)
integer ierrmpi
A global MPI error return code.
logical autoconvert
If true, already convert to output format during the run.
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.
double precision unit_velocity
Physical scaling factor for velocity.
double precision c_norm
Normalised speed of light.
logical b0field
split magnetic field as background B0 field
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
pure subroutine cross_product(ixIL, ixOL, a, b, axb)
Cross product of two vectors.
integer nghostcells
Number of ghost cells surrounding a grid.
integer, parameter bc_symm
logical phys_trac
Use TRAC (Johnston 2019 ApJL, 873, L22) for MHD or 1D HD.
logical need_global_cmax
need global maximal wave speed
logical convert
If true and restart_from_file is given, convert snapshots to other file formats.
logical crash
Save a snapshot before crash a run met unphysical values.
logical use_multigrid
Use multigrid (only available in 2D and 3D)
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
double precision small_density
integer r_
Indices for cylindrical coordinates FOR TESTS, negative value when not used:
integer boundspeed
bound (left/min and right.max) speed of Riemann fan
integer, parameter unitconvert
double precision, dimension(ndim) dxlevel
logical check_small_values
check and optionally fix unphysical small values (density, gas pressure)
integer, parameter ixglo
Lower index of grid block arrays (always 1)
Subroutines for Roe-type Riemann solver for HD.
subroutine second_same_deriv2(ixIL, ixOL, nu_hyper, var2, var, idimm, res)
subroutine second_cross_deriv(ixIL, ixOL, nu_hyper, var, idimm, idimm2, res)
subroutine div_vel_coeff(ixIL, ixOL, vel, idimm, nu_vel)
subroutine hyp_coeff(ixIL, ixOL, var, idimm, nu_hyp)
subroutine second_cross_deriv2(ixIL, ixOL, nu_hyper, var2, var, idimm, idimm2, res)
subroutine second_same_deriv(ixIL, ixOL, nu_hyper, var, idimm, res)
subroutine hyperdiffusivity_init()
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.
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition: mod_physics.t:4
module radiative cooling – add optically thin radiative cooling for HD and MHD
subroutine radiative_cooling_init(fl, read_params)
subroutine cooling_get_dt(w, ixIL, ixOL, dtnew, dxD, x, fl)
subroutine radiative_cooling_add_source(qdt, ixIL, ixOL, wCT, w, x, qsourcesplit, active, fl)
subroutine radiative_cooling_init_params(phys_gamma, He_abund)
Radiative cooling initialization.
Module for handling problematic values in simulations, such as negative pressures.
logical, public trace_small_values
trace small values in the source file using traceback flag of compiler
subroutine, public small_values_average(ixIL, ixOL, w, x, w_flag, windex)
logical, dimension(:), allocatable, public small_values_fix_iw
Whether to apply small value fixes to certain variables.
subroutine, public small_values_error(wprim, x, ixIL, ixOL, w_flag, subname)
character(len=20), public small_values_method
How to handle small values.
Generic supertimestepping method 1) in amrvac.par in sts_list set the following parameters which have...
subroutine, public add_sts_method(sts_getdt, sts_set_sources, startVar, nflux, startwbc, nwbc, evolve_B)
subroutine which added programatically a term to be calculated using STS Params: sts_getdt function c...
subroutine, public set_conversion_methods_to_head(sts_before_first_cycle, sts_after_last_cycle)
Set the hooks called before the first cycle and after the last cycle in the STS update This method sh...
subroutine, public set_error_handling_to_head(sts_error_handling)
Set the hook of error handling in the STS update. This method is called before updating the BC....
subroutine, public sts_init()
Initialize sts module.
Thermal conduction for HD and MHD Adaptation of mod_thermal_conduction for the mod_supertimestepping ...
subroutine, public sts_set_source_tc_hd(ixIL, ixOL, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux, fl)
subroutine, public tc_get_hd_params(fl, read_hd_params)
Read tc module parameters from par file: MHD case.
subroutine tc_init_params(phys_gamma)
subroutine, public sts_set_source_tc_mhd(ixIL, ixOL, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux, fl)
anisotropic thermal conduction with slope limited symmetric scheme Sharma 2007 Journal of Computation...
double precision function, public get_tc_dt_hd(w, ixIL, ixOL, dxD, x, fl)
subroutine, public tc_get_mhd_params(fl, read_mhd_params)
Init TC coeffiecients: MHD case.
double precision function, public get_tc_dt_mhd(w, ixIL, ixOL, dxD, x, fl)
Get the explicut timestep for the TC (mhd implementation)
subroutine get_euv_image(qunit, fl)
subroutine get_sxr_image(qunit, fl)
subroutine get_euv_spectrum(qunit, fl)
Magneto-hydrodynamics module.
Definition: mod_twofl_phys.t:2
double precision function twofl_get_tc_dt_mhd_c(w, ixIL, ixOL, dxD, x)
subroutine twofl_get_temperature_from_etot_c(w, x, ixIL, ixOL, res)
Calculate temperature=p/rho when in e_ the total energy is stored this does not check the values of t...
subroutine add_source_linde(qdt, ixIL, ixOL, wCT, w, x)
logical, public twofl_coll_inc_ionrec
whether include ionization/recombination inelastic collisional terms
subroutine twofl_getv_hall(w, x, ixIL, ixOL, vHall)
subroutine twofl_get_csound2_adiab_c(w, x, ixIL, ixOL, csound2)
subroutine add_source_b0split(qdt, ixIL, ixOL, wCT, w, x)
Source terms after split off time-independent magnetic field.
subroutine twofl_check_w(primitive, ixIL, ixOL, w, flag)
logical, public, protected twofl_dump_full_vars
whether dump full variables (when splitting is used) in a separate dat file
double precision, public, protected rn
logical, public clean_initial_divb
clean initial divB
double precision, public twofl_eta_hyper
The MHD hyper-resistivity.
pure logical function has_collisions()
subroutine hyperdiffusivity_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
subroutine internal_energy_add_source_n(qdt, ixIL, ixOL, wCT, w, x)
double precision, public twofl_eta
The MHD resistivity.
integer, public, protected twofl_trac_type
Which TRAC method is used
subroutine twofl_get_pthermal_c_primitive(w, x, ixIL, ixOL, pth)
logical, public has_equi_pe_c0
double precision function, dimension(ixop^s, 1:nw) dump_hyperdiffusivity_coef_dim(ixIL, ixOPL, w, x, ii)
type(tc_fluid), allocatable, public tc_fl_c
double precision function, dimension(ixo^s, 1:nwc) dump_coll_terms(ixIL, ixOL, w, x, nwc)
subroutine twofl_energy_synchro(ixIL, ixOL, w, x)
logical, public twofl_alpha_coll_constant
double precision, dimension(:), allocatable, public, protected c_shk
subroutine twofl_get_h_speed_one(wprim, x, ixIL, ixOL, idim, Hspeed)
get H speed for H-correction to fix the carbuncle problem at grid-aligned shock front
subroutine twofl_get_csound2_from_pthermal(w, x, ixIL, ixOL, pth_c, pth_n, csound2)
subroutine twofl_get_csound2_n_from_primitive(w, x, ixIL, ixOL, csound2)
logical, public, protected twofl_dump_hyperdiffusivity_coef
subroutine twofl_get_v_c(w, x, ixIL, ixOL, v)
Calculate v_c vector.
subroutine twofl_get_csound_c_idim(w, x, ixIL, ixOL, idim, csound)
subroutine set_equi_vars_grid(igrid)
sets the equilibrium variables
double precision, public twofl_glm_alpha
GLM-MHD parameter: ratio of the diffusive and advective time scales for div b taking values within [0...
subroutine update_faces_contact(ixIL, ixOL, qt, qdt, wp, fC, fE, sCT, s, vcts)
update faces using UCT contact mode by Gardiner and Stone 2005 JCP 205, 509
integer, parameter, public eq_energy_ki
subroutine twofl_get_temperature_from_eint_n_with_equi(w, x, ixIL, ixOL, res)
subroutine twofl_boundary_adjust(igrid, psb)
subroutine twofl_tc_handle_small_e_c(w, x, ixIL, ixOL, step)
subroutine twofl_get_temperature_from_eint_c(w, x, ixIL, ixOL, res)
separate routines so that it is faster Calculate temperature=p/rho when in e_ the internal energy is ...
subroutine, public get_current(w, ixIL, ixOL, idirmin, current)
Calculate idirmin and the idirmin:3 components of the common current array make sure that dxlevel(^D)...
subroutine internal_energy_add_source_c(qdt, ixIL, ixOL, wCT, w, x, ie)
subroutine add_pe_n0_divv(qdt, ixIL, ixOL, wCT, w, x)
logical, public, protected twofl_thermal_conduction_n
subroutine, public twofl_phys_init()
subroutine twofl_modify_wlr(ixIL, ixOL, qt, wLC, wRC, wLp, wRp, s, idir)
subroutine add_source_hyperres(qdt, ixIL, ixOL, wCT, w, x)
Add Hyper-resistive source to w within ixO Uses 9 point stencil (4 neighbours) in each direction.
subroutine gravity_add_source(qdt, ixIL, ixOL, wCT, w, x, energy, qsourcesplit, active)
w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO
subroutine rc_params_read_c(fl)
subroutine, public get_divb(w, ixIL, ixOL, divb, fourthorder)
Calculate div B within ixO.
logical, public, protected twofl_thermal_conduction_c
Whether thermal conduction is used.
double precision, public twofl_adiab
The adiabatic constant.
logical, public twofl_equi_thermal_c
subroutine, public twofl_get_csound2_c_from_conserved(w, x, ixIL, ixOL, csound2)
double precision function, dimension(ixo^s, 1:nwc) dump_hyperdiffusivity_coef_z(ixIL, ixOL, w, x, nwc)
subroutine add_source_powel(qdt, ixIL, ixOL, wCT, w, x)
Add divB related sources to w within ixO corresponding to Powel.
subroutine twofl_get_tcutoff_n(ixIL, ixOL, w, x, tco_local, Tmax_local)
get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
character(len=std_len), public, protected type_ct
Method type of constrained transport.
subroutine, public get_rhoc_tot(w, x, ixIL, ixOL, rhoc)
subroutine twofl_get_csound_n(w, x, ixIL, ixOL, csound)
integer, public tweight_c_
subroutine twofl_get_temperature_from_eki_c_with_equi(w, x, ixIL, ixOL, res)
subroutine, public twofl_get_pthermal_c(w, x, ixIL, ixOL, pth)
subroutine get_lorentz(ixIL, ixOL, w, JxB)
Compute the Lorentz force (JxB)
logical, public, protected twofl_radiative_cooling_n
subroutine twofl_get_csound2_adiab_n(w, x, ixIL, ixOL, csound2)
subroutine twofl_get_tcutoff_c(ixIL, ixOL, w, x, Tco_local, Tmax_local)
get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
integer, parameter, public eq_energy_none
subroutine twofl_get_csound_prim_c(w, x, ixIL, ixOL, idim, csound)
Calculate fast magnetosonic wave speed.
subroutine, public twofl_get_v_n_idim(w, x, ixIL, ixOL, idim, v)
Calculate v component.
subroutine twofl_ei_to_e_c(ixIL, ixOL, w, x)
Transform internal energy to total energy.
subroutine twofl_get_rho_n_equi(w, x, ixIL, ixOL, res)
integer, public e_n_
type(te_fluid), allocatable, public te_fl_c
double precision, public, protected rc
subroutine twofl_get_temperature_from_etot_n(w, x, ixIL, ixOL, res)
Calculate temperature=p/rho when in e_ the total energy is stored this does not check the values of t...
logical, public, protected twofl_dump_coll_terms
whether dump collisional terms in a separte dat file
logical, public twofl_equi_thermal_n
subroutine twofl_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
If resistivity is not zero, check diffusion time limit for dt.
subroutine twofl_get_pthermal_n(w, x, ixIL, ixOL, pth)
subroutine grav_params_read(files)
copied from mod_gravity
subroutine twofl_get_csound2_adiab(w, x, ixIL, ixOL, csound2)
subroutine twofl_update_faces(ixIL, ixOL, qt, qdt, wprim, fC, fE, sCT, s, vcts)
subroutine twofl_get_pthermal_n_primitive(w, x, ixIL, ixOL, pth)
logical, public, protected twofl_radiative_cooling_c
Whether radiative cooling is added.
logical, public, protected b0field_forcefree
B0 field is force-free.
subroutine twofl_sts_set_source_tc_n_hd(ixIL, ixOL, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux)
subroutine update_faces_hll(ixIL, ixOL, qt, qdt, fE, sCT, s, vcts)
update faces
integer, public e_c_
Index of the energy density (-1 if not present)
subroutine get_resistive_electric_field(ixIL, ixOL, sCT, s, jce)
calculate eta J at cell edges
integer, public equi_rho_n0_
subroutine set_equi_vars_grid_faces(igrid, x, ixIL, ixOL)
sets the equilibrium variables
subroutine twofl_implicit_coll_terms_update(dtfactor, qdt, qtC, psb, psa)
Implicit solve of psb=psa+dtfactor*dt*F_im(psb)
subroutine, public twofl_face_to_center(ixOL, s)
calculate cell-center values from face-center values
integer, parameter, public eq_energy_int
subroutine, public get_normalized_divb(w, ixIL, ixOL, divb)
get dimensionless div B = |divB| * volume / area / |B|
subroutine twofl_evaluate_implicit(qtC, psa)
inplace update of psa==>F_im(psa)
subroutine add_source_res2(qdt, ixIL, ixOL, wCT, w, x)
Add resistive source to w within ixO Uses 5 point stencil (2 neighbours) in each direction,...
double precision function, dimension(ixo^s, 1:nwc) dump_hyperdiffusivity_coef_y(ixIL, ixOL, w, x, nwc)
integer, dimension(:), allocatable, public mom_c
Indices of the momentum density.
subroutine, public get_rhon_tot(w, x, ixIL, ixOL, rhon)
subroutine twofl_angmomfix(fC, x, wnew, ixIL, ixOL, idim)
logical, public twofl_coll_inc_te
whether include thermal exchange collisional terms
double precision function twofl_get_tc_dt_hd_n(w, ixIL, ixOL, dxD, x)
logical, public has_equi_rho_c0
equi vars flags
subroutine twofl_add_source(qdt, ixIL, ixOL, wCT, w, x, qsourcesplit, active, wCTprim)
w[iws]=w[iws]+qdt*S[iws,wCT] where S is the source based on wCT within ixO
logical, public, protected twofl_viscosity
Whether viscosity is added.
subroutine calc_mult_factor1(ixIL, ixOL, step_dt, JJ, res)
double precision, public dtcollpar
subroutine twofl_explicit_coll_terms_update(qdt, ixIL, ixOL, w, wCT, x)
logical, public divbwave
Add divB wave in Roe solver.
subroutine add_source_hyperdiffusive(qdt, ixIL, ixOL, w, wCT, x)
subroutine, public twofl_to_conserved(ixIL, ixOL, w, x)
Transform primitive variables into conservative ones.
subroutine gravity_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
subroutine twofl_get_csound2(w, x, ixIL, ixOL, csound2)
subroutine twofl_get_temperature_from_etot_c_with_equi(w, x, ixIL, ixOL, res)
subroutine twofl_e_to_ei_c(ixIL, ixOL, w, x)
Transform total energy to internal energy.
subroutine twofl_handle_small_ei_c(w, x, ixIL, ixOL, ie, subname)
handle small or negative internal energy
logical, public twofl_equi_ionrec
logical, public, protected twofl_4th_order
MHD fourth order.
subroutine add_source_lorentz_work(qdt, ixIL, ixOL, w, wCT, x)
subroutine get_alpha_coll(ixIL, ixOL, w, x, alpha)
subroutine add_source_glm(qdt, ixIL, ixOL, wCT, w, x)
integer, public tcoff_n_
subroutine twofl_write_info(fh)
Write this module's parameters to a snapsoht.
subroutine, public twofl_to_primitive(ixIL, ixOL, w, x)
Transform conservative variables into primitive ones.
subroutine twofl_get_h_speed_species(wprim, x, ixIL, ixOL, idim, Hspeed)
get H speed for H-correction to fix the carbuncle problem at grid-aligned shock front
subroutine twofl_get_v_n(w, x, ixIL, ixOL, v)
Calculate v_n vector.
double precision, dimension(:), allocatable, public, protected c_hyp
subroutine twofl_get_temperature_c_equi(w, x, ixIL, ixOL, res)
subroutine twofl_get_ct_velocity(vcts, wLp, wRp, ixIL, ixOL, idim, cmax, cmin)
prepare velocities for ct methods
integer, public equi_rho_c0_
equi vars indices in the stateequi_vars array
logical, public, protected twofl_glm
Whether GLM-MHD is used.
double precision, public twofl_alpha_coll
collisional alpha
logical, public, protected twofl_trac
Whether TRAC method is used.
integer, parameter, public eq_energy_tot2
subroutine coll_terms(ixIL, ixOL, w, x)
integer, dimension(:), allocatable, public mag
Indices of the magnetic field.
subroutine twofl_get_cbounds_species(wLC, wRC, wLp, wRp, x, ixIL, ixOL, idim, Hspeed, cmax, cmin)
Estimating bounds for the minimum and maximum signal velocities.
subroutine rc_params_read_n(fl)
double precision, public twofl_etah
The MHD Hall coefficient.
subroutine twofl_get_temp_n_pert_from_etot(w, x, ixIL, ixOL, res)
subroutine, public b_from_vector_potential(ixIsL, ixIL, ixOL, ws, x)
calculate magnetic field from vector potential
double precision function, dimension(ixo^s, 1:nwc) convert_vars_splitting(ixIL, ixOL, w, x, nwc)
subroutine twofl_init_hyper(files)
subroutine add_source_res1(qdt, ixIL, ixOL, wCT, w, x)
Add resistive source to w within ixO Uses 3 point stencil (1 neighbour) in each direction,...
subroutine twofl_get_csound(w, x, ixIL, ixOL, idim, csound)
logical, dimension(2 *^nd), public, protected boundary_divbfix
To control divB=0 fix for boundary.
double precision function, dimension(ixo^s) twofl_mag_en(w, ixIL, ixOL)
Compute evolving magnetic energy.
integer, public equi_pe_c0_
subroutine twofl_get_temperature_from_eint_c_with_equi(w, x, ixIL, ixOL, res)
integer, parameter, public eq_energy_tot
subroutine twofl_te_images
integer, dimension(:), allocatable, public mom_n
logical, public, protected twofl_gravity
Whether gravity is added: common flag for charges and neutrals.
subroutine, public get_alpha_coll_plasma(ixIL, ixOL, w, x, alpha)
double precision function twofl_get_tc_dt_hd_c(w, ixIL, ixOL, dxD, x)
integer, public tcoff_c_
Index of the cutoff temperature for the TRAC method.
subroutine twofl_check_params
subroutine, public twofl_clean_divb_multigrid(qdt, qt, active)
subroutine twofl_get_csound_prim(w, x, ixIL, ixOL, idim, csound)
Calculate fast magnetosonic wave speed when cbounds_species=false.
subroutine twofl_sts_set_source_tc_c_mhd(ixIL, ixOL, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux)
subroutine twofl_physical_units()
double precision, public, protected he_abundance
subroutine associate_dump_hyper()
double precision, public, protected twofl_trac_mask
Height of the mask used in the TRAC method.
logical, public has_equi_pe_n0
subroutine twofl_get_a2max(w, x, ixIL, ixOL, a2max)
subroutine twofl_add_source_geom(qdt, ixIL, ixOL, wCT, w, x)
double precision function, dimension(ixo^s) twofl_mag_en_all(w, ixIL, ixOL)
Compute 2 times total magnetic energy.
subroutine twofl_handle_small_values(primitive, w, x, ixIL, ixOL, subname)
double precision function, dimension(ixo^s) twofl_kin_en_c(w, ixIL, ixOL)
compute kinetic energy of charges w are conserved variables
subroutine twofl_get_temperature_n_equi(w, x, ixIL, ixOL, res)
subroutine twofl_get_temperature_from_eint_n(w, x, ixIL, ixOL, res)
separate routines so that it is faster Calculate temperature=p/rho when in e_ the internal energy is ...
integer, public rho_c_
Index of the density (in the w array)
logical, public, protected twofl_divb_4thorder
Whether divB is computed with a fourth order approximation.
logical, public twofl_equi_thermal
subroutine twofl_get_csound2_n_from_conserved(w, x, ixIL, ixOL, csound2)
subroutine tc_c_params_read_hd(fl)
double precision function, dimension(ixo^s) twofl_kin_en_n(w, ixIL, ixOL)
compute kinetic energy of neutrals
subroutine, public get_gamma_ion_rec(ixIL, ixOL, w, x, gamma_rec, gamma_ion)
subroutine twofl_get_temp_c_pert_from_etot(w, x, ixIL, ixOL, res)
subroutine twofl_get_cmax(w, x, ixIL, ixOL, idim, cmax)
Calculate cmax_idim=csound+abs(v_idim) within ixO^L.
subroutine twofl_ei_to_e_n(ixIL, ixOL, w, x)
double precision function, dimension(ixo^s) twofl_mag_i_all(w, ixIL, ixOL, idir)
Compute full magnetic field by direction.
subroutine twofl_handle_small_ei_n(w, x, ixIL, ixOL, ie, subname)
handle small or negative internal energy
subroutine update_faces_average(ixIL, ixOL, qt, qdt, fC, fE, sCT, s)
get electric field though averaging neighors to update faces in CT
logical, public has_equi_rho_n0
subroutine tc_n_params_read_hd(fl)
subroutine twofl_e_to_ei_n(ixIL, ixOL, w, x)
Transform total energy to internal energy.
integer, public rho_n_
subroutine fixdivb_boundary(ixGL, ixOL, w, x, iB)
subroutine twofl_get_csound_prim_n(w, x, ixIL, ixOL, idim, csound)
Calculate fast magnetosonic wave speed.
subroutine twofl_get_flux(wC, w, x, ixIL, ixOL, idim, f)
Calculate fluxes within ixO^L.
subroutine tc_c_params_read_mhd(fl)
subroutine twofl_get_cbounds_one(wLC, wRC, wLp, wRp, x, ixIL, ixOL, idim, Hspeed, cmax, cmin)
Estimating bounds for the minimum and maximum signal velocities.
integer, public eaux_c_
Indices of auxiliary internal energy.
subroutine add_pe_c0_divv(qdt, ixIL, ixOL, wCT, w, x)
logical, public, protected twofl_hyperdiffusivity
Whether hyperdiffusivity is used.
integer, public, protected twofl_eq_energy
subroutine, public twofl_get_v_c_idim(w, x, ixIL, ixOL, idim, v)
Calculate v_c component.
subroutine twofl_get_pe_c_equi(w, x, ixIL, ixOL, res)
subroutine add_geom_pdivv(qdt, ixIL, ixOL, v, p, w, x, ind)
subroutine twofl_get_pe_n_equi(w, x, ixIL, ixOL, res)
subroutine add_source_janhunen(qdt, ixIL, ixOL, wCT, w, x)
integer, dimension(2 *^nd), public, protected boundary_divbfix_skip
To skip * layer of ghost cells during divB=0 fix for boundary.
subroutine twofl_sts_set_source_tc_c_hd(ixIL, ixOL, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux)
character(len=std_len), public, protected typedivbfix
Method type to clean divergence of B.
double precision, public twofl_gamma
The adiabatic index.
integer, public equi_pe_n0_
logical, public, protected twofl_hall
Whether Hall-MHD is used.
integer, public tweight_n_
subroutine twofl_tc_handle_small_e_n(w, x, ixIL, ixOL, step)
subroutine twofl_get_temperature_from_etot_n_with_equi(w, x, ixIL, ixOL, res)
subroutine twofl_get_temperature_from_eki_c(w, x, ixIL, ixOL, res)
integer, public, protected psi_
Indices of the GLM psi.
subroutine twofl_get_rho_c_equi(w, x, ixIL, ixOL, res)
logical, public, protected source_split_divb
Whether divB cleaning sources are added splitting from fluid solver.
Module with all the methods that users can customize in AMRVAC.
procedure(special_resistivity), pointer usr_special_resistivity
procedure(phys_gravity), pointer usr_gravity
procedure(set_equi_vars), pointer usr_set_equi_vars
procedure(set_electric_field), pointer usr_set_electric_field
procedure(set_wlr), pointer usr_set_wlr
The module add viscous source terms and check time step.
Definition: mod_viscosity.t:10
subroutine viscosity_add_source(qdt, ixIL, ixOL, wCT, w, x, energy, qsourcesplit, active)
Definition: mod_viscosity.t:86
subroutine viscosity_init(phys_wider_stencil, phys_req_diagonal)
Initialize the module.
Definition: mod_viscosity.t:57
The data structure that contains information about a tree node/grid block.
Definition: mod_forest.t:11