Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fast Formal Integral #2725

Merged
merged 17 commits into from
Jul 23, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
259 changes: 244 additions & 15 deletions tardis/transport/montecarlo/formal_integral_cuda.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,212 @@
H_CGS = 6.62606957e-27


@cuda.jit
def cuda_vector_integrator(L, I_nu, N, R_max):

andrewfullard marked this conversation as resolved.
Show resolved Hide resolved
nu_idx = cuda.grid(1)
L[nu_idx] = (

Check warning on line 19 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L18-L19

Added lines #L18 - L19 were not covered by tests
8 * M_PI * M_PI * trapezoid_integration_cuda(I_nu[nu_idx], R_max / N)
)

@cuda.jit
def cuda_formal_integral_fast(
r_inner,
r_outer,
time_explosion,
line_list_nu,
iT,
inu,
inu_size,
att_S_ul,
Jred_lu,
Jblue_lu,
tau_sobolev,
electron_density,
N,
pp,
exp_tau,
I_nu,
z,
shell_id,
):
"""
The CUDA version of numba_formal_integral that can run
on a NVIDIA GPU.

Parameters
----------
r_inner : array(float64, 1d, C)
self.geometry.r_inner
r_outer : array(float64, 1d, C)
self.geometry.r_outer
time_explosion: float64
self.geometry.time_explosion
line_list_nu : array(float64, 1d, A)
self.plasma.line_list_nu
iT : np.float64
andrewfullard marked this conversation as resolved.
Show resolved Hide resolved
inu : np.float64
inu_size : int64
att_S_ul : array(float64, 1d, C)
Jred_lu : array(float64, 1d, C)
Jblue_lu : array(float64, 1d, C)
tau_sobolev : array(float64, 2d, C)
electron_density : array(float64, 1d, C)
N : int64
L : array(float64, 1d, C)
This is where the results will be stored
pp : array(float64, 1d, C)
exp_tau : array(float64, 1d, C)
I_nu array(floatt64, 2d, C)
z : array(float64, 2d, C)
shell_id : array(int64, 2d, C)
"""

# todo: add all the original todos
andrewfullard marked this conversation as resolved.
Show resolved Hide resolved

# global read-only values
size_line, size_shell = tau_sobolev.shape
size_tau = size_line * size_shell
R_ph = r_inner[0] # make sure these are cgs
R_max = r_outer[size_shell - 1]

Check warning on line 82 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L79-L82

Added lines #L79 - L82 were not covered by tests

nu_idx, p_idx = cuda.grid(2) # 2D Cuda Grid, nu x p
p_idx += 1 # Because the iteration starts at 1

Check warning on line 85 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L84-L85

Added lines #L84 - L85 were not covered by tests
# Check to see if CUDA is out of bounds
if nu_idx >= inu_size:
return

Check warning on line 88 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L87-L88

Added lines #L87 - L88 were not covered by tests

if p_idx >= N:
return

Check warning on line 91 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L90-L91

Added lines #L90 - L91 were not covered by tests

# These all have their own version for each thread to avoid race conditions
I_nu_thread = I_nu[nu_idx]
z_thread = z[nu_idx]
shell_id_thread = shell_id[nu_idx]

Check warning on line 96 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L94-L96

Added lines #L94 - L96 were not covered by tests

offset = 0
size_z = 0
idx_nu_start = 0
direction = 0
first = 0
i = 0
p = 0.0
nu_start = 0.0
nu_end = 0.0
nu = 0.0
zstart = 0.0
zend = 0.0
escat_contrib = 0.0
escat_op = 0.0
Jkkp = 0.0
pexp_tau = 0
patt_S_ul = 0
pJred_lu = 0
pJblue_lu = 0
pline = 0

Check warning on line 117 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L98-L117

Added lines #L98 - L117 were not covered by tests

nu = inu[nu_idx]

Check warning on line 119 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L119

Added line #L119 was not covered by tests

# now loop over discrete values along line
andrewfullard marked this conversation as resolved.
Show resolved Hide resolved

escat_contrib = 0.0
p = pp[p_idx]

Check warning on line 124 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L123-L124

Added lines #L123 - L124 were not covered by tests

# initialize z intersections for p values
andrewfullard marked this conversation as resolved.
Show resolved Hide resolved
size_z = populate_z_cuda(

Check warning on line 127 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L127

Added line #L127 was not covered by tests
r_inner, r_outer, time_explosion, p, z_thread, shell_id_thread
)
if p <= R_ph:
I_nu_thread[p_idx] = intensity_black_body_cuda(nu * z_thread[0], iT)

Check warning on line 131 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L130-L131

