call Eos(integer(IN) :: mode, integer(IN) :: vecLen, real(INOUT) :: eosData(vecLen*EOS_NUM), optional, real(IN) :: massFrac(vecLen*NSPECIES), optional, logical(IN),target :: mask(EOS_VARS+1:EOS_NUM), optional, integer(IN) :: vecBegin, optional, integer(IN) :: vecEnd )
This routine applies the equation of state to thermodynamic quantities at one or more grid cells. The number of cells is determined by the argument veclen. The routine expects data packaged for it in the 1d array, eosData. The data in eosData is organized as: 1:vecLen points contain the first variable, vecLen+1:2*vecLen points contain the second variable, and so on. The number and order of variables in the array is determined by the constants defined in Eos.h. The routine takes different quantities as givens depending on the value of the mode variable: if mode=MODE_DENS_TEMP, density and temperature are taken as given, and pressure and internal energy are generated as output; if mode=MODE_DENS_EI, density and internal energy are taken as givens, and pressure and temperature are generated as output. If mode=MODE_DENS_PRES, density and pressure are taken as givens, and internal energy and temperature are generated as output. Note that internal energy is EINT_VAR, not ENER_VAR. In addition to pressure, temperature, and internal energy, which are always thermodynamically consistent after this call, other quantities such as the various thermodynamic partial derivatives can be calculated based on the values in the argument, mask. mask is a logical array with one entry per quantity, with the order determined by constants defined in Eos.h (the same as those for the eosData argument); .true. means return the quantity, .false. means don't.
mode : Selects the mode of operation of the Eos unit. The valid values are MODE_DENS_EI, MODE_DENS_PRES and MODE_DENS_TEMP as decribed above. vecLen : number of points (cells) for which the eosData array is sized. If vecBegin and vecEnd are not present, this is also the number of points (cells) for which EOS computation is to be done. eosData : This array is the data structure through which variable values are passed in and out of the Eos routine. The arrays is sized as EOS_NUM*vecLen. EOS_NUM, and individual input and output Eos variables are defined in Eos.h. The array is organizes such that the first 1:vecLen entries represent the first Eos variable, vecLen+1: 2*vecLen represent the second Eos variable and so on. massFrac : Contains the mass fractions of the species included in the simulation. The array is sized as NSPECIES*vecLen. mask : Mask is a logical array the size of EOS_DERIVS (number of partial derivatives that can be computed, defined in Eos.h), where each index represents a specific partial derivative that can be calculated by the Eos unit. A .true. value in mask results in the corresponding derivative being calculated and returned. It should preferably be dimensioned as mask(EOS_VARS+1:EOS_NUM) in the calling routine to exactly match the arguments declaration in Eos Unit. Note that the indexing of mask does not begin at 1, but rather at one past the number of variables. An implementation that does not need derivative quantities should set the mask equal to .false. vecBegin : Index of first cell in eosData to handle. Can be used to limit operation to a subrange of cells, untested. If not present, the default is 1. vecEnd : Index of last cell in eosData to handle. Can be used to limit operation to a subrange of cells, untested. If not present, the default is vecLen.
--- A single-point at a time example, does not calculate derivatives (based on Cellular Simulation)--- #include "constants.h" ! for MODE_DENS_TEMP #include "Flash.h" ! for NSPECIES #include "Eos.h" ! for EOS_VAR order real :: temp_zone, rho_zone, ptot, eint, gamma real, dimension(EOS_NUM) :: eosData real, dimension(SPECIES_BEGIN:SPECIES_END) :: massFraction integer, dimension(2,MDIM) :: blockRange,blockExtent massFraction(:) = 1.0e-12 massFraction(C12_SPEC) = 1.0 .... initiale temp_zone, rho_zone call Grid_getBlkIndexLimits(blockId,blockRange,blockExtent) do k = blockRange(LOW,KAXIS), blockRange(HIGH,KAXIS) do j = blockRange(LOW,JAXIS),blockRange(HIGH,JAXIS) do i = blockRange(LOW,IAXIS),blockRange(HIGH,IAXIS) eosData(EOS_TEMP) = temp_zone eosData(EOS_DENS) = rho_zone call Eos(MODE_DENS_TEMP,1,eosData,massFraction) ptot = eosData(EOS_PRES) eint = eosData(EOS_EINT) gamma = eosData(EOS_GAMC) call Grid_putPointData(blockId,CENTER,TEMP_VAR,EXTERIOR,iPosition,temp_zone) call Grid_putPointData(blockId,CENTER,DENS_VAR,EXTERIOR,iPosition,rho_zone) call Grid_putPointData(blockId,CENTER,PRES_VAR,EXTERIOR,iPosition,ptot) call Grid_putPointData(blockId,CENTER,EINT_VAR,EXTERIOR,iPosition,eint) if you want ENER_VAR, calculate it from EINT_VAR and kinetic energy call Grid_putPointData(blockId,CENTER,GAMC_VAR,EXTERIOR,iPosition,gamma) call Grid_putPointData(blockId,CENTER,GAME_VAR,EXTERIOR,iPosition,(ptot/(etot*sim_rhoAmbient) + 1.0)) enddo ! end of k loop enddo ! end of j loop enddo ! end of i loop ------------------ Row at a time example, with derivates (based on Eos_unitTest) -------- #include "constants.h" ! for MODE_DENS_TEMP #include "Flash.h" ! for NSPECIES, EOS_NUM #include "Eos.h" ! for EOS_VAR order integer veclen, isize, jsize, ksize, i,j,k, e real, dimension(:), allocatable :: eosData real, dimension(:), allocatable :: massFrac logical, dimension (EOS_VARS+1:EOS_NUM) :: mask real, allocatable, dimension(:,:,:,:) :: derivedVariables integer,dimension(2,MDIM) :: blkLimits,blkLimitsGC ! in the Eos_unitTest, this loops over all blocks.... here is a snippet from inside call Grid_getBlkIndexLimits(blockID,blkLimits,blkLimitsGC) ! Allocate the necessary arrays for an entire block of data isize = (blkLimits(HIGH,IAXIS) - blkLimits(LOW,IAXIS) + 1) jsize = (blkLimits(HIGH,JAXIS) - blkLimits(LOW,JAXIS) + 1) ksize = (blkLimits(HIGH,KAXIS) - blkLimits(LOW,KAXIS) + 1) vecLen=isize allocate(derivedVariables(isize,jsize,ksize,EOS_NUM)) allocate(eosData(vecLen*EOS_NUM)) allocate(massFrac(vecLen*NSPECIES)) mask = .true. ! indices into the first location for these variables pres = (EOS_PRES-1)*vecLen dens = (EOS_DENS-1)*vecLen temp = (EOS_TEMP-1)*vecLen call Grid_getBlkPtr(blockID,solnData) do k = blkLimits(LOW,KAXIS),blkLimits(HIGH,KAXIS) do j = blkLimits(LOW,JAXIS), blkLimits(HIGH, JAXIS) do i = 1,vecLen massFrac((i-1)*NSPECIES+1:i*NSPECIES) = & solnData(SPECIES_BEGIN:SPECIES_END,ib+i-1,j,k) end do eosData(pres+1:pres+vecLen) = solnData(PRES_VAR,ib:ie,j,k) eosData(dens+1:dens+vecLen) = solnData(DENS_VAR,ib:ie,j,k) ! Eos Helmholtz needs a good initial estimate of temperature no matter what the mode eosData(temp+1:temp+vecLen) = solnData(TEMP_VAR,ib:ie,j,k) call Eos(MODE_DENS_PRES,vecLen,eosData,massFrac,mask) do e=EOS_VARS+1,EOS_NUM m = (e-1)*vecLen derivedVariables(1:vecLen,j-NGUARD,k-NGUARD,e) = eosData(m+1:m+vecLen) end do end do end do
NSPECIES is defined in Flash.h. EOS_VARS and EOS_NUM are defined in Eos.h. Calling funtions should included Eos.h, in order to get the definitions of Eos-specific constants to be able to populate the eosData and mask arrays. MODE_DENS_TEMP, MODE_DENS_EI, and MODE_DENS_PRES are defined in constants.h. All routines calling this routine should include a use Eos_interface statement, preferable with "ONLY" attribute e.g. use Eos_interface, ONLY: Eos When using Helmholtz, strange behaviour occurs. See the notes in subunit Helmholtz/Eos.F90 directly. For Helmholtz, when operating in MODE_DENS_EI, the INPUT energy is updated. Similarly, when operating in MODE_DENS_PRES, the INPUT pressure is updated. Physicists need to be aware of this. This behavior can be turned off by setting the runtime parameter eos_forceConstantInput. For Gamma and Multigamma routines, the entropy and entropy derivatives calculations have not been confirmed to be correct. Use with caution.
Eos.h defines the variables used. Eos_wrapped sets up the data structure.