module mod_variables use mod_basic_types implicit none public !> Number of flux variables integer :: nwflux = 0 !> Number of flux variables which need user to specify boundary type integer :: nwfluxbc = 0 !> Number of auxiliary variables in w integer :: nwaux = 0 !> Number of extra variables in w integer :: nwextra = 0 !> Number of extra variables in wextra seperated from w integer :: nw_extra = 0 !> Total number of variables integer :: nw = 0 !> Total number of stagger variables integer :: nws = 0 !> Number of variables which need to be updated in ghost cells integer :: nwgc = 0 !> Number of vector variables (used for writing output) integer :: nvector = 0 !> Indices of vector variables integer, dimension(:), allocatable :: iw_vector ! the number of the first w variable to exchange ghost cells integer :: iwstart=1 !> Maximum number of variables. The largest build (cell-centred GLM-MHD with !> anisotropic hyperbolic conduction and a few tracers) reaches ~15, so this !> is comfortable headroom; mod_convert and var_set_extravar guard against !> exceeding it. integer, parameter :: max_nw = 20 !> Indices in w of the extra variables, in registration order: !> iw_extra(1:nwextra). Filled by var_set_extravar so that generic code can !> address the extra variables without assuming where in w they sit. integer :: iw_extra(max_nw) = -1 !> Primitive variable names character(len=name_len) :: prim_wnames(max_nw) !> Conservative variable names character(len=name_len) :: cons_wnames(max_nw) ! Global indices of variables that are often used !> Index of the (gas) density integer :: iw_rho = -1 !> Indices of the momentum density integer, allocatable :: iw_mom(:) !> Index of the energy density integer :: iw_e = -1 !> Index of the (scalar, field-aligned-only) heat flux (isotropic HTC only) integer :: iw_q = -1 !> Indices of the heat flux vector components (anisotropic HTC only) integer, allocatable, protected :: iw_qvec(:) !> Index of the radiation energy density integer :: iw_r_e = -1 !> Indices of the magnetic field components integer, allocatable, protected :: iw_mag(:) !> Index of the cutoff temperature for the TRAC method integer :: iw_tcoff = -1 !> number of species: each species has different characterictic speeds and should !> be used accordingly in mod_finite_volume and mod_finite_difference integer :: number_species = 1 !> index of the var !> whose velocity appears in the induction eq. integer :: index_v_mag = 1 !> the indices in 1:nwflux array are assumed consecutive for each species !> this array should be of size number_species and contain the first index in the array of !> the number_species integer, allocatable :: start_indices(:) !> the indices in 1:nwflux array are assumed consecutive for each species !> this array should be of size number_species and contain the last index in the array of !> the first number_species, the last index for the last one is nwflux integer, allocatable :: stop_indices(:) ! indices of equi for the species index_v_mag ! these are needed for hlld solver, TODO: consider moving in a separate file integer :: iw_equi_rho = -1 integer :: iw_equi_p = -1 contains !> Set generic flux variable function var_set_fluxvar(name_cons, name_prim, ix, need_bc) result(iw) character(len=*), intent(in) :: name_cons !< Conservative name character(len=*), intent(in) :: name_prim !< Primitive name integer, intent(in), optional :: ix !< Optional index (to make var1, var2, ...) logical, intent(in), optional :: need_bc !< Require boundary condition (default: true) integer :: iw logical :: add_bc nwflux = nwflux + 1 nw = nw + 1 iw = nwflux add_bc = .true. if (present(need_bc)) add_bc = need_bc if (add_bc) nwfluxbc = nwfluxbc + 1 if (.not. present(ix)) then prim_wnames(nwflux) = name_cons cons_wnames(nwflux) = name_prim else write(cons_wnames(nwflux),"(A,I0)") name_cons, ix write(prim_wnames(nwflux),"(A,I0)") name_prim, ix end if end function var_set_fluxvar !> Set extra variable in w, which is not advected and has no boundary conditions. !> This has to be done after defining flux variables and auxiliary variables. function var_set_extravar(name_cons, name_prim, ix) result(iw) character(len=*), intent(in) :: name_cons, name_prim integer, intent(in), optional :: ix integer :: iw nwextra = nwextra + 1 nw = nw + 1 iw = nw if (nwextra > max_nw) then call errormsg("var_set_extravar: nwextra exceeds max_nw; raise max_nw & &in mod_variables") else iw_extra(nwextra) = iw end if if (.not. present(ix)) then prim_wnames(iw) = name_cons cons_wnames(iw) = name_prim else write(cons_wnames(iw),"(A,I0)") name_cons, ix write(prim_wnames(iw),"(A,I0)") name_prim, ix end if end function var_set_extravar !> Set extra variable in wextra, which is not advected and has no boundary conditions and not output in dat. !> This has to be done after defining flux variables and auxiliary variables. function var_set_wextra() result(iw) integer :: iw nw_extra = nw_extra + 1 iw = nw_extra end function var_set_wextra !> Set auxiliary variable, which is not advected but has boundary conditions. !> This has to be done after defining flux variables. function var_set_auxvar(name_cons, name_prim, ix) result(iw) character(len=*), intent(in) :: name_cons, name_prim integer, intent(in), optional :: ix integer :: iw nwaux = nwaux + 1 nw = nw + 1 iw = nw if (.not. present(ix)) then prim_wnames(iw) = name_cons cons_wnames(iw) = name_prim else write(cons_wnames(iw),"(A,I0)") name_cons, ix write(prim_wnames(iw),"(A,I0)") name_prim, ix end if end function var_set_auxvar !> Set density variable function var_set_rho() result(iw) integer :: iw nwflux = nwflux + 1 nwfluxbc = nwfluxbc + 1 nw = nw + 1 iw_rho = nwflux iw = nwflux prim_wnames(nwflux) = 'rho' cons_wnames(nwflux) = 'rho' end function var_set_rho ! THE INCLUDE files cannot use other modules ! mpistop replaced by errormsg, should it exit? !> Exit MPI-AMRVAC with an error message subroutine errormsg(message) character(len=*), intent(in) :: message !< The error message write(*, *) "ERROR for processor" write(*, *) trim(message) end subroutine errormsg !> Set momentum variables function var_set_momentum(ndir) result(iw) integer, intent(in) :: ndir integer :: iw(ndir), idir if (allocated(iw_mom)) call errormsg("Error: set_mom was already called") allocate(iw_mom(ndir)) do idir = 1, ndir nwflux = nwflux + 1 nwfluxbc = nwfluxbc + 1 nw = nw + 1 iw_mom(idir) = nwflux iw(idir) = nwflux write(cons_wnames(nwflux),"(A1,I1)") "m", idir write(prim_wnames(nwflux),"(A1,I1)") "v", idir end do end function var_set_momentum !> Set energy variable function var_set_energy() result(iw) integer :: iw nwflux = nwflux + 1 nwfluxbc = nwfluxbc + 1 nw = nw + 1 iw_e = nwflux iw = nwflux cons_wnames(nwflux) = 'e' prim_wnames(nwflux) = 'p' end function var_set_energy !> Set heat flux variable (hyperbolic TC treatment) function var_set_q(need_bc) result(iw) logical, intent(in), optional :: need_bc integer :: iw logical :: add_bc add_bc = .true. if (present(need_bc)) add_bc = need_bc nwflux = nwflux + 1 nw = nw + 1 if (add_bc) nwfluxbc = nwfluxbc + 1 iw_q = nwflux iw = nwflux cons_wnames(nwflux) = 'q' prim_wnames(nwflux) = 'q' end function var_set_q !> Set heat-flux vector variables (anisotropic HTC only): the full !> Cartesian heat-flux vector, decomposed into field-aligned/cross-field parts function var_set_qvec(ndir, need_bc) result(iw) integer, intent(in) :: ndir logical, intent(in), optional :: need_bc integer :: iw(ndir), idir logical :: add_bc add_bc = .true. if (present(need_bc)) add_bc = need_bc if (allocated(iw_qvec)) call errormsg("Error: set_qvec was already called") allocate(iw_qvec(ndir)) do idir = 1, ndir nwflux = nwflux + 1 nw = nw + 1 if (add_bc) nwfluxbc = nwfluxbc + 1 iw_qvec(idir) = nwflux iw(idir) = nwflux write(cons_wnames(nwflux),"(A4,I1)") "qvec", idir write(prim_wnames(nwflux),"(A4,I1)") "qvec", idir end do end function var_set_qvec function var_set_radiation_energy() result(iw) integer :: iw nwflux = nwflux + 1 nwfluxbc = nwfluxbc + 1 nw = nw + 1 iw_r_e = nwflux iw = nwflux cons_wnames(nwflux) = 'r_e' prim_wnames(nwflux) = 'r_e' end function var_set_radiation_energy !> Set magnetic field variables function var_set_bfield(ndir) result(iw) integer, intent(in) :: ndir integer :: iw(ndir), idir if (allocated(iw_mag)) call errormsg("Error: set_mag was already called") allocate(iw_mag(ndir)) do idir = 1, ndir nwflux = nwflux + 1 nwfluxbc = nwfluxbc + 1 nw = nw + 1 iw_mag(idir) = nwflux iw(idir) = nwflux write(cons_wnames(nwflux),"(A1,I1)") "b", idir write(prim_wnames(nwflux),"(A1,I1)") "b", idir end do end function var_set_bfield end module mod_variables