Added lines #L130 - L131 were not covered by tests
else:
I_nu_thread[p_idx] = 0
nu_start = nu * z_thread[0]
nu_end = nu * z_thread[1]

Check warning on line 135 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L133-L135

Added lines #L133 - L135 were not covered by tests

idx_nu_start = line_search_cuda(line_list_nu, nu_start, size_line)
offset = shell_id_thread[0] * size_line

Check warning on line 138 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L137-L138

Added lines #L137 - L138 were not covered by tests
# start tracking accumulated e-scattering optical depth
zstart = time_explosion / C_INV * (1.0 - z_thread[0])

Check warning on line 140 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L140

Added line #L140 was not covered by tests
# Initialize "pointers"
pline = int(idx_nu_start)
pexp_tau = int(offset + idx_nu_start)
patt_S_ul = int(offset + idx_nu_start)
pJred_lu = int(offset + idx_nu_start)
pJblue_lu = int(offset + idx_nu_start)

Check warning on line 146 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L142-L146

Added lines #L142 - L146 were not covered by tests

# flag for first contribution to integration on current p-ray
first = 1

Check warning on line 149 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L149

Added line #L149 was not covered by tests

# loop over all interactions
for i in range(size_z - 1):
escat_op = electron_density[int(shell_id_thread[i])] * SIGMA_THOMSON
nu_end = (

Check warning on line 154 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L152-L154

Added lines #L152 - L154 were not covered by tests
nu * z_thread[i + 1]
) # +1 is the offset as the original is from z[1:]

nu_end_idx = line_search_cuda(

Check warning on line 158 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L158

Added line #L158 was not covered by tests
line_list_nu, nu_end, len(line_list_nu)
)

for _ in range(max(nu_end_idx - pline, 0)):

Check warning on line 162 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L162

Added line #L162 was not covered by tests
# calculate e-scattering optical depth to next resonance point
zend = time_explosion / C_INV * (1.0 - line_list_nu[pline] / nu)
if first == 1:

Check warning on line 165 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L164-L165

Added lines #L164 - L165 were not covered by tests
# first contribution to integration
# NOTE: this treatment of I_nu_b (given
# by boundary conditions) is not in Lucy 1999;
# should be re-examined carefully
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to re-examine now? :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, I can take a look back and try to rederive it

escat_contrib += (

Check warning on line 170 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L170

Added line #L170 was not covered by tests
(zend - zstart)
* escat_op
* (Jblue_lu[pJblue_lu] - I_nu_thread[p_idx])
)
first = 0

Check warning on line 175 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L175

Added line #L175 was not covered by tests
else:
# Account for e-scattering, c.f. Eqs 27, 28 in Lucy 1999
Jkkp = 0.5 * (Jred_lu[pJred_lu] + Jblue_lu[pJblue_lu])
escat_contrib += (

Check warning on line 179 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L178-L179

Added lines #L178 - L179 were not covered by tests
(zend - zstart) * escat_op * (Jkkp - I_nu_thread[p_idx])
)
# this introduces the necessary offset of one element between
# pJblue_lu and pJred_lu
pJred_lu += 1
I_nu_thread[p_idx] += escat_contrib

Check warning on line 185 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L184-L185

Added lines #L184 - L185 were not covered by tests
# // Lucy 1999, Eq 26
I_nu_thread[p_idx] *= exp_tau[pexp_tau]
I_nu_thread[p_idx] += att_S_ul[patt_S_ul]

Check warning on line 188 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L187-L188

Added lines #L187 - L188 were not covered by tests

# // reset e-scattering opacity
escat_contrib = 0.0
zstart = zend

Check warning on line 192 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L191-L192

Added lines #L191 - L192 were not covered by tests

pline += 1
pexp_tau += 1
patt_S_ul += 1
pJblue_lu += 1

Check warning on line 197 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L194-L197

Added lines #L194 - L197 were not covered by tests

# calculate e-scattering optical depth to grid cell boundary

Jkkp = 0.5 * (Jred_lu[pJred_lu] + Jblue_lu[pJblue_lu])
zend = time_explosion / C_INV * (1.0 - nu_end / nu)
escat_contrib += (

Check warning on line 203 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L201-L203

Added lines #L201 - L203 were not covered by tests
(zend - zstart) * escat_op * (Jkkp - I_nu_thread[p_idx])
)
zstart = zend

Check warning on line 206 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L206

Added line #L206 was not covered by tests

# advance pointers
direction = int(

Check warning on line 209 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L209

Added line #L209 was not covered by tests
(shell_id_thread[i + 1] - shell_id_thread[i]) * size_line
)
pexp_tau += direction
patt_S_ul += direction
pJred_lu += direction
pJblue_lu += direction

