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

Line opacity parallelization #179

Merged
merged 36 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
454542a
fix bug with last depth point out of bounds error
jvshields Feb 22, 2024
346e342
make tau j+1 = 0
jvshields Feb 22, 2024
a253032
fix comment to align with tau = 0
jvshields Feb 22, 2024
00231db
rewrite the equation to use array broadcasting
jvshields Feb 22, 2024
1a6e9a5
try numba optimization and parallelization
jvshields Feb 23, 2024
7bcc635
add parallel implementation
jvshields Feb 26, 2024
3530860
add parallelization support
jvshields Feb 26, 2024
4972dc7
add parallel test
jvshields Feb 26, 2024
7b28dcd
small single threaded optimization and add conftest
jvshields Feb 26, 2024
11b4dfa
testing benchmarks
jvshields Feb 26, 2024
51e0beb
fix tests
jvshields Feb 26, 2024
d768b1b
try njitting single-threaded weight calculation
jvshields Feb 26, 2024
ee8c8be
fix parallelization bug
jvshields Feb 26, 2024
9b7ad6b
further simplification of single threaded loop
jvshields Feb 26, 2024
b6af724
apply black
jvshields Feb 27, 2024
e0e8885
final polish
jvshields Feb 27, 2024
d58cb68
unwrap thetas for the broadcasting case
jvshields Feb 28, 2024
d4c8470
parallel support for line opacity calculation
jvshields Feb 29, 2024
2fd8d82
update conftest
jvshields Feb 29, 2024
6b7aaee
assume not parallel if not specified
jvshields Feb 29, 2024
5dab831
assume not parallel if not specified
jvshields Feb 29, 2024
d7df844
basic logging
jvshields Mar 4, 2024
274a4b8
Merge remote-tracking branch 'upstream/main' into line_opacity_parall…
jvshields Mar 4, 2024
a45ef85
remove repeated fixture from merge conflict
jvshields Mar 4, 2024
c9e554a
update docstrings
jvshields Mar 4, 2024
a7f395f
apply black again
jvshields Mar 4, 2024
2ecd8eb
change user specification to number of threads
jvshields Mar 5, 2024
5e13387
update tests
jvshields Mar 5, 2024
a0ca387
add more helpful config validation failure message
jvshields Mar 5, 2024
914e435
improve descriptions in the config_schema
jvshields Mar 5, 2024
00fbaba
change serial n_threads to 1 and max threads to -99
jvshields Mar 5, 2024
f784a47
update test_config_parallel.yml
jvshields Mar 5, 2024
8559b46
update single threaded value in raytracing
jvshields Mar 5, 2024
202d48a
widen benchmark suite
jvshields Mar 5, 2024
6c063ba
shorten class names and use broadening range in benchmarks
jvshields Mar 5, 2024
e3ab84a
improve raytracing parallelization
jvshields Mar 5, 2024
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
8 changes: 6 additions & 2 deletions stardis/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from stardis.io.model.marcs import read_marcs_model
from stardis.io.model.mesa import read_mesa_model
from stardis.radiation_field.source_functions.blackbody import blackbody_flux_at_nu
import logging


BASE_DIR = Path(__file__).parent
Expand Down Expand Up @@ -48,6 +49,7 @@ def run_stardis(config_fname, tracing_lambdas_or_nus):
adata = AtomData.from_hdf(config.atom_data)

# model
logging.info("Reading model")
if config.model.type == "marcs":
raw_marcs_model = read_marcs_model(
Path(config.model.fname), gzipped=config.model.gzipped
Expand Down Expand Up @@ -91,19 +93,21 @@ def run_stardis(config_fname, tracing_lambdas_or_nus):
continuum_interaction_species=[],
)
# plasma
logging.info("Creating plasma")
stellar_plasma = create_stellar_plasma(stellar_model, adata, config)

stellar_radiation_field = RadiationField(
tracing_nus, blackbody_flux_at_nu, stellar_model
)

logging.info("Calculating alphas")
calc_alphas(
stellar_plasma=stellar_plasma,
stellar_model=stellar_model,
stellar_radiation_field=stellar_radiation_field,
opacity_config=config.opacity,
parallel_config=config.parallel,
)

logging.info("Raytracing")
raytrace(
stellar_model,
stellar_radiation_field,
Expand Down
1 change: 1 addition & 0 deletions stardis/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ def example_stellar_radiation_field_parallel(
stellar_model=example_stellar_model,
stellar_radiation_field=stellar_radiation_field,
opacity_config=example_config_parallel.opacity,
parallel_config=example_config_parallel.parallel,
)

raytrace(
Expand Down
139 changes: 111 additions & 28 deletions stardis/radiation_field/opacities/opacities_solvers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@
stellar_model,
tracing_nus,
line_opacity_config,
parallel_config=False,
):
"""
Calculates line opacity.
Expand Down Expand Up @@ -415,22 +416,16 @@
line_opacity_config.broadening,
) # This can be further improved by only calculating the broadening for the lines that are within the range.

alpha_line_at_nu = np.zeros((stellar_model.no_of_depth_points, len(tracing_nus)))
delta_nus = tracing_nus.value - line_nus[:, np.newaxis]

# If no broadening range, compute the contribution of every line at every frequency.
if line_range is None:
for i, nu in enumerate(tracing_nus):
delta_nus = nu.value - line_nus

alpha_line_at_nu[:, i] = calc_alan_entries(
delta_nus[:, np.newaxis],
doppler_widths,
gammas,
alphas_array,
)
h_lines_indices = None
line_range_value = None

# If there is a broadening range, first make sure the range is in frequency units, and then iterate through each frequency to calculate the contribution of each line within the broadening range.
else: # This if statement block appropriately handles if the broadening range is in frequency or wavelength units.
if (
line_range is not None
): # This if statement block appropriately handles if the broadening range is in frequency or wavelength units.
h_lines_indices = (
lines_sorted_in_range.atomic_number == 1
).to_numpy() # Hydrogen lines are much broader than other lines, so they need special treatment to ignore the broadening range.
Expand All @@ -448,29 +443,116 @@
"Broadening range must be in units of length or frequency."
)

# Iterate through each frequency to calculate the contribution of each line within the broadening range.
for i, nu in enumerate(tracing_nus):
delta_nus = nu.value - line_nus
# Iterate through each frequency to calculate the contribution of each line within the broadening range.
if parallel_config:
alpha_line_at_nu = calc_alan_entries_parallel(
stellar_model.no_of_depth_points,
tracing_nus.value,
delta_nus,
doppler_widths,
gammas,
alphas_array,
line_range_value,
h_lines_indices,
)

else:
alpha_line_at_nu = calc_alan_entries(
stellar_model.no_of_depth_points,
tracing_nus.value,
delta_nus,
doppler_widths,
gammas,
alphas_array,
line_range_value,
h_lines_indices,
)

return alpha_line_at_nu, gammas, doppler_widths

broadening_mask = np.abs(delta_nus) < line_range_value[i]

@numba.njit(parallel=True)
def calc_alan_entries_parallel(
no_of_depth_points,
tracing_nus_values,
delta_nus,
doppler_widths,
gammas,
alphas_array,
broadening_range=None,
h_lines_indices=None,
):
jvshields marked this conversation as resolved.
Show resolved Hide resolved
alpha_line_at_nu = np.zeros((no_of_depth_points, len(tracing_nus_values)))

Check warning on line 485 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L485

Added line #L485 was not covered by tests

if broadening_range is None:
for frequency_index in numba.prange(len(tracing_nus_values)):
andrewfullard marked this conversation as resolved.
Show resolved Hide resolved
alpha_line_at_nu[:, frequency_index] = _calc_alan_entries(

Check warning on line 489 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L487-L489

Added lines #L487 - L489 were not covered by tests
delta_nus[:, frequency_index, np.newaxis],
doppler_widths,
gammas,
alphas_array,
)

else:
for frequency_index in numba.prange(len(tracing_nus_values)):
broadening_mask = (

Check warning on line 498 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L497-L498

Added lines #L497 - L498 were not covered by tests
np.abs(delta_nus[:, frequency_index])
< broadening_range[frequency_index]
)
broadening_mask = np.logical_or(broadening_mask, h_lines_indices)

delta_nus_considered = delta_nus[broadening_mask]
gammas_considered = gammas[broadening_mask, :]
doppler_widths_considered = doppler_widths[broadening_mask, :]
alphas_considered = alphas_array[broadening_mask, :]
alpha_line_at_nu[:, i] = calc_alan_entries(
delta_nus_considered[:, np.newaxis],
doppler_widths_considered,
gammas_considered,
alphas_considered,
alpha_line_at_nu[:, frequency_index] = _calc_alan_entries(

Check warning on line 504 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L504

Added line #L504 was not covered by tests
delta_nus[:, frequency_index, np.newaxis][broadening_mask],
doppler_widths[broadening_mask],
gammas[broadening_mask],
alphas_array[broadening_mask],
)

return alpha_line_at_nu, gammas, doppler_widths
return alpha_line_at_nu

Check warning on line 511 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L511

Added line #L511 was not covered by tests


@numba.njit
def calc_alan_entries(
no_of_depth_points,
tracing_nus_values,
delta_nus,
doppler_widths,
gammas,
alphas_array,
broadening_range=None,
h_lines_indices=None,
):
jvshields marked this conversation as resolved.
Show resolved Hide resolved
alpha_line_at_nu = np.zeros((no_of_depth_points, len(tracing_nus_values)))

Check warning on line 525 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L525

Added line #L525 was not covered by tests

if broadening_range is None:
for frequency_index in range(len(tracing_nus_values)):
alpha_line_at_nu[:, frequency_index] = _calc_alan_entries(

Check warning on line 529 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L527-L529

Added lines #L527 - L529 were not covered by tests
delta_nus[:, frequency_index, np.newaxis],
doppler_widths,
gammas,
alphas_array,
)

else:
for frequency_index in range(len(tracing_nus_values)):
broadening_mask = (

Check warning on line 538 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L537-L538

Added lines #L537 - L538 were not covered by tests
np.abs(delta_nus[:, frequency_index])
< broadening_range[frequency_index]
)
broadening_mask = np.logical_or(broadening_mask, h_lines_indices)

Check warning on line 542 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L542

Added line #L542 was not covered by tests

alpha_line_at_nu[:, frequency_index] = _calc_alan_entries(

Check warning on line 544 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L544

Added line #L544 was not covered by tests
delta_nus[:, frequency_index, np.newaxis][broadening_mask],
doppler_widths[broadening_mask],
gammas[broadening_mask],
alphas_array[broadening_mask],
)

return alpha_line_at_nu

Check warning on line 551 in stardis/radiation_field/opacities/opacities_solvers/base.py

View check run for this annotation

Codecov / codecov/patch

stardis/radiation_field/opacities/opacities_solvers/base.py#L551

Added line #L551 was not covered by tests


@numba.njit
def _calc_alan_entries(
delta_nus,
doppler_widths_at_depth_point,
gammas_at_depth_point,
Expand All @@ -497,9 +579,8 @@
float
Line opacity.
"""

phis = voigt_profile(
np.abs(delta_nus), doppler_widths_at_depth_point, gammas_at_depth_point
delta_nus, doppler_widths_at_depth_point, gammas_at_depth_point
)

return np.sum(phis * alphas_at_depth_point, axis=0)
Expand All @@ -510,6 +591,7 @@
stellar_model,
stellar_radiation_field,
opacity_config,
parallel_config=False,
):
"""
Calculates each opacity and adds it to the opacity dictionary contained in the radiation field.
Expand Down Expand Up @@ -582,6 +664,7 @@
stellar_model,
stellar_radiation_field.frequencies,
opacity_config.line,
parallel_config,
)
stellar_radiation_field.opacities.opacities_dict[
"alpha_line_at_nu"
Expand Down
Loading