The radiative transfer (25.1) and electron energy (25.2) equations can be simplified using a multigroup diffusion approximation. The frequency space is divided into groups with . Group is defined by the frequency range from to . The plasma is assumed to emit radiation in a Planck spectrum with a given emission opacity. The multigroup diffusion equations solved by FLASH are
(25.5) |
The multigroup diffusion equation and electron internal energy equation are operator-split using an explicit treatment. Thus, on each time step (25.4) is solved for each energy group using coefficients evaluated at time level using an implicit treatment for the diffusion solution itself. The equation below shows how the multigroup equations are discretized in time
The diffusion equation, (25.6), is an implicit equation and is solved using the general implicit diffusion solver described in section 19.1.2. It is recommended that users familiarize themselves with the general implicit diffusion solver to learn more about using MGD in FLASH.
The planck integral in previous versions has significant error and can be negative for . Set rt_planckIntMethod to 0 (by default) to use the method in old versions. Set rt_planckIntMethod to a positive number to use the new method: mininum of the -th order expansion as and the -th order expansion as . Current available options: set to for and , set to for and , set to for and .
This section describes how to use MGD in FLASH. Section 35.7.5 shows an example of how to use MGD in a realistic HEDP simulation and is extremely informative.
Several setup options are needed to use MGD. The +mgd setup shortcut will include the MGD unit in the simulation. In addition, storage needs to be created for storing the specific energy for each group. This is done using the mgd_meshgroups setup variable. The user must set mgd_meshgroups such that:
(25.8) |
+mgd mgd_meshgroups=6
The FLASH checkpoint files will contain the specific energy in each radiation energy group for each cell. The variables are named r### where ### is a three digit number from one to . Users can also add these variables to the list of plot variables so they will be included in plot files.
Several runtime parameters are used to control the MGD unit. The runtime parameter rt_useMGD must be set to .true. for MGD simulations. The energy group structure (values of the group boundaries) are specified, manually, using runtime parameters. A simulation with groups will have energy group boundaries. These are set using the rt_mgdBounds_### runtime parameters, where ### is a number between 1 and . By default, enough runtime parameters exist for specifying 101 energy group boundaries. In the case that more groups are needed, the mgd_maxgroups setup variable sets the number of group boundary runtime parameters. For example, if 200 energy groups are needed, then mgd_maxgroups=200 should be specified on the setup line. If , no action is needed.
When MGD is in use, the Opacity unit provides opacities for each cell. Thus, the useOpacity runtime parameter must be set to true and the appropriate opacity model must be specified. Please see section 23.5 for a detailed description on how to use the Opacity unit in FLASH.
Finally, the radiation boundary conditions must be specified using
runtime parameters. The parameters:
rt_mgdXlBoundaryType rt_mgdXrBoundaryType rt_mgdYlBoundaryType rt_mgdYrBoundaryType rt_mgdZlBoundaryType rt_mgdZrBoundaryType
As was mentioned earlier, FLASH uses the generalized implicit diffusion solver, described in section 19.1.2, to solve (25.6) for each energy group. Thus, users must make sure to include an appropriate diffusion solver in their simulation.
When many energy groups are needed, domain decomposition alone is not an effective method for speeding up calculations. The computation time scales roughly linearly with the number of energy groups. As the number of groups increases, users can divide the mesh among larger number of processors to compensate. This is an effective strategy until the strong scaling limit for the simulation is reached. At this point, mesh replication becomes the only way to speed up the simulation further.
Mesh replication allows FLASH to perform the diffusion solves for each energy group in parallel. By default, mesh replication is deactivated and each diffusion equation is solved serially. When mesh replication is in use the total pool of processes is divided among identical copies of the computational mesh. The radiation solver uses these copies of the mesh to perform parallel radiation solves. The runtime parameter meshCopyCount is used to set and has a value of 1 by default.
This is best illustrated with an example. Suppose , the total number of energy groups, is set to 100, and there are processes available to run the simulation. If meshCopyCount=1, then and the computational mesh will not be replicated. This is FLASH's normal mode of operation: the mesh will be divided into six pieces and each process will be responsible for one of these pieces. Each process will also be involved in the solution of the diffusion equation for all 100 energy groups. If meshCopyCount=2, then the computational domain will be divided into three pieces. Two processes will be assigned to each piece. In other words two groups of three processes will be created. The first set of three processes will be responsible for solving the diffusion equations for the odd numbered energy groups. The second set of processes will solve the diffusion equations for the even numbered energy groups. Each process only knows about 50 of the 100 groups. In some cases, this may be substantially faster than the meshCopyCount=1 approach.
Another benefit of mesh replication is that it reduces the amount of memory needed per process. In the example above, when meshCopyCount=1, each process must store the energy density for all 100 energy groups. Thus, storage must exist for 100 cell centered variables on each process. When meshCopyCount=2, storage is only needed for 50 cell centered variables. The setup variable mgd_meshgroups controls the number of cell centered variables created on process. Thus, when meshCopyCount=2, we can set mgd_meshgroups to 50 instead of 100. As a result, far less memory is used per block.
Whether or not mesh replication is helpful for a particular simulation can only be determined through extensive testing. It depends on the particular simulation and the hardware.
The initial conditions must be specified throughout the domain for each radiation energy group. This involves setting the specific energy, , in units of erg/g for each group. Because of the mesh replication capability, the user is discouraged from manually setting the value of the underlying radiation mass scalars. Instead, several routines have been added to the RadTrans unit to simplify this process dramatically. Specifying the initial conditions involves two steps. First, the value of must be set for each group in each cell. Second, either the total specific radiation energy, , or the radiation temperature, , must be set - depending on the value of eosModeInit. Below, two use cases are described.
The easiest way to set the initial condition is to use a radiation temperature in each cell and to assume that the radiation field is described by a Planck spectrum. The subroutine:
RadTrans_mgdEFromT(blockId, axis, trad, tradActual)
will automatically set the value of for each group using a given radiation temperature and assuming a black body spectrum. The arguments are:
Once RadTrans_mgdEFromT has been used to initialize , either the total radiation specific energy, , must be set or the radiation temperature for the cell must be specified. When the runtime parameter eosModeInit is set to “dens_temp_gather”, the initial radiation temperature must be specified in the variable TRAD_VAR. When eosModeInit is set to “dens_ie_gather”, must be specified in the variable ERAD_VAR.
The example below shows a segment from a Simulation_initBlock routine from a typical simulation which uses MGD:
do k = blkLimits(LOW,KAXIS),blkLimits(HIGH,KAXIS) do j = blkLimits(LOW,JAXIS),blkLimits(HIGH,JAXIS) do i = blkLimits(LOW,IAXIS),blkLimits(HIGH,IAXIS) axis(IAXIS) = i axis(JAXIS) = j axis(KAXIS) = k ... ! Set the secific energy in each radiation group using a ! radiation temperature of 1 eV (11604.55 K): call RadTrans_mgdEFromT(blockId, axis, 11604.55, tradActual) ! Set the radiation temperature: call Grid_putPointData(blockId, CENTER, TRAD_VAR, EXTERIOR, axis, tradActual) ! Alternatively, we could have set ERAD_VAR using a*(tradActual)**4 enddo enddo enddo
Note that tradActual is used to specify the value of TRAD_VAR.
Specifying the radiation temperature is sufficient for many cases. Alternatively, users can manually specify the radiation spectrum. The subroutine
RadTrans_mgdSetEnergy(blockId, axis, group, eg)
has been created for this purpose. The arguments are:
The example below assumes that the user would like to initialize the radiation field so that and all other groups are initialized to zero energy. Note, that for this example, the user should obtain the value of , the radiation constant, from the PhysicalConstants unit. This simulations used .
do k = blkLimits(LOW,KAXIS),blkLimits(HIGH,KAXIS) do j = blkLimits(LOW,JAXIS),blkLimits(HIGH,JAXIS) do i = blkLimits(LOW,IAXIS),blkLimits(HIGH,IAXIS) axis(IAXIS) = i axis(JAXIS) = j axis(KAXIS) = k ... ! Set the secific energy in each radiation group: call RadTrans_mgdSetEnergy(blockId, axis, 1, a*sim_trad**4/sim_rho) call RadTrans_mgdSetEnergy(blockId, axis, 2, 0.0) call RadTrans_mgdSetEnergy(blockId, axis, 3, 0.0) call RadTrans_mgdSetEnergy(blockId, axis, 4, 0.0) ! Set the radiation temperature: call Grid_putPointData(blockId, CENTER, TRAD_VAR, EXTERIOR, axis, sim_trad) ! Alternatively, we could have set ERAD_VAR using a*sim_trad**4/sim_rho enddo enddo enddo
In some cases, it is necessary to alter the radiation spectrum manually, for example, to add a radiation energy source. In these cases, it is useful to manually alter the mesh variables which store the specific radiation energy within each group: . However, because of mesh replication, altering these variables requires a different procedure than modifying other mesh variables (such as the density) in FLASH. The reason is that each process does not, in general, have access to each . The procedure for modifying directly is as follows:
! Loop over all cells, set the specific radiation energy to zero: do lb = 1, nblk call Grid_getBlkIndexLimits(blklst(lb),blkLimits,blkLimitsGC) call Grid_getBlkPtr(blklst(lb), blkPtr) do k = blkLimits(LOW,KAXIS), blkLimits(HIGH,KAXIS) do j = blkLimits(LOW,JAXIS), blkLimits(HIGH,JAXIS) do i = blkLimits(LOW,IAXIS), blkLimits(HIGH,IAXIS) blkPtr(ERAD_VAR,i,j,k) = 0.0 end do end do end do call Grid_releaseBlkPtr(blklst(lb), blkPtr) end do ! Loop over radiation energy groups: do gloc = 1, NONREP_NLOCS(rt_acrossMe, rt_meshCopyCount, rt_mgdNumGroups) ! g represents the global energy group number: g = NONREP_LOC2GLOB(gloc, rt_acrossMe, rt_meshCopyCount) ! gvar represents the index in the block pointer for group g: gvar = MGDR_NONREP_LOC2UNK(gloc) ! Loop over blocks and set the energy density in each group: do lb = 1, nblk call Grid_getBlkIndexLimits(blklst(lb),blkLimits,blkLimitsGC) call Grid_getBlkPtr(blklst(lb), blkPtr) do k = blkLimits(LOW,KAXIS), blkLimits(HIGH,KAXIS) do j = blkLimits(LOW,JAXIS), blkLimits(HIGH,JAXIS) do i = blkLimits(LOW,IAXIS), blkLimits(HIGH,IAXIS) ! Set the specific energy in group g: blkPtr(gvar,i,j,k) = 1.0e+12 ! Make sure to track the total radiation energy in the cell: blkPtr(ERAD_VAR,i,j,k) = blkPtr(ERAD_VAR,i,j,k) + & blkPtr(gvar,i,j,k) end do end do end do call Grid_releaseBlkPtr(blklst(lb), blkPtr) end do end do ! Finally, every process needs to know the total specific radiation ! energy. RadTrans_sumEnergy adds up ERAD_VAR across all of the ! meshes: call RadTrans_sumEnergy(ERAD_VAR, nblk, blklst) ! Call EOS to get a consistent state: do lb = 1, nblk call Grid_getBlkIndexLimits(blklst(lb),blkLimits,blkLimitsGC) call Eos_wrapped(MODE_DENS_EI_GATHER,blkLimits,blklst(lb)) end do
The second part of the example loops over the groups. Notice the strange loop ending index. The NONREP_NLOCS macro computes the number of groups represented on a given process. To find the actual group number, , a call is made to NONREP_LOC2GLOB. Next, MGDR_NONREP_LOC2UNK is called to get the actual index into the block pointer which corresponds to group g. Following this is a fairly standard loop over blocks and cells where the block pointer is used to modify the specific energy in each group. Notice that we are keeping a running total of the total specific energy in the cell which is stored in ERAD_VAR.
Finally, we must call RadTrans_sumEnergy to add up ERAD_VAR across all of the meshes. After this call, every process will contain the same total specific energy in each cell. This is followed by a call to the equation of state. This is needed to update the radiation temperature and pressure, TRAD_VAR and ERAD_VAR, respectively.