Check warning on line 215 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L212-L215

Added lines #L212 - L215 were not covered by tests

I_nu_thread[p_idx] *= p

Check warning on line 217 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L217

Added line #L217 was not covered by tests



@cuda.jit
def cuda_formal_integral(
r_inner,
Expand Down Expand Up @@ -236,52 +442,75 @@
"""
Simple wrapper for the CUDA implementation of the formal integral
"""
L = np.zeros(inu_size, dtype=np.float64) # array(float64, 1d, C)
# global read-only values
size_line, size_shell = tau_sobolev.shape # int64, int64
size_tau = size_line * size_shell # int64

pp = np.zeros(N, dtype=np.float64) # array(float64, 1d, C)
exp_tau = np.zeros(size_tau, dtype=np.float64) # array(float64, 1d, C)
exp_tau = np.exp(-tau_sobolev.T.ravel()) # array(float64, 1d, C)
pp[::] = calculate_p_values(
self.geometry.r_outer[size_shell - 1], N
) # array(float64, 1d, C)

I_nu = np.zeros(
(inu_size, N), dtype=np.float64
) # array(float64, 1d, C)
z = np.zeros(
(inu_size, 2 * size_shell), dtype=np.float64
) # array(float64, 1d, C)
shell_id = np.zeros(
(inu_size, 2 * size_shell), dtype=np.int64
) # array(int64, 1d, C)
THREADS_PER_BLOCK = 32
blocks_per_grid = (inu_size // THREADS_PER_BLOCK) + 1

cuda_formal_integral[blocks_per_grid, THREADS_PER_BLOCK](
self.geometry.r_inner,
self.geometry.r_outer,
# These get separate names since they'll be copied back
d_L = cuda.device_array((inu_size,), dtype=np.float64)
andrewfullard marked this conversation as resolved.
Show resolved Hide resolved
d_I_nu = cuda.device_array((inu_size, N), dtype=np.float64)

Check warning on line 464 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L463-L464

Added lines #L463 - L464 were not covered by tests

# Copy these arrays to the device, we don't need them again
# But they must be initialized with zeros
z = cuda.to_device(z)
shell_id = cuda.to_device(shell_id)
pp = cuda.to_device(pp)
exp_tau = cuda.to_device(exp_tau)
r_inner = cuda.to_device(self.geometry.r_inner)
r_outer = cuda.to_device(self.geometry.r_outer)
line_list_nu = cuda.to_device(self.plasma.line_list_nu)
inu = cuda.to_device(inu.value)
att_S_ul = cuda.to_device(att_S_ul)
Jred_lu = cuda.to_device(Jred_lu)
Jblue_lu = cuda.to_device(Jblue_lu)
tau_sobolev = cuda.to_device(tau_sobolev)
electron_density = cuda.to_device(electron_density)

Check warning on line 480 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L468-L480

Added lines #L468 - L480 were not covered by tests

# Thread/Block Allocation, this seems to work
THREADS_PER_BLOCK_NU = 32
THREADS_PER_BLOCK_P = 16
blocks_per_grid_nu = (inu_size // THREADS_PER_BLOCK_NU) + 1
blocks_per_grid_p = ((N - 1) // THREADS_PER_BLOCK_P) + 1

Check warning on line 486 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L483-L486

Added lines #L483 - L486 were not covered by tests

cuda_formal_integral_fast[(blocks_per_grid_nu, blocks_per_grid_p), (THREADS_PER_BLOCK_NU, THREADS_PER_BLOCK_P)](

Check warning on line 488 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L488

Added line #L488 was not covered by tests
r_inner,
r_outer,
self.time_explosion,
self.plasma.line_list_nu,
line_list_nu,
iT.value,
inu.value,
inu,
inu_size,
att_S_ul,
Jred_lu,
Jblue_lu,
tau_sobolev,
electron_density,
N,
L,
pp,
exp_tau,
I_nu,
d_I_nu,
z,
shell_id,
)

R_max = self.geometry.r_outer[size_shell - 1]
cuda_vector_integrator[blocks_per_grid_nu, THREADS_PER_BLOCK_NU](d_L, d_I_nu, N, R_max)
L = d_L.copy_to_host()
I_nu = d_I_nu.copy_to_host()

Check warning on line 512 in tardis/transport/montecarlo/formal_integral_cuda.py

View check run for this annotation

Codecov / codecov/patch

tardis/transport/montecarlo/formal_integral_cuda.py#L509-L512

Added lines #L509 - L512 were not covered by tests

return L, I_nu


Expand Down
Loading