MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_rt_sc_state.t
Go to the documentation of this file.
1!=============================================================================
2!> Parameters, resolved state and lifecycle of the short-characteristics (SC) radiative
3!> transfer, the Olson-Kunasz linear RT of AMRVAC
4!>
5!> The &rt_list parameters are physical, with heights in cm, pressures in dyn/cm^2 and
6!> temperatures in K. rt_sc_params_read reads them, and rt_sc_setup, run once the units are
7!> fixed, converts them to code units, snaps the top of each band to a block face, sets the
8!> horizontal boundary conditions, binds the opacity callback and builds the quadrature.
9!> rt_sc_activate, called by the physics module when hd_radiative_transfer or
10!> mhd_radiative_transfer is set, runs the reading and reserves the intensity slots that the
11!> distributed wavefront needs
12!>
13!> The module also holds the state that the solvers share. This is the ps_rt intensity state,
14!> kept out of the hydro w so that it skips the stage copies, the prolongation and the output,
15!> together with the block caches of chi and B, the KBA wave state of the current solve, the
16!> buffers of the periodic seam and the node communicators of the gather. It uses
17!> mod_rt_sc_opacity and mod_rt_sc_kernel, and mod_rt_sc_solvers uses it in turn
18!>
19!> Jack Jenkins (10.2026); More or less finished in v1 state for amrvac4.0
20!=============================================================================
22 use mod_global_parameters, only: bigdouble, smalldouble, std_len, max_blocks
23 use mod_physicaldata, only: state
26 implicit none
27
28 !> True when the physics module has switched the RT on, with hd_radiative_transfer or
29 !> mhd_radiative_transfer, through rt_sc_activate
30 logical, public :: rt_sc_active = .false.
31 !> Axis of the stratification, 1 for x and 2 for y. The default of -1 takes the last axis
32 integer, public :: rt_sc_updim = -1
33 !> The AMR level the RT runs on. The bands are held at this level so that the RT sees a uniform
34 !> grid, and it cannot exceed refine_max_level
35 integer, public :: rt_sc_amr_level = 1
36 !> Centre and half-width in K of the temperature gate in rt_sc_thin_weight, which divides the
37 !> radiative losses between the SC transfer and the thin cooling
38 double precision, public :: rt_sc_blend_t0 = 2.0d4
39 double precision, public :: rt_sc_blend_dt = 5.0d3
40
41 !> The RT bands along updim, of which a bar with a photosphere at each end needs two. The edges
42 !> are in cm, with -1e30 and +1e30 standing for the domain ends, and each end has its own
43 !> incoming-intensity condition, 'thermal' or 'open'
44 integer, parameter :: rt_sc_maxband = 8
45 integer, public :: rt_sc_nband = 1
46 double precision, public :: rt_sc_band_min(rt_sc_maxband) = -1.0d30
47 double precision, public :: rt_sc_band_max(rt_sc_maxband) = 1.0d30
48 character(len=10), public :: rt_sc_bc_min(rt_sc_maxband) = 'thermal'
49 character(len=10), public :: rt_sc_bc_max(rt_sc_maxband) = 'open'
50 !> Incoming intensity at the horizontal edges where they are not periodic, 'open' for I = 0 or
51 !> 'thermal' for I = B of the edge column
52 character(len=10), public :: rt_sc_bc_hmin = 'open', rt_sc_bc_hmax = 'open'
53 !> rt_sc_flux_blend blends the thin heating c chi (J - B) with the thick -div F. rt_sc_cfl limits
54 !> the heating so that one stage changes the gas energy by at most that fraction of itself
55 logical, public :: rt_sc_flux_blend = .true.
56 double precision, public :: rt_sc_cfl = 0.5d0
57 !> Prints the cumulative RT timing every 10 solves
58 logical, public :: rt_sc_debug = .false.
59 !> Not read by the RT itself. The user files set it from eos%eint_rho_FI_threshold for their own
60 !> SC source
61 double precision, public :: rt_sc_fi_thresh = -1.0d0
62 !> Extra-variable indices of the heating Q, the vertical flux F and the emergent intensity Iout,
63 !> left at -1 when they are not registered
64 integer, public :: i_qrad = -1, i_frad = -1, i_iout = -1
65 !> Horizontal mean of the flux on the tau = rt_sc_tau_emergent surface, from rt_sc_emergent_tau1.
66 !> A flux controller should read this one, because Frad still grows by 10-16% above tau = 1 and
67 !> the flux at the band top therefore reads high
68 double precision, public :: rt_sc_ftau1 = 0.0d0
69 double precision, public :: rt_sc_tau_emergent = 1.0d0
70 !> The distributed KBA wavefront. Each rank sweeps only its own band blocks, one diagonal at a
71 !> time, with a getbc of the ray intensity between diagonals, so no rank ever holds the whole
72 !> slab. Its intensity slots are reserved by rt_sc_activate. Setting it false selects the
73 !> replicated gather, the original implementation, kept for comparison only: it holds the whole
74 !> band on every rank and its periodic seam is not exact. Production runs should keep KBA
75 logical, public :: rt_sc_distributed = .true.
76 !> The pipelined KBA. The four sweep corners run at once, each with its own intensity slot, and
77 !> the rays of a corner follow one another through the wavefront. It agrees with the ray-by-ray
78 !> wave to round-off and is 1.4-1.8 times faster
79 logical, public :: rt_sc_pipeline = .true.
80 !> For validation, runs the ray-by-ray and pipelined waves on the same state and prints max|dQ|
81 logical, public :: rt_sc_valpipe = .false.
82 !> First column of the ray intensity in ps_rt, and -1 until reserved. It is the only field getbc
83 !> exchanges during a sweep, because chi and B are cached per block while J and Fy accumulate in
84 !> i_qrad and i_frad, perhaps confusingly but it works and prevents size creep in ps_rt
85 integer :: i_isw = -1
86 !> Number of intensity slots, one for the ray-by-ray wave and up to four when pipelined
87 integer :: nisw = 1
88 !> The RT intensity state. It is kept out of the hydro w so that it skips the stage copies, the
89 !> prolongation and the output, and getbc exchanges it with bcphys off. rt_sc_alloc_state
90 !> allocates it per block
91 type(state), dimension(:), allocatable, target :: ps_rt
92 ! Set once the seam notice has been printed, so that it appears only once
93 logical :: rt_sc_seam_warned = .false.
94 !> The periodic seam of the single-pass KBA. A ray crossing the seam takes as its inflow the
95 !> outflow at the far edge from the previous solve, which is exact at steady state. The buffers
96 !> are indexed by global row along updim and by ray. seamR holds the right-hand outflow of the
97 !> last block column, which feeds the +x wrap into the first, and seamL the reverse. The _prev
98 !> buffers are read and the _cur buffers written, the allreduce at the end of each solve makes
99 !> them global, and both start at zero. With rt_sc_seam_on false the seam inflow stays zero
100 logical :: rt_sc_seam_on = .true.
101 double precision, allocatable :: rt_sc_seaml_prev(:,:), rt_sc_seamr_prev(:,:)
102 double precision, allocatable :: rt_sc_seaml_cur(:,:), rt_sc_seamr_cur(:,:)
103 !> Node-local communicator for the moment reduction of the gather. The ranks reach that
104 !> reduction far out of step because of the ray imbalance, and inter-node collectives under
105 !> such a stagger fail on the tcp/ofi provider. Each node therefore forms the full moments from
106 !> its own copy of the field
107 integer :: rt_node_comm = -1, rt_node_rank = 0, rt_node_size = 1
108 !> Communicator of one leader rank per node. The field gather sums within each node, then over
109 !> the leaders, and then broadcasts within the node, so that no collective spans all the ranks.
110 !> The tcp provider refuses those at 46 Mm
111 integer :: rt_lead_comm = -1
112 !> Cumulative wall time of the field gather, the sweep, the moment reduction and the scatter,
113 !> and of the wave, together with the number of solves
114 double precision, public :: rt_wt_gath=0.d0, rt_wt_swp=0.d0, rt_wt_red=0.d0, rt_wt_scat=0.d0
115 double precision, public :: rt_wt_wave=0.d0
116 integer, public :: rt_nsolve=0
117 !> Block chi and B including the ghosts, rebuilt every solve, and the block horizontal flux Fx
118 !> for the -div F blend. Fy accumulates in i_frad instead, and Fx is copied into ps_rt for its
119 !> ghost exchange when the band closes
120 double precision, allocatable :: rtw_chib(:,:,:), rtw_bb(:,:,:), rtw_fx(:,:,:)
121 !> The band blocks of this rank with their block position (bi, bj), the block rows of the
122 !> current band and its longest diagonal, and the wrap and seam modes of the KBA
124 integer, allocatable :: wv_ig(:), wv_bi(:), wv_bj(:)
125 logical :: wv_xwrap
126 ! True when the lagged wrap applies, which needs the distributed x-sweep and a periodic domain
127 logical :: wv_seam
128 !> Ray cosines along the RT grid axes (hdim, updim). They are (mux, muy) for updim = 2 and the
129 !> swapped pair for updim = 1
130 double precision, allocatable :: mu_h(:), mu_v(:)
131
132 ! The axes, band edges and readiness flag, all resolved in code units by rt_sc_setup
133 integer :: updim = 2, hdim = 1
135 logical :: rt_sc_ready = .false.
136 !> The RT grid on rt_sc_amr_level along (hdim, updim): cells across the domain, cells per block,
137 !> blocks across the width, cell sizes and the lower domain edges, with the cell and block
138 !> rows of each band
139 integer :: rg_nh, rg_nv, rg_bh, rg_bv, rg_nbh
140 double precision :: rg_dh, rg_dv, rg_hlo, rg_vlo
142 !> Unit steps of hdim and updim in block index space and the block index ranges along them, so
143 !> that a loop written in (h, v) serves either stratification axis
144 integer :: eh(2), ev(2)
146
147 namelist /rt_list/ rt_sc_updim, rt_sc_amr_level, rt_sc_nband, &
154
155 public :: rt_sc_params_read
156 public :: rt_sc_setup
157 public :: rt_sc_reserve_slots
158 public :: rt_sc_init
159
160contains
161
162 !> Read &rt_list from each parameter file. The values stay physical until rt_sc_setup, and a
163 !> file without the namelist is passed over
164 subroutine rt_sc_params_read(files)
166 character(len=*), intent(in) :: files(:)
167 integer :: n
168 do n = 1, size(files)
169 open(unitpar, file=trim(files(n)), status="old")
170 read(unitpar, rt_list, end=222)
171222 close(unitpar)
172 end do
173 end subroutine rt_sc_params_read
174
175 !> Check the geometry, convert the parameters to code units, resolve the bands and the boundary
176 !> conditions, and bind rt_sc_chiB to the chosen opacity. Runs after the unit system is fixed
177 subroutine rt_sc_setup()
181 use mod_comm_lib, only: mpistop
182 integer :: ib, fac
183 integer :: dnx(ndim), bnx(ndim), mlo(ndim), mhi(ndim), glo(ndim), ghi(ndim)
184 double precision :: dlo(ndim), dhi(ndim), hi_req
185 if(.not. rt_sc_active) return
187 ! The RT grid arithmetic assumes uniform Cartesian cells. All else is rejected for now
188 if(coordinate /= cartesian) then
189 call mpistop("rt_sc_setup: uniform Cartesian only (no stretched grids)")
190 end if
191 if(ndim /= 2) call mpistop("rt_sc_setup: 2D only")
192 if(rt_sc_updim > ndim) call mpistop("rt_sc_setup: bad rt_sc_updim")
193 ! The horizontal axis is whichever of the two is not updim
195 hdim = 3 - updim
197 if(rt_sc_amr_level > refine_max_level) call mpistop("rt_sc_setup: rt_sc_amr_level above refine_max_level")
198 if(rt_sc_nband < 1) rt_sc_nband = 1
199 if(rt_sc_nband > rt_sc_maxband) call mpistop("rt_sc_setup: rt_sc_nband above rt_sc_maxband")
200 ! The distributed wave keeps its intensity in slots that rt_sc_activate reserves
201 if(rt_sc_distributed .and. i_isw < 0) call mpistop("rt_sc_setup: call rt_sc_activate first")
202 ! The RT grid along (hdim, updim). The horizontal direction splits into whole blocks, since
203 ! AMRVAC requires domain_nx to be a multiple of block_nx
204 {dlo(^d)=xprobmin^d; dhi(^d)=xprobmax^d; dnx(^d)=domain_nx^d; bnx(^d)=block_nx^d;}
205 fac = 2**(rt_sc_amr_level-1)
206 rg_nh = dnx(hdim)*fac; rg_nv = dnx(updim)*fac
207 rg_bh = bnx(hdim); rg_bv = bnx(updim)
209 rg_hlo = dlo(hdim); rg_vlo = dlo(updim)
210 rg_dh = (dhi(hdim) -dlo(hdim)) /dble(rg_nh)
211 rg_dv = (dhi(updim)-dlo(updim))/dble(rg_nv)
212 {mlo(^d)=ixmlo^d; mhi(^d)=ixmhi^d; glo(^d)=ixglo^d; ghi(^d)=ixghi^d;}
213 eh = 0; eh(hdim) = 1
214 ev = 0; ev(updim) = 1
215 imlo_h = mlo(hdim); imhi_h = mhi(hdim); iglo_h = glo(hdim); ighi_h = ghi(hdim)
216 imlo_v = mlo(updim); imhi_v = mhi(updim); iglo_v = glo(updim); ighi_v = ghi(updim)
217 ! The band edges go to code units, and the 1e30 sentinels resolve to the domain ends
218 do ib = 1, rt_sc_nband
219 band_lo_c(ib) = merge(dlo(updim), rt_sc_band_min(ib)/unit_length, rt_sc_band_min(ib) <= -1.0d29)
220 band_hi_c(ib) = merge(dhi(updim), rt_sc_band_max(ib)/unit_length, rt_sc_band_max(ib) >= 1.0d29)
221 if(band_hi_c(ib) <= band_lo_c(ib)) call mpistop("rt_sc_setup: band top not above its bottom")
222 end do
223 ! The KBA needs every band to tile into whole blocks along updim, so its top is snapped down to
224 ! the last block edge below the requested height, and everything downstream reads band_hi_c.
225 ! It never moves up, which could leave the domain or reach blocks the refinement pin has not
226 ! refined
227 do ib = 1, rt_sc_nband
228 hi_req = band_hi_c(ib)
229 ! Integer division counts only the whole blocks that fit in the requested band
230 ! nbv = floor(ncells/bv), band_hi = band_lo + nbv bv dv
231 band_nbv(ib) = nint((band_hi_c(ib)-band_lo_c(ib))/rg_dv)/rg_bv
232 if(band_nbv(ib) < 1) call mpistop("rt_sc_setup: band thinner than one block along updim")
233 band_nv(ib) = band_nbv(ib)*rg_bv
234 band_hi_c(ib) = band_lo_c(ib) + dble(band_nv(ib))*rg_dv
235 if(mype==0 .and. dabs(hi_req-band_hi_c(ib)) > 1.0d-10*dabs(rg_dv)) then
236 write(*,'(a,i2,a,es13.6,a,es13.6,a,i0,a,i0,a)') &
237 ' rt_sc_setup: band ', ib, ' top snapped ', hi_req*unit_length, &
238 ' -> ', band_hi_c(ib)*unit_length, ' cm (', band_nbv(ib), ' blocks of ', rg_bv, ' cells)'
239 end if
240 end do
241 ! The switch pressure is held as a code-unit logarithm, so the cells need no conversion. The
242 ! opacity callback is bound once here, and the table is read only when it is needed
243 rt_sc_lp_tr = dlog10(rt_sc_p_tr/unit_pressure)
244 select case(trim(rt_sc_opacity))
245 case('Rosseland')
246 call read_opacity_table()
247 rt_sc_chib => rt_sc_chib_rosseland
248 case('Kramers')
249 rt_sc_chib => rt_sc_chib_kramers
250 case('usr')
251 if(.not. associated(usr_rt_sc_chib)) &
252 call mpistop("rt_sc_setup: rt_sc_opacity='usr' but usr_rt_sc_chiB not set in mod_usr.t")
253 rt_sc_chib => usr_rt_sc_chib
254 case default
255 call mpistop("rt_sc_setup: unknown rt_sc_opacity (Rosseland, Kramers or usr)")
256 end select
257 ! The horizontal edges wrap only where the domain is periodic, and otherwise take the inflow
258 ! conditions given in &rt_list
259 bc_h_periodic = periodb(hdim)
260 bc_hlo_thermal = (trim(rt_sc_bc_hmin) == 'thermal')
261 bc_hhi_thermal = (trim(rt_sc_bc_hmax) == 'thermal')
262 if(mype==0 .and. .not.bc_h_periodic) print *, &
263 'rt_sc_setup: hdim not periodic, inflow BC ', trim(rt_sc_bc_hmin),'/',trim(rt_sc_bc_hmax)
264
265 ! The GL polar nodes are placed about the stratification axis, and the cosines are then mapped
266 ! onto the RT grid axes
267 rt_sc_polar_axis = updim
268 call rt_sc_init()
269 call rt_sc_axis_cosines()
270 rt_sc_ready = .true.
271 if(mype==0) print *, "rt_sc_setup: done. updim=",updim," level=",rt_sc_amr_level, &
272 " nband=",rt_sc_nband," opacity=",trim(rt_sc_opacity)
273 end subroutine rt_sc_setup
274
275 !> Map the quadrature onto the RT grid axes (hdim, updim). Called after rt_sc_init
277 if(allocated(mu_h)) deallocate(mu_h, mu_v)
278 allocate(mu_h(rt_sc_nray), mu_v(rt_sc_nray))
279 if(hdim == 1) then
280 mu_h = mux; mu_v = muy
281 else
282 mu_h = muy; mu_v = mux
283 end if
284 end subroutine rt_sc_axis_cosines
285
286 !> Block indices (i1, i2) of the cell at position ih along hdim and iv along updim
287 pure subroutine hv(ih, iv, i1, i2)
288 integer, intent(in) :: ih, iv
289 integer, intent(out) :: i1, i2
290 i1 = eh(1)*ih + ev(1)*iv
291 i2 = eh(2)*ih + ev(2)*iv
292 end subroutine hv
293
294 !> Reserve the wavefront intensity slots in ps_rt, four in all, one per sweep corner, of which
295 !> the ray-by-ray wave uses only the first. Called from rt_sc_activate, and does nothing
296 !> unless rt_sc_distributed is set
298 if(.not. rt_sc_distributed) return
299 ! A second call leaves the reservation as it is
300 if(i_isw > 0) return
301 ! The slots are the first columns of ps_rt, which is separate from the hydro state
302 nisw = 4
303 i_isw = 1
304 end subroutine rt_sc_reserve_slots
305
306 !> Allocate ps_rt(igrid)%w on every active block and zero it, sharing the geometry of ps, which
307 !> getbc reads. With bcphys off only %w is exchanged. Blocks created by a regrid get their state
308 !> at the next solve, and blocks that go inactive keep it until they are reused
309 subroutine rt_sc_alloc_state()
311 integer :: iigrid, igrid
312 if(.not.allocated(ps_rt)) allocate(ps_rt(max_blocks))
313 do iigrid=1,igridstail; igrid=igrids(iigrid)
314 ! A block whose state was sized for a different nw is allocated afresh
315 if(allocated(ps_rt(igrid)%w)) then
316 if(size(ps_rt(igrid)%w,ndim+1) /= nw) deallocate(ps_rt(igrid)%w)
317 end if
318 if(.not.allocated(ps_rt(igrid)%w)) allocate(ps_rt(igrid)%w(ixg^t,1:nw))
319 ! The state is zeroed every solve, because getbc with bcphys off never fills the
320 ! physical-boundary ghosts, which would otherwise keep stale values
321 ps_rt(igrid)%w = 0.0d0
322 ps_rt(igrid)%igrid = igrid
323 ps_rt(igrid)%level = node(plevel_,igrid)
324 ! The geometry points at the hydro block rather than being copied
325 {ps_rt(igrid)%ixGmin^d = ixglo^d; ps_rt(igrid)%ixGmax^d = ixghi^d;}
326 ps_rt(igrid)%x => ps(igrid)%x
327 ps_rt(igrid)%dvolume => ps(igrid)%dvolume
328 ps_rt(igrid)%is_physical_boundary=> ps(igrid)%is_physical_boundary
329 end do
330 end subroutine rt_sc_alloc_state
331
332 !> Allocate the seam buffers once, or again when the row or ray count changes, and zero the
333 !> buffers written this solve
334 subroutine rt_sc_seam_alloc(dnxv, nray)
335 integer, intent(in) :: dnxv, nray
336 if(allocated(rt_sc_seaml_prev)) then
337 if(size(rt_sc_seaml_prev,1)/=dnxv .or. size(rt_sc_seaml_prev,2)/=nray) &
339 end if
340 ! The previous edges start at zero, so the first solve sees no seam inflow
341 if(.not.allocated(rt_sc_seaml_prev)) then
342 allocate(rt_sc_seaml_prev(dnxv,nray), rt_sc_seamr_prev(dnxv,nray), &
343 rt_sc_seaml_cur(dnxv,nray), rt_sc_seamr_cur(dnxv,nray))
344 rt_sc_seaml_prev = 0.0d0; rt_sc_seamr_prev = 0.0d0
345 end if
346 rt_sc_seaml_cur = 0.0d0; rt_sc_seamr_cur = 0.0d0
347 end subroutine rt_sc_seam_alloc
348
349 !> Sum the seam edges of this solve over the ranks, where each edge has a single owner, and keep
350 !> them for the next solve
351 subroutine rt_sc_seam_finalize(dnxv, nray)
353 integer, intent(in) :: dnxv, nray
354 integer :: ierr
355 call mpi_allreduce(mpi_in_place, rt_sc_seaml_cur, dnxv*nray, mpi_double_precision, mpi_sum, icomm, ierr)
356 call mpi_allreduce(mpi_in_place, rt_sc_seamr_cur, dnxv*nray, mpi_double_precision, mpi_sum, icomm, ierr)
359 end subroutine rt_sc_seam_finalize
360
361 !> In-place sum allreduce of a 2D array in chunks of whole columns of about 1 MB
362 subroutine rt_allreduce_chunk(a, n1, n2, comm)
364 integer, intent(in) :: n1, n2, comm
365 double precision, intent(inout) :: a(n1,n2)
366 integer :: j0, j1, nc, ierr
367 ! 131072 doubles make 1 MB, so nc whole columns fit in one chunk
368 nc = max(1, 131072/max(n1,1))
369 j0 = 1
370 do while(j0 <= n2)
371 j1 = min(j0+nc-1, n2)
372 call mpi_allreduce(mpi_in_place, a(1,j0), n1*(j1-j0+1), mpi_double_precision, mpi_sum, comm, ierr)
373 j0 = j1 + 1
374 end do
375 end subroutine rt_allreduce_chunk
376end module mod_rt_sc_state
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Module with geometry-related routines (e.g., divergence, curl).
Definition mod_geometry.t:2
integer coordinate
Definition mod_geometry.t:7
integer, parameter cartesian
Definition mod_geometry.t:8
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer ixghi
Upper index of grid block arrays.
integer domain_nx
number of cells for each dimension in level-one mesh
integer, parameter unitpar
file handle for IO
double precision unit_pressure
Physical scaling factor for pressure.
integer, parameter ndim
Number of spatial dimensions for grid variables.
double precision unit_length
Physical scaling factor for length.
integer icomm
The MPI communicator.
integer mype
The rank of the current MPI task.
integer block_nx
number of cells for each dimension in grid block excluding ghostcells
double precision, dimension(:), allocatable, parameter d
logical, dimension(ndim) periodb
True for dimensions with periodic boundaries.
integer refine_max_level
Maximal number of AMR levels.
integer max_blocks
The maximum number of grid blocks in a processor.
integer, dimension(:,:), allocatable node
integer, parameter ixglo
Lower index of grid block arrays (always 1).
Transport kernel of the short-characteristics (SC) radiative transfer.
subroutine rt_sc_init()
Build the quadrature into mux, muy, muz and wmu as full 3D cosines, according to rt_sc_quad.
integer, public rt_sc_ndir
Azimuthal directions and polar nodes of the GL set, with nmu one of 2, 4, 6 or 8.
double precision, public rt_sc_blend_k
Weight of the heating blend, w = exp(-blend_k tau), and the scale of the taper tau^2/(tau^2 + tau_min...
character(len=16), public rt_sc_quad
The angular quadrature, either 'GL' (Gauss-Legendre polar nodes times equally spaced azimuths) or 'Ca...
double precision, public rt_sc_tau_min
integer, public rt_sc_nmu
Opacity and Planck source of the short-characteristics (SC) radiative transfer.
double precision, public rt_sc_dtcap
double precision, public rt_sc_dp_tr
double precision, public rt_sc_tcap
The built-in opacities keep the SC transfer on where the gas is cool (T < Tcap) or dense (p > p_TR),...
character(len=std_len), public rt_sc_kappa_table
The Rosseland table file, read in rt_sc_setup when the table model is chosen.
double precision, public rt_sc_p_tr
character(len=10), public rt_sc_opacity
The opacity model, either 'Rosseland' (the table), 'Kramers' (the analytic fit) or 'usr',...
Parameters, resolved state and lifecycle of the short-characteristics (SC) radiative transfer,...
integer i_isw
First column of the ray intensity in ps_rt, and -1 until reserved. It is the only field getbc exchang...
integer, public i_frad
double precision rg_dh
subroutine rt_sc_alloc_state()
Allocate ps_rt(igrid)w on every active block and zero it, sharing the geometry of ps,...
double precision, dimension(:), allocatable mu_h
Ray cosines along the RT grid axes (hdim, updim). They are (mux, muy) for updim = 2 and the swapped p...
integer, public rt_sc_nband
double precision, dimension(:,:,:), allocatable rtw_bb
subroutine rt_sc_seam_finalize(dnxv, nray)
Sum the seam edges of this solve over the ranks, where each edge has a single owner,...
double precision, dimension(:), allocatable mu_v
integer, dimension(rt_sc_maxband) band_nv
integer rt_node_comm
Node-local communicator for the moment reduction of the gather. The ranks reach that reduction far ou...
logical, public rt_sc_distributed
The distributed KBA wavefront. Each rank sweeps only its own band blocks, one diagonal at a time,...
double precision, dimension(:,:), allocatable rt_sc_seaml_prev
integer, public rt_sc_amr_level
The AMR level the RT runs on. The bands are held at this level so that the RT sees a uniform grid,...
logical rt_sc_seam_warned
double precision, public rt_wt_swp
double precision, public rt_sc_ftau1
Horizontal mean of the flux on the tau = rt_sc_tau_emergent surface, from rt_sc_emergent_tau1....
integer, public rt_nsolve
double precision, public rt_wt_wave
character(len=10), public rt_sc_bc_hmax
integer, dimension(2) eh
Unit steps of hdim and updim in block index space and the block index ranges along them,...
logical, public rt_sc_active
True when the physics module has switched the RT on, with hd_radiative_transfer or mhd_radiative_tran...
integer, dimension(rt_sc_maxband) band_nbv
logical, public rt_sc_flux_blend
rt_sc_flux_blend blends the thin heating c chi (J - B) with the thick -div F. rt_sc_cfl limits the he...
integer rg_nh
The RT grid on rt_sc_amr_level along (hdim, updim): cells across the domain, cells per block,...
double precision, dimension(rt_sc_maxband), public rt_sc_band_min
double precision, dimension(:,:,:), allocatable rtw_fx
double precision, dimension(:,:), allocatable rt_sc_seamr_cur
logical rt_sc_seam_on
The periodic seam of the single-pass KBA. A ray crossing the seam takes as its inflow the outflow at ...
subroutine, public rt_sc_reserve_slots()
Reserve the wavefront intensity slots in ps_rt, four in all, one per sweep corner,...
integer, dimension(:), allocatable wv_ig
double precision, dimension(rt_sc_maxband), public rt_sc_band_max
subroutine, public rt_sc_setup()
Check the geometry, convert the parameters to code units, resolve the bands and the boundary conditio...
double precision, public rt_sc_fi_thresh
Not read by the RT itself. The user files set it from eoseint_rho_FI_threshold for their own SC sourc...
subroutine rt_allreduce_chunk(a, n1, n2, comm)
In-place sum allreduce of a 2D array in chunks of whole columns of about 1 MB.
double precision, public rt_wt_red
integer nisw
Number of intensity slots, one for the ray-by-ray wave and up to four when pipelined.
integer, dimension(:), allocatable wv_bi
integer rt_lead_comm
Communicator of one leader rank per node. The field gather sums within each node, then over the leade...
double precision rg_vlo
double precision, public rt_sc_cfl
integer, public rt_sc_updim
Axis of the stratification, 1 for x and 2 for y. The default of -1 takes the last axis.
subroutine rt_sc_seam_alloc(dnxv, nray)
Allocate the seam buffers once, or again when the row or ray count changes, and zero the buffers writ...
integer, public i_iout
character(len=10), dimension(rt_sc_maxband), public rt_sc_bc_min
character(len=10), public rt_sc_bc_hmin
Incoming intensity at the horizontal edges where they are not periodic, 'open' for I = 0 or 'thermal'...
double precision, dimension(:,:,:), allocatable rtw_chib
Block chi and B including the ghosts, rebuilt every solve, and the block horizontal flux Fx for the -...
pure subroutine hv(ih, iv, i1, i2)
Block indices (i1, i2) of the cell at position ih along hdim and iv along updim.
double precision, public rt_wt_gath
Cumulative wall time of the field gather, the sweep, the moment reduction and the scatter,...
type(state), dimension(:), allocatable, target ps_rt
The RT intensity state. It is kept out of the hydro w so that it skips the stage copies,...
subroutine rt_sc_axis_cosines()
Map the quadrature onto the RT grid axes (hdim, updim). Called after rt_sc_init.
double precision, public rt_wt_scat
integer, public i_qrad
Extra-variable indices of the heating Q, the vertical flux F and the emergent intensity Iout,...
logical, public rt_sc_pipeline
The pipelined KBA. The four sweep corners run at once, each with its own intensity slot,...
double precision, public rt_sc_blend_dt
double precision, dimension(:,:), allocatable rt_sc_seamr_prev
double precision rg_dv
integer, parameter rt_sc_maxband
The RT bands along updim, of which a bar with a photosphere at each end needs two....
integer wv_nblk
The band blocks of this rank with their block position (bi, bj), the block rows of the current band a...
double precision, dimension(rt_sc_maxband) band_lo_c
integer, dimension(:), allocatable wv_bj
double precision, public rt_sc_tau_emergent
character(len=10), dimension(rt_sc_maxband), public rt_sc_bc_max
logical, public rt_sc_debug
Prints the cumulative RT timing every 10 solves.
subroutine, public rt_sc_params_read(files)
Read &rt_list from each parameter file. The values stay physical until rt_sc_setup,...
double precision rg_hlo
double precision, dimension(rt_sc_maxband) band_hi_c
logical, public rt_sc_valpipe
For validation, runs the ray-by-ray and pipelined waves on the same state and prints max|dQ|.
double precision, dimension(:,:), allocatable rt_sc_seaml_cur
double precision, public rt_sc_blend_t0
Centre and half-width in K of the temperature gate in rt_sc_thin_weight, which divides the radiative ...
integer, dimension(2) ev
Module with all the methods that users can customize in AMRVAC.
procedure(sub_rt_sc_chib), pointer usr_rt_sc_chib
opacity and Planck source for the SC RT when rt_sc_opacity = 'usr'