Skip to content

Commit 5e2d0bb

Browse files
V inner formal integral (#2800)
* Basic skeleton * Lots of progress Solvers pass info to each other Simplified some parts * Adds setup method, refactors some functions, removes unused items * Move convergence setup to setup method * Add docs notebook, fix a couple of errors * Move setup to init * Fix iteration and convergence * Simplify spectrumsolver init * Separate plasma "solver" and simulation state updates * Simplify convergence solver setup with a dict. * Minor formatting change * Minor refactoring * Fixes plasma update step * Fixes loggers and progress bars Also adds docstrings to methods. Updates some methods to use new functionality of the plasma. Adds requirements for the convergence plots (still broken) * Fixes convergence plot rendering * Fixes convergence plots in the final iteration * black * Simplify convergence plot updating * Move logging handling to a separate class * Add HDF output capability to solver * Move more basic logging back into workflow * Add not-converged error message * Update notebook with export option * Added simple base workflow and changed some verbiage * Fix typo * Moved solver workflow over to updated branch * Added reprojection method for comparing arrays between iterations * Updated schema and parser to add v_inner_boundary, added property to the model because it is named weirdly * Added ntoebook for the IBVS workflow * Updated workflow notebook to have correct convergence information, updated simple solver to properly set up the plasma with the new assembly * Reduced size of overloaded functions to make them more in-line with the simple solver, updated simple solver to handle current tardis master branch * cleared notebook outputs * Updated notebook to use correctmethod * Updated the docstrings * removed unused imports * Updated notebook to stop if converged * Updated v_inner_solver to deal with detailed radiative rates types * removed old comment * Added docstrings, removed old comments * Fixed typo * Updated notebook to be more explicit * removed old comment * removed unused variable * Changed the radiation_field to use the radiation field state properties with no explicit sovler method * Added back radaition field to plasma solver in v_inner solver * Added a solve opacity method * Added docstring to solve_opacity method * Fixed initializing opacity at the last iteration * Added initial v_inner estimate in the __init__ * massively simplified the reproject method by just doing basic math * added docstring describing the simplified reproject method so I don't forget why it works later * Formatting error in doscstring * Added nice logger output showing changes in geometry state * Cleaned up the notebook a bit * Updated the formal integral to handle changes in geometry * Fixed the standard simulation solver * Remove old files * Fixes v_inner workflow * Minor formatting changes * Clean up confusing v_boundary_inner vs v_inner_boundary variable names --------- Co-authored-by: Andrew Fullard <[email protected]>
1 parent 0a0ecbf commit 5e2d0bb

File tree

10 files changed

+655
-34
lines changed

10 files changed

+655
-34
lines changed

Diff for: docs/physics/setup/model.ipynb

+4-4
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
"id": "cee054e9",
8282
"metadata": {},
8383
"source": [
84-
"In the cell below, we set up a model. We use the [specific structure](../../io/configuration/components/models/index.rst#specific-structure) where we supply $t_\\mathrm{explosion}$, the velocity of the inner and outer boundaries of the supernova (labeled `start` and `stop`), and the number of shells (labeled `num`). The shells are then evenly spaced between the inner and outer boundaries of the supernova. The time after the explosion, the inner and outer velocities, and the number of shells can be varied to get different shell structures. The `SimulationState` object stores information about the model in the following attributes: `velocity` shows the velocity of the shell boundaries, `v_inner` shows the velocities of the inner boundaries of each shell, `v_outer` shows the velocity of the outer boundaries of each shell, and `v_middle` shows the velocity of the middle of each shell. Similarly, `radius`, `r_inner`, `r_outer`, and `r_middle` show the radii of each shell boundary, the inner boundaries, the outer boundaries, and the middles of each shell, respectively. `v_boundary_inner` shows the velocity of the inner boundary of the computational domain, and `v_boundary_outer` shows the velocity of the outer boundary of the computational domain. Finally, `volume` shows the volume of each shell, calculated via the formula of the volume of a spherical shell: $V=\\frac{4}{3}\\pi (r_\\mathrm{outer}^3-r_\\mathrm{inner}^3)$."
84+
"In the cell below, we set up a model. We use the [specific structure](../../io/configuration/components/models/index.rst#specific-structure) where we supply $t_\\mathrm{explosion}$, the velocity of the inner and outer boundaries of the supernova (labeled `start` and `stop`), and the number of shells (labeled `num`). The shells are then evenly spaced between the inner and outer boundaries of the supernova. The time after the explosion, the inner and outer velocities, and the number of shells can be varied to get different shell structures. The `SimulationState` object stores information about the model in the following attributes: `velocity` shows the velocity of the shell boundaries, `v_inner` shows the velocities of the inner boundaries of each shell, `v_outer` shows the velocity of the outer boundaries of each shell, and `v_middle` shows the velocity of the middle of each shell. Similarly, `radius`, `r_inner`, `r_outer`, and `r_middle` show the radii of each shell boundary, the inner boundaries, the outer boundaries, and the middles of each shell, respectively. `v_inner_boundary` shows the velocity of the inner boundary of the computational domain, and `v_outer_boundary` shows the velocity of the outer boundary of the computational domain. Finally, `volume` shows the volume of each shell, calculated via the formula of the volume of a spherical shell: $V=\\frac{4}{3}\\pi (r_\\mathrm{outer}^3-r_\\mathrm{inner}^3)$."
8585
]
8686
},
8787
{
@@ -111,8 +111,8 @@
111111
"print('v_inner:\\n', shell_simulation_state.v_inner)\n",
112112
"print('v_outer:\\n', shell_simulation_state.v_outer)\n",
113113
"print('v_middle:\\n', shell_simulation_state.v_middle)\n",
114-
"print('v_boundary_inner:\\n', shell_simulation_state.v_boundary_inner)\n",
115-
"print('v_boundary_outer:\\n', shell_simulation_state.v_boundary_outer)\n",
114+
"print('v_inner_boundary:\\n', shell_simulation_state.v_inner_boundary)\n",
115+
"print('v_outer_boundary:\\n', shell_simulation_state.v_outer_boundary)\n",
116116
"print('radius:\\n', shell_simulation_state.radius)\n",
117117
"print('r_inner:\\n', shell_simulation_state.r_inner)\n",
118118
"print('r_outer:\\n', shell_simulation_state.r_outer)\n",
@@ -125,7 +125,7 @@
125125
"id": "1ee56110",
126126
"metadata": {},
127127
"source": [
128-
"Notice that `radius = velocity*time_explosion`, and similarly for `r_inner`, `r_outer`, and `r_middle`. You can get the radius of the photosphere via `v_boundary_inner*time_explosion` and outer edge of the supernova via `v_boundary_outer*time_explosion`.\n",
128+
"Notice that `radius = velocity*time_explosion`, and similarly for `r_inner`, `r_outer`, and `r_middle`. You can get the radius of the photosphere via `v_inner_boundary*time_explosion` and outer edge of the supernova via `v_boundary_outer*time_explosion`.\n",
129129
"\n",
130130
"<div class=\"alert alert-info\">\n",
131131
" \n",

Diff for: docs/workflows/v_inner_solver_workflow.ipynb

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"from tardis.workflows.v_inner_solver import InnerVelocitySolverWorkflow\n",
10+
"from tardis.io.configuration.config_reader import Configuration"
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": null,
16+
"metadata": {},
17+
"outputs": [],
18+
"source": [
19+
"config = Configuration.from_yaml('../tardis_example.yml')"
20+
]
21+
},
22+
{
23+
"cell_type": "markdown",
24+
"metadata": {},
25+
"source": [
26+
"This code modifies the TARDIS example configuration to include convergence information for the inner boundary velocity solver.\n",
27+
"Note that the number of shells is increased and the starting velocity is reduced to provide more granularity and a wider search window, respectively."
28+
]
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": null,
33+
"metadata": {
34+
"scrolled": true
35+
},
36+
"outputs": [],
37+
"source": [
38+
"from astropy import units as u\n",
39+
"\n",
40+
"config.montecarlo.convergence_strategy['v_inner_boundary'] = {\n",
41+
" 'damping_constant' : 0.5,\n",
42+
" 'threshold' : 0.01,\n",
43+
" 'type' : 'damped'\n",
44+
" }\n",
45+
"\n",
46+
"config.montecarlo.convergence_strategy.stop_if_converged = True\n",
47+
"config.model.structure.velocity.start = 5000 * u.km/u.s # Larger window over which to search\n",
48+
"config.model.structure.velocity.num = 50 # Increase number of shells\n",
49+
"\n",
50+
"workflow = InnerVelocitySolverWorkflow(\n",
51+
" config, tau=2.0/3,\n",
52+
" mean_optical_depth=\"rosseland\"\n",
53+
")"
54+
]
55+
},
56+
{
57+
"cell_type": "code",
58+
"execution_count": null,
59+
"metadata": {},
60+
"outputs": [],
61+
"source": [
62+
"workflow.run()"
63+
]
64+
},
65+
{
66+
"cell_type": "code",
67+
"execution_count": null,
68+
"metadata": {},
69+
"outputs": [],
70+
"source": [
71+
"import matplotlib.pyplot as plt"
72+
]
73+
},
74+
{
75+
"cell_type": "code",
76+
"execution_count": null,
77+
"metadata": {},
78+
"outputs": [],
79+
"source": [
80+
"spectrum = workflow.spectrum_solver.spectrum_real_packets\n",
81+
"spectrum_virtual = workflow.spectrum_solver.spectrum_virtual_packets\n",
82+
"spectrum_integrated = workflow.spectrum_solver.spectrum_integrated"
83+
]
84+
},
85+
{
86+
"cell_type": "code",
87+
"execution_count": null,
88+
"metadata": {},
89+
"outputs": [],
90+
"source": [
91+
"%matplotlib inline\n",
92+
"plt.figure(figsize=(10, 6.5))\n",
93+
"\n",
94+
"spectrum.plot(label=\"Normal packets\")\n",
95+
"spectrum_virtual.plot(label=\"Virtual packets\")\n",
96+
"spectrum_integrated.plot(label='Formal integral')\n",
97+
"\n",
98+
"plt.xlim(500, 9000)\n",
99+
"plt.title(\"TARDIS example model spectrum\")\n",
100+
"plt.xlabel(r\"Wavelength [$\\AA$]\")\n",
101+
"plt.ylabel(r\"Luminosity density [erg/s/$\\AA$]\")\n",
102+
"plt.legend()\n",
103+
"plt.show()"
104+
]
105+
}
106+
],
107+
"metadata": {
108+
"kernelspec": {
109+
"display_name": "tardis",
110+
"language": "python",
111+
"name": "python3"
112+
},
113+
"language_info": {
114+
"codemirror_mode": {
115+
"name": "ipython",
116+
"version": 3
117+
},
118+
"file_extension": ".py",
119+
"mimetype": "text/x-python",
120+
"name": "python",
121+
"nbconvert_exporter": "python",
122+
"pygments_lexer": "ipython3",
123+
"version": "3.12.4"
124+
}
125+
},
126+
"nbformat": 4,
127+
"nbformat_minor": 2
128+
}

Diff for: tardis/io/configuration/config_reader.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ def parse_convergence_section(convergence_section_dict):
431431
"""
432432
convergence_parameters = ["damping_constant", "threshold", "type"]
433433

434-
for convergence_variable in ["t_inner", "t_rad", "w"]:
434+
for convergence_variable in ["t_inner", "t_rad", "w", "v_inner_boundary"]:
435435
if convergence_variable not in convergence_section_dict:
436436
convergence_section_dict[convergence_variable] = {}
437437
convergence_variable_section = convergence_section_dict[

Diff for: tardis/io/configuration/schemas/montecarlo_definitions.yml

+18-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ definitions:
55
title: 'Damped Convergence Strategy'
66
type: object
77
additionalProperties: false
8-
properties:
98
properties:
109
type:
1110
enum:
@@ -59,6 +58,24 @@ definitions:
5958
type: string
6059
default: 'damped'
6160
description: THIS IS A DUMMY VARIABLE DO NOT USE
61+
v_inner_boundary:
62+
type: object
63+
additionalProperties: false
64+
properties:
65+
damping_constant:
66+
type: number
67+
default: 0.0
68+
description: damping constant
69+
minimum: 0
70+
threshold:
71+
type: number
72+
description: specifies the threshold that is taken as convergence (i.e.
73+
0.05 means that the value does not change more than 5%)
74+
minimum: 0
75+
type:
76+
type: string
77+
default: 'damped'
78+
description: THIS IS A DUMMY VARIABLE DO NOT USE
6279
t_rad:
6380
type: object
6481
additionalProperties: false

Diff for: tardis/io/model/parse_geometry_configuration.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,17 @@ def parse_geometry_from_csvy(
135135
"""
136136
if hasattr(config, "model"):
137137
if hasattr(config.model, "v_inner_boundary"):
138-
v_boundary_inner = config.model.v_inner_boundary
138+
v_inner_boundary = config.model.v_inner_boundary
139139
else:
140-
v_boundary_inner = None
140+
v_inner_boundary = None
141141

142142
if hasattr(config.model, "v_outer_boundary"):
143-
v_boundary_outer = config.model.v_outer_boundary
143+
v_outer_boundary = config.model.v_outer_boundary
144144
else:
145-
v_boundary_outer = None
145+
v_outer_boundary = None
146146
else:
147-
v_boundary_inner = None
148-
v_boundary_outer = None
147+
v_inner_boundary = None
148+
v_outer_boundary = None
149149

150150
if hasattr(csvy_model_config, "velocity"):
151151
velocity = quantity_linspace(
@@ -166,8 +166,8 @@ def parse_geometry_from_csvy(
166166
geometry = HomologousRadial1DGeometry(
167167
velocity[:-1], # v_inner
168168
velocity[1:], # v_outer
169-
v_inner_boundary=v_boundary_inner,
170-
v_outer_boundary=v_boundary_outer,
169+
v_inner_boundary=v_inner_boundary,
170+
v_outer_boundary=v_outer_boundary,
171171
time_explosion=time_explosion,
172172
)
173173
return geometry

Diff for: tardis/model/base.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ class SimulationState(HDFWriterMixin):
5858
dilution_factor : np.ndarray
5959
If None, the dilution_factor will be initialized with the geometric
6060
dilution factor.
61-
v_boundary_inner : astropy.units.Quantity
62-
v_boundary_outer : astropy.units.Quantity
61+
v_inner_boundary : astropy.units.Quantity
62+
v_outer_boundary : astropy.units.Quantity
6363
raw_velocity : np.ndarray
6464
The complete array of the velocities, without being cut by
65-
`v_boundary_inner` and `v_boundary_outer`
65+
`v_inner_boundary` and `v_outer_boundary`
6666
electron_densities : astropy.units.quantity.Quantity
6767
6868
Attributes
@@ -81,8 +81,8 @@ class SimulationState(HDFWriterMixin):
8181
density : astropy.units.quantity.Quantity
8282
volume : astropy.units.quantity.Quantity
8383
no_of_shells : int
84-
The number of shells as formed by `v_boundary_inner` and
85-
`v_boundary_outer`
84+
The number of shells as formed by `v_inner_boundary` and
85+
`v_outer_boundary`
8686
no_of_raw_shells : int
8787
"""
8888

@@ -206,11 +206,11 @@ def radius(self):
206206
return self.time_explosion * self.velocity
207207

208208
@property
209-
def v_boundary_inner(self):
209+
def v_inner_boundary(self):
210210
return self.geometry.v_inner_boundary
211211

212212
@property
213-
def v_boundary_outer(self):
213+
def v_outer_boundary(self):
214214
return self.geometry.v_outer_boundary
215215

216216
@property

Diff for: tardis/spectrum/formal_integral.py

+31-13
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,22 @@ def make_source_function(self):
434434
-------
435435
Numpy array containing ( 1 - exp(-tau_ul) ) S_ul ordered by wavelength of the transition u -> l
436436
"""
437+
437438
simulation_state = self.simulation_state
439+
# slice for the active shells
440+
local_slice = slice(
441+
simulation_state.geometry.v_inner_boundary_index,
442+
simulation_state.geometry.v_outer_boundary_index,
443+
)
444+
438445
transport = self.transport
439446
montecarlo_transport_state = transport.transport_state
447+
transition_probabilities = self.opacity_state.transition_probabilities[
448+
:, local_slice
449+
]
450+
tau_sobolevs = self.opacity_state.tau_sobolev[:, local_slice]
451+
452+
columns = range(simulation_state.no_of_shells)
440453

441454
# macro_ref = self.atomic_data.macro_atom_references
442455
macro_ref = self.atomic_data.macro_atom_references
@@ -449,9 +462,7 @@ def make_source_function(self):
449462
if transport.line_interaction_type == "macroatom":
450463
internal_jump_mask = (macro_data.transition_type >= 0).values
451464
ma_int_data = macro_data[internal_jump_mask]
452-
internal = self.opacity_state.transition_probabilities[
453-
internal_jump_mask
454-
]
465+
internal = transition_probabilities[internal_jump_mask]
455466

456467
source_level_idx = ma_int_data.source_level_idx.values
457468
destination_level_idx = ma_int_data.destination_level_idx.values
@@ -460,7 +471,7 @@ def make_source_function(self):
460471
montecarlo_transport_state.packet_collection.time_of_simulation
461472
* simulation_state.volume
462473
)
463-
exptau = 1 - np.exp(-self.opacity_state.tau_sobolev)
474+
exptau = 1 - np.exp(-tau_sobolevs)
464475
Edotlu = (
465476
Edotlu_norm_factor
466477
* exptau
@@ -493,14 +504,14 @@ def make_source_function(self):
493504
upper_level_index = self.atomic_data.lines.index.droplevel(
494505
"level_number_lower"
495506
)
496-
e_dot_lu = pd.DataFrame(Edotlu.value, index=upper_level_index)
507+
e_dot_lu = pd.DataFrame(
508+
Edotlu.value, index=upper_level_index, columns=columns
509+
)
497510
e_dot_u = e_dot_lu.groupby(level=[0, 1, 2]).sum()
498511
e_dot_u_src_idx = macro_ref.loc[e_dot_u.index].references_idx.values
499512

500513
if transport.line_interaction_type == "macroatom":
501-
C_frame = pd.DataFrame(
502-
columns=np.arange(no_shells), index=macro_ref.index
503-
)
514+
C_frame = pd.DataFrame(columns=columns, index=macro_ref.index)
504515
q_indices = (source_level_idx, destination_level_idx)
505516
for shell in range(no_shells):
506517
Q = sp.coo_matrix(
@@ -523,7 +534,7 @@ def make_source_function(self):
523534
["atomic_number", "ion_number", "source_level_number"]
524535
).index.copy()
525536
tmp = pd.DataFrame(
526-
self.opacity_state.transition_probabilities[
537+
transition_probabilities[
527538
(self.atomic_data.macro_atom_data.transition_type == -1).values
528539
]
529540
)
@@ -539,13 +550,15 @@ def make_source_function(self):
539550
att_S_ul = wave * (q_ul * e_dot_u) * t / (4 * np.pi)
540551

541552
result = pd.DataFrame(
542-
att_S_ul.values, index=transitions.transition_line_id.values
553+
att_S_ul.values,
554+
index=transitions.transition_line_id.values,
555+
columns=columns,
543556
)
544557
att_S_ul = result.loc[lines.index.values].values
545558

546559
# Jredlu should already by in the correct order, i.e. by wavelength of
547560
# the transition l->u (similar to Jbluelu)
548-
Jredlu = Jbluelu * np.exp(-self.opacity_state.tau_sobolev) + att_S_ul
561+
Jredlu = Jbluelu * np.exp(-tau_sobolevs) + att_S_ul
549562
if self.interpolate_shells > 0:
550563
(
551564
att_S_ul,
@@ -592,15 +605,20 @@ def interpolate_integrator_quantities(
592605

593606
transport.electron_densities_integ = interp1d(
594607
r_middle,
595-
plasma.electron_densities,
608+
plasma.electron_densities.iloc[
609+
self.simulation_state.geometry.v_inner_boundary_index : self.simulation_state.geometry.v_outer_boundary_index
610+
],
596611
fill_value="extrapolate",
597612
kind="nearest",
598613
)(r_middle_integ)
599614
# Assume tau_sobolevs to be constant within a shell
600615
# (as in the MC simulation)
601616
transport.tau_sobolevs_integ = interp1d(
602617
r_middle,
603-
self.opacity_state.tau_sobolev,
618+
self.opacity_state.tau_sobolev[
619+
:,
620+
self.simulation_state.geometry.v_inner_boundary_index : self.simulation_state.geometry.v_outer_boundary_index,
621+
],
604622
fill_value="extrapolate",
605623
kind="nearest",
606624
)(r_middle_integ)

Diff for: tardis/workflows/simple_tardis_workflow.py

+2
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ def solve_simulation_state(
268268
"t_inner"
269269
]
270270

271+
return next_values
272+
271273
def solve_plasma(self, estimated_radfield_properties):
272274
"""Update the plasma solution with the new radiation field estimates
273275

0 commit comments

Comments
 (0)