56 double precision,
allocatable,
public ::
mux(:),
muy(:),
muz(:),
wmu(:)
59 double precision,
allocatable,
public ::
chi_g(:,:),
b_g(:,:),
jm_g(:,:),
ii_g(:,:),
q_g(:,:)
60 double precision,
allocatable,
public ::
fx_g(:,:),
fy_g(:,:),
tau_g(:,:)
62 integer,
public ::
nxg = -1,
nyg = -1
67 double precision,
allocatable ::
chi_p(:,:),
b_p(:,:),
i_p(:,:)
74 double precision,
intent(in) :: a
75 ray_sign = merge(1, 0, a > 0.0d0) - merge(1, 0, a < 0.0d0)
84 case(
'Carlson',
'carlson')
100 double precision,
allocatable :: nx(:), ny(:), nz(:), wsum(:)
101 logical,
allocatable :: gone(:)
102 integer :: k, j, nnew
104 double precision,
parameter :: tol = 1.0
d-12
107 gone = .false.; nnew = 0
113 nx(nnew) =
mux(k); ny(nnew) =
muy(k); nz(nnew) =
muz(k); wsum(nnew) =
wmu(k)
117 if(abs(
mux(j)-
mux(k)) < tol .and. abs(
muy(j)-
muy(k)) < tol)
then
118 wsum(nnew) = wsum(nnew) +
wmu(j); gone(j) = .true.
126 mux = nx(1:nnew);
muy = ny(1:nnew);
muz = nz(1:nnew);
wmu = wsum(1:nnew)
127 if(
mype==0) print *,
"rt_sc_dedup_rays: (mux,muy) rays",
rt_sc_nray,
"->", nnew,
" (2D-identical merged)"
130 deallocate(nx, ny, nz, wsum, gone)
137 integer :: im, ip, k, nmu, nphi
138 double precision :: phi, s, mu, xmu(8), wgl(8)
151 s = dsqrt(max(1.0d0 - mu*mu, 0.0d0))
154 phi = 2.0d0*dpi*(dble(ip)-0.5d0)/dble(nphi)
158 muy(k) = mu;
mux(k) = s*dcos(phi)
160 mux(k) = mu;
muy(k) = s*dcos(phi)
165 wmu(k) = 0.5d0*wgl(im)/dble(nphi)
175 double precision,
parameter :: m1 = 0.88191710d0, m2 = 0.33333333d0
176 double precision :: base(3,3)
177 integer :: ib, sgx, sgy, sgz, k
179 base(:,1) = (/ m1, m2, m2 /)
180 base(:,2) = (/ m2, m1, m2 /)
181 base(:,3) = (/ m2, m2, m1 /)
188 do sgz = -1, 1, 2;
do sgy = -1, 1, 2;
do sgx = -1, 1, 2
192 mux(k) = sgx*base(1,ib);
muy(k) = sgy*base(2,ib);
muz(k) = sgz*base(3,ib)
193 wmu(k) = 1.0d0/24.0d0
195 end do;
end do;
end do
201 integer,
intent(inout) :: n
202 double precision,
intent(out) :: x(8), w(8)
209 x(1:2) = (/-0.5773502691896257d0, 0.5773502691896257d0/)
210 w(1:2) = (/ 1.0000000000000000d0, 1.0000000000000000d0/)
213 x(1:4) = (/-0.8611363115940526d0,-0.3399810435848563d0, 0.3399810435848563d0, 0.8611363115940526d0/)
214 w(1:4) = (/ 0.3478548451374538d0, 0.6521451548625461d0, 0.6521451548625461d0, 0.3478548451374538d0/)
217 x(1:6) = (/-0.9324695142031521d0,-0.6612093864662645d0,-0.2386191860831969d0, &
218 0.2386191860831969d0, 0.6612093864662645d0, 0.9324695142031521d0/)
219 w(1:6) = (/ 0.1713244923791704d0, 0.3607615730481386d0, 0.4679139345726910d0, &
220 0.4679139345726910d0, 0.3607615730481386d0, 0.1713244923791704d0/)
223 x(1:8) = (/-0.9602898564975363d0,-0.7966664774136267d0,-0.5255324099163290d0,-0.1834346424956498d0, &
224 0.1834346424956498d0, 0.5255324099163290d0, 0.7966664774136267d0, 0.9602898564975363d0/)
225 w(1:8) = (/ 0.1012285362903763d0, 0.2223810344533745d0, 0.3137066458778873d0, 0.3626837833783620d0, &
226 0.3626837833783620d0, 0.3137066458778873d0, 0.2223810344533745d0, 0.1012285362903763d0/)
234 pure double precision function blend_heating(chi, jm, bpl, divf, tau)
result(q)
236 double precision,
intent(in) :: chi, jm, bpl, divf, tau
237 double precision :: w
249 integer :: i, j, ip, im
250 double precision :: divf
269 ip = i+1;
if(ip>
nxg) ip=1
270 im = i-1;
if(im<1) im=
nxg
273 ip = min(i+1,
nxg); im = max(i-1,1)
281 divf = divf + (
fy_g(i,j+1)-
fy_g(i,j-1))/(2.0d0*
dyg)
290 if(
allocated(
chi_g))
then
294 allocate(
chi_g(
nxg,
nyg),
b_g(
nxg,
nyg),
jm_g(
nxg,
nyg),
ii_g(
nxg,
nyg),
q_g(
nxg,
nyg), &
304 if(
allocated(
chi_p))
then
332 double precision,
intent(in) :: nx, ny
335 call sc_sweep_block(nx, ny,
dxg,
dyg, .true., 0,0,
nxg+1,
nyg+1, 1,1,
nxg,
nyg,
chi_p,
b_p,
i_p)
341 double precision,
intent(in) :: dtau
342 double precision,
intent(out) :: ex, psi0, psiu
343 double precision :: w0, w1
345 if(dtau <= 1.0d-10)
then
346 ex = 1.0d0; psi0 = 0.0d0; psiu = 0.0d0;
return
355 if(dtau > 1.0d-4)
then
360 w0 = dtau - dtau*dtau*0.5d0 + dtau*dtau*dtau/6.0d0
361 w1 = dtau*dtau*0.5d0 - dtau*dtau*dtau/3.0d0
376 double precision,
intent(in) :: nx, ny, dxb, dyb
377 logical,
intent(in) :: xwrap
378 integer,
intent(in) :: ixI^L, ixO^L
379 double precision,
intent(in) :: chi(ixI^S), bpl(ixI^S)
380 double precision,
intent(inout) :: ii(ixI^S)
381 integer :: i, j, sx, sy, nxper
382 double precision :: absnx, absny, ds, frac
383 absnx = dabs(nx); absny = dabs(ny)
386 nxper = ixomax1 - ixomin1 + 1
391 if(absnx*dyb >= absny*dxb)
then
393 ds = dxb/max(absnx,smalldouble); frac = (dxb/dyb)*absny/max(absnx,smalldouble)
395 do i = ixomin1, ixomax1;
call sweep_column(i);
end do
397 do i = ixomax1, ixomin1, -1;
call sweep_column(i);
end do
401 ds = dyb/max(absny,smalldouble); frac = (dyb/dxb)*absnx/max(absny,smalldouble)
403 do j = ixomin2, ixomax2;
call sweep_row(j);
end do
405 do j = ixomax2, ixomin2, -1;
call sweep_row(j);
end do
411 integer,
intent(in) :: i
414 if(iu<ixomin1) iu=iu+nxper
415 if(iu>ixomax1) iu=iu-nxper
418 subroutine sweep_column(i)
419 integer,
intent(in) :: i
422 do j = ixomin2, ixomax2
423 call step(i, j, iu, j, iu, j-sy)
425 end subroutine sweep_column
426 subroutine sweep_row(j)
427 integer,
intent(in) :: j
429 do i = ixomin1, ixomax1
430 call step(i, j, i, j-sy,
upwind_x(i), j-sy)
432 end subroutine sweep_row
436 subroutine step(i, j, ia, ja, iu, ju)
437 integer,
intent(in) :: i, j, ia, ja, iu, ju
438 double precision :: in_a, in_b, iu_val, chiu, bu, dtau, ex, psi0, psiu
444 if( (iu<ixomin1 .or. iu>ixomax1) .and. (ju<ixomin2 .or. ju>ixomax2) )
then
446 in_b = 0.5d0*(ii(iu,j) + ii(i,ju))
451 iu_val = (1.0d0-frac)*in_a + frac*in_b
452 chiu = (1.0d0-frac)*chi(ia,ja) + frac*chi(iu,ju)
453 bu = (1.0d0-frac)*bpl(ia,ja) + frac*bpl(iu,ju)
455 dtau = 0.5d0*(chiu + chi(i,j))*ds
457 ii(i,j) = iu_val*ex + bpl(i,j)*psi0 + bu*psiu
integer function upwind_x(i)
x-upwind index of column i, wrapped in place when the block spans the periodic domain
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer mype
The rank of the current MPI task.
double precision, dimension(:), allocatable, parameter d
double precision c_norm
Normalised speed of light.
Transport kernel of the short-characteristics (SC) radiative transfer.
integer, public rt_sc_polar_axis
Stratification axis (1 = x, 2 = y), set by the driver before rt_sc_init. The GL set places its polar ...
subroutine build_gl()
Product Gauss-Legendre set, with nmu polar nodes about rt_sc_polar_axis and ndir azimuths at the midp...
double precision, dimension(:,:), allocatable, public fx_g
subroutine rt_grid_alloc()
Allocate the replicated grid at nxg by nyg, and keep it when its size is unchanged.
subroutine ka_coeffs(dtau, ex, psi0, psiu)
Textbook Olson-Kunasz weights for linear short characteristics over an optical-depth step dtau.
double precision, dimension(:), allocatable, public muy
double precision, public dyg
subroutine rt_sc_dedup_rays()
Merge rays that share (mux, muy) and add up their weights. Since the 2D sweep and the moments see onl...
integer, public rt_sc_nray
double precision, dimension(:,:), allocatable, public ii_g
subroutine rt_sc_heat_blend()
Heating q_g, blending the thin imbalance c chi (J - B) with the thick, conservative -div F through w ...
double precision, dimension(:,:), allocatable, public q_g
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.
pure double precision function blend_heating(chi, jm, bpl, divf, tau)
Heating of one cell. The thin imbalance c chi (J - B) is blended with the thick, conservative -div F ...
double precision, dimension(:,:), allocatable i_p
double precision, dimension(:,:), allocatable, public chi_g
The replicated single-level grid with chi = kappa rho, B = a T^4, the mean intensity J,...
pure integer function ray_sign(a)
Sign of a direction cosine as -1, 0 or 1. The zero case occurs, for example for the GL rays at phi = ...
double precision, dimension(:), allocatable, public wmu
double precision, dimension(:,:), allocatable, public tau_g
double precision, dimension(:), allocatable, public muz
subroutine gauss_legendre_nodes(n, x, w)
Gauss-Legendre nodes and weights on [-1,1] for n in {2,4,6,8}. Any other n is moved up to the next su...
subroutine sc_sweep_2d(nx, ny)
One sweep of the whole replicated grid for direction (nx, ny) into ii_g. The padded grid of sc_pad_gr...
subroutine build_carlson()
Carlson A4 level-symmetric set, built from the three cyclic permutations of (mu1, mu2,...
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...
double precision, dimension(:,:), allocatable, public b_g
double precision, dimension(:,:), allocatable b_p
character(len=16), public rt_sc_quad
The angular quadrature, either 'GL' (Gauss-Legendre polar nodes times equally spaced azimuths) or 'Ca...
subroutine sc_pad_grid()
Pad the replicated grid with one ghost layer for sc_sweep_block, once per band after chi_g and b_g ar...
double precision, public dxg
double precision, dimension(:,:), allocatable, public fy_g
logical, public bc_hhi_thermal
logical, public bc_hlo_thermal
double precision, public rt_sc_tau_min
integer, public rt_sc_nmu
logical, public bc_hi_thermal
double precision, dimension(:), allocatable, public mux
Direction cosines and weights, normalised so that sum(wmu) = 1. In 2D the out-of-plane muz only lengt...
logical, public bc_h_periodic
The horizontal edges wrap when the domain is periodic and otherwise act as inflow boundaries,...
double precision, dimension(:,:), allocatable chi_p
subroutine sc_sweep_block(nx, ny, dxb, dyb, xwrap, ixil, ixol, chi, bpl, ii)
Sweep of one block for ray (nx, ny), the kernel of the wavefront solvers. The upwind face and corner ...
logical, public bc_lo_thermal
Incoming intensity at the lower and upper ends of the current band, thermal (I = B) when set and open...
double precision, dimension(:,:), allocatable, public jm_g