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 !> Sweep corners the pipelined wave runs at once, each with an even and an odd slot
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 use mod_eos, only: eos
183 integer :: ib, fac
184 integer :: dnx(ndim), bnx(ndim), mlo(ndim), mhi(ndim), glo(ndim), ghi(ndim)
185 double precision :: dlo(ndim), dhi(ndim), hi_req
186 if(.not. rt_sc_active) return
188 ! The RT grid arithmetic assumes uniform Cartesian cells. All else is rejected for now
189 if(coordinate /= cartesian) then
190 call mpistop("rt_sc_setup: uniform Cartesian only (no stretched grids)")
191 end if
192 if(ndim /= 2) call mpistop("rt_sc_setup: 2D only")
193 if(rt_sc_updim > ndim) call mpistop("rt_sc_setup: bad rt_sc_updim")
194 ! The horizontal axis is whichever of the two is not updim
196 hdim = 3 - updim
198 if(rt_sc_amr_level > refine_max_level) call mpistop("rt_sc_setup: rt_sc_amr_level above refine_max_level")
199 if(rt_sc_nband < 1) rt_sc_nband = 1
200 if(rt_sc_nband > rt_sc_maxband) call mpistop("rt_sc_setup: rt_sc_nband above rt_sc_maxband")
201 ! The distributed wave keeps its intensity in slots that rt_sc_activate reserves
202 if(rt_sc_distributed .and. i_isw < 0) call mpistop("rt_sc_setup: call rt_sc_activate first")
203 ! The RT grid along (hdim, updim). The horizontal direction splits into whole blocks, since
204 ! AMRVAC requires domain_nx to be a multiple of block_nx
205 {dlo(^d)=xprobmin^d; dhi(^d)=xprobmax^d; dnx(^d)=domain_nx^d; bnx(^d)=block_nx^d;}
206 fac = 2**(rt_sc_amr_level-1)
207 rg_nh = dnx(hdim)*fac; rg_nv = dnx(updim)*fac
208 rg_bh = bnx(hdim); rg_bv = bnx(updim)
210 rg_hlo = dlo(hdim); rg_vlo = dlo(updim)
211 rg_dh = (dhi(hdim) -dlo(hdim)) /dble(rg_nh)
212 rg_dv = (dhi(updim)-dlo(updim))/dble(rg_nv)
213 {mlo(^d)=ixmlo^d; mhi(^d)=ixmhi^d; glo(^d)=ixglo^d; ghi(^d)=ixghi^d;}
214 eh = 0; eh(hdim) = 1
215 ev = 0; ev(updim) = 1
216 imlo_h = mlo(hdim); imhi_h = mhi(hdim); iglo_h = glo(hdim); ighi_h = ghi(hdim)
217 imlo_v = mlo(updim); imhi_v = mhi(updim); iglo_v = glo(updim); ighi_v = ghi(updim)
218 ! The band edges go to code units, and the 1e30 sentinels resolve to the domain ends
219 do ib = 1, rt_sc_nband
220 band_lo_c(ib) = merge(dlo(updim), rt_sc_band_min(ib)/unit_length, rt_sc_band_min(ib) <= -1.0d29)
221 band_hi_c(ib) = merge(dhi(updim), rt_sc_band_max(ib)/unit_length, rt_sc_band_max(ib) >= 1.0d29)
222 if(band_hi_c(ib) <= band_lo_c(ib)) call mpistop("rt_sc_setup: band top not above its bottom")
223 end do
224 ! The KBA needs every band to tile into whole blocks along updim, so its top is snapped down to
225 ! the last block edge below the requested height, and everything downstream reads band_hi_c.
226 ! It never moves up, which could leave the domain or reach blocks the refinement pin has not
227 ! refined
228 do ib = 1, rt_sc_nband
229 hi_req = band_hi_c(ib)
230 ! Integer division counts only the whole blocks that fit in the requested band
231 ! nbv = floor(ncells/bv), band_hi = band_lo + nbv bv dv
232 band_nbv(ib) = nint((band_hi_c(ib)-band_lo_c(ib))/rg_dv)/rg_bv
233 if(band_nbv(ib) < 1) call mpistop("rt_sc_setup: band thinner than one block along updim")
234 band_nv(ib) = band_nbv(ib)*rg_bv
235 band_hi_c(ib) = band_lo_c(ib) + dble(band_nv(ib))*rg_dv
236 if(mype==0 .and. dabs(hi_req-band_hi_c(ib)) > 1.0d-10*dabs(rg_dv)) then
237 write(*,'(a,i2,a,es13.6,a,es13.6,a,i0,a,i0,a)') &
238 ' rt_sc_setup: band ', ib, ' top snapped ', hi_req*unit_length, &
239 ' -> ', band_hi_c(ib)*unit_length, ' cm (', band_nbv(ib), ' blocks of ', rg_bv, ' cells)'
240 end if
241 end do
242 ! The switch pressure is held as a code-unit logarithm, so the cells need no conversion. The
243 ! opacity callback is bound once here, and the table is read only when it is needed
244 rt_sc_lp_tr = dlog10(rt_sc_p_tr/unit_pressure)
245 ! The built-in opacities and the Planck source are evaluated from the temperature and density of
246 ! the equation of state, which only the LTE closure ties to an ionisation balance. Under FI or PI
247 ! they describe no real gas, so only a user opacity is accepted there
248 if(trim(rt_sc_opacity) /= 'usr' .and. trim(eos%eos_type) /= 'LTE') call mpistop( &
249 "rt_sc_setup: the built-in opacities need eos_type='LTE'"// &
250 ", with FI or PI set rt_sc_opacity='usr'")
251 select case(trim(rt_sc_opacity))
252 case('Rosseland')
253 call read_opacity_table()
254 rt_sc_chib => rt_sc_chib_rosseland
255 case('Kramers')
256 rt_sc_chib => rt_sc_chib_kramers
257 case('usr')
258 if(.not. associated(usr_rt_sc_chib)) &
259 call mpistop("rt_sc_setup: rt_sc_opacity='usr' but usr_rt_sc_chiB not set in mod_usr.t")
260 rt_sc_chib => usr_rt_sc_chib
261 case default
262 call mpistop("rt_sc_setup: unknown rt_sc_opacity (Rosseland, Kramers or usr)")
263 end select
264 ! The horizontal edges wrap only where the domain is periodic, and otherwise take the inflow
265 ! conditions given in &rt_list
266 bc_h_periodic = periodb(hdim)
267 bc_hlo_thermal = (trim(rt_sc_bc_hmin) == 'thermal')
268 bc_hhi_thermal = (trim(rt_sc_bc_hmax) == 'thermal')
269 if(mype==0 .and. .not.bc_h_periodic) print *, &
270 'rt_sc_setup: hdim not periodic, inflow BC ', trim(rt_sc_bc_hmin),'/',trim(rt_sc_bc_hmax)
271
272 ! The GL polar nodes are placed about the stratification axis, and the cosines are then mapped
273 ! onto the RT grid axes
274 rt_sc_polar_axis = updim
275 call rt_sc_init()
276 call rt_sc_axis_cosines()
277 rt_sc_ready = .true.
278 if(mype==0) print *, "rt_sc_setup: done. updim=",updim," level=",rt_sc_amr_level, &
279 " nband=",rt_sc_nband," opacity=",trim(rt_sc_opacity)
280 end subroutine rt_sc_setup
281
282 !> Map the quadrature onto the RT grid axes (hdim, updim). Called after rt_sc_init
284 if(allocated(mu_h)) deallocate(mu_h, mu_v)
285 allocate(mu_h(rt_sc_nray), mu_v(rt_sc_nray))
286 if(hdim == 1) then
287 mu_h = mux; mu_v = muy
288 else
289 mu_h = muy; mu_v = mux
290 end if
291 end subroutine rt_sc_axis_cosines
292
293 !> Block indices (i1, i2) of the cell at position ih along hdim and iv along updim
294 pure subroutine hv(ih, iv, i1, i2)
295 integer, intent(in) :: ih, iv
296 integer, intent(out) :: i1, i2
297 i1 = eh(1)*ih + ev(1)*iv
298 i2 = eh(2)*ih + ev(2)*iv
299 end subroutine hv
300
301 !> Reserve the wavefront intensity slots in ps_rt. The pipelined wave runs up to nisw sweep
302 !> corners at once with two slots each, within the nw columns of ps_rt, and the ray-by-ray wave
303 !> uses only the first. Called from rt_sc_activate, and does nothing unless rt_sc_distributed
304 !> is set
306 if(.not. rt_sc_distributed) return
307 ! A second call leaves the reservation as it is
308 if(i_isw > 0) return
309 ! The slots are the first columns of ps_rt, which is separate from the hydro state
310 nisw = 4
311 i_isw = 1
312 end subroutine rt_sc_reserve_slots
313
314 !> Allocate ps_rt(igrid)%w on every active block and zero it, sharing the geometry of ps, which
315 !> getbc reads. With bcphys off only %w is exchanged. Blocks created by a regrid get their state
316 !> at the next solve, and blocks that go inactive keep it until they are reused
317 subroutine rt_sc_alloc_state()
319 integer :: iigrid, igrid
320 if(.not.allocated(ps_rt)) allocate(ps_rt(max_blocks))
321 do iigrid=1,igridstail; igrid=igrids(iigrid)
322 ! A block whose state was sized for a different nw is allocated afresh
323 if(allocated(ps_rt(igrid)%w)) then
324 if(size(ps_rt(igrid)%w,ndim+1) /= nw) deallocate(ps_rt(igrid)%w)
325 end if
326 if(.not.allocated(ps_rt(igrid)%w)) allocate(ps_rt(igrid)%w(ixg^t,1:nw))
327 ! The state is zeroed every solve, because getbc with bcphys off never fills the
328 ! physical-boundary ghosts, which would otherwise keep stale values
329 ps_rt(igrid)%w = 0.0d0
330 ps_rt(igrid)%igrid = igrid
331 ps_rt(igrid)%level = node(plevel_,igrid)
332 ! The geometry points at the hydro block rather than being copied
333 {ps_rt(igrid)%ixGmin^d = ixglo^d; ps_rt(igrid)%ixGmax^d = ixghi^d;}
334 ps_rt(igrid)%x => ps(igrid)%x
335 ps_rt(igrid)%dvolume => ps(igrid)%dvolume
336 ps_rt(igrid)%is_physical_boundary=> ps(igrid)%is_physical_boundary
337 end do
338 end subroutine rt_sc_alloc_state
339
340 !> Allocate the seam buffers once, or again when the row or ray count changes, and zero the
341 !> buffers written this solve
342 subroutine rt_sc_seam_alloc(dnxv, nray)
343 integer, intent(in) :: dnxv, nray
344 if(allocated(rt_sc_seaml_prev)) then
345 if(size(rt_sc_seaml_prev,1)/=dnxv .or. size(rt_sc_seaml_prev,2)/=nray) &
347 end if
348 ! The previous edges start at zero, so the first solve sees no seam inflow
349 if(.not.allocated(rt_sc_seaml_prev)) then
350 allocate(rt_sc_seaml_prev(dnxv,nray), rt_sc_seamr_prev(dnxv,nray), &
351 rt_sc_seaml_cur(dnxv,nray), rt_sc_seamr_cur(dnxv,nray))
352 rt_sc_seaml_prev = 0.0d0; rt_sc_seamr_prev = 0.0d0
353 end if
354 rt_sc_seaml_cur = 0.0d0; rt_sc_seamr_cur = 0.0d0
355 end subroutine rt_sc_seam_alloc
356
357 !> Sum the seam edges of this solve over the ranks, where each edge has a single owner, and keep
358 !> them for the next solve
359 subroutine rt_sc_seam_finalize(dnxv, nray)
361 integer, intent(in) :: dnxv, nray
362 integer :: ierr
363 call mpi_allreduce(mpi_in_place, rt_sc_seaml_cur, dnxv*nray, mpi_double_precision, mpi_sum, icomm, ierr)
364 call mpi_allreduce(mpi_in_place, rt_sc_seamr_cur, dnxv*nray, mpi_double_precision, mpi_sum, icomm, ierr)
367 end subroutine rt_sc_seam_finalize
368
369 !> In-place sum allreduce of a 2D array in chunks of whole columns of about 1 MB
370 subroutine rt_allreduce_chunk(a, n1, n2, comm)
372 integer, intent(in) :: n1, n2, comm
373 double precision, intent(inout) :: a(n1,n2)
374 integer :: j0, j1, nc, ierr
375 ! 131072 doubles make 1 MB, so nc whole columns fit in one chunk
376 nc = max(1, 131072/max(n1,1))
377 j0 = 1
378 do while(j0 <= n2)
379 j1 = min(j0+nc-1, n2)
380 call mpi_allreduce(mpi_in_place, a(1,j0), n1*(j1-j0+1), mpi_double_precision, mpi_sum, comm, ierr)
381 j0 = j1 + 1
382 end do
383 end subroutine rt_allreduce_chunk
384end module mod_rt_sc_state
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Equation of state for AMRVAC, handled through a single eos_container object.
Definition mod_eos.t:30
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. The pipelined wave runs up to nisw sweep corners at o...
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
Sweep corners the pipelined wave runs at once, each with an even and an odd slot.
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'