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

Changing construction of the first guess and coefficient matrices in NLTE solver #2201

Merged
merged 80 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
91c8882
implementing nlte_excitation
sonachitchyan Jan 24, 2023
78b5c91
ran black
sonachitchyan Jan 24, 2023
38f895a
Merge branch 'master' of github.com:tardis-sn/tardis into adding_exci…
sonachitchyan Jan 24, 2023
82ae5c5
fixed a typo
sonachitchyan Jan 24, 2023
a63ea03
got rid of unnecessary lines
sonachitchyan Jan 25, 2023
ed5184e
rewrote tests
sonachitchyan Jan 26, 2023
94645d1
made a change on assigning the config values to plasma properties
sonachitchyan Jan 26, 2023
7f147cb
fixed the tests
sonachitchyan Jan 26, 2023
2de10bf
Update tardis/io/tests/test_config_reader.py
sonachitchyan Jan 30, 2023
2eb1e55
Merge branch 'master' of github.com:tardis-sn/tardis into adding_exci…
sonachitchyan Jan 30, 2023
6112033
Merge branch 'master' of github.com:tardis-sn/tardis into adding_exci…
sonachitchyan Jan 31, 2023
3ebf154
restructured the first guess for NLTE solver to be compatible with NL…
sonachitchyan Feb 1, 2023
c6b7949
ran black
sonachitchyan Feb 1, 2023
3957a94
modified the existing rates to change when treating species with NLTE…
sonachitchyan Feb 6, 2023
14d9d20
nlte not implemented, remove from rate_matrix_index
sonachitchyan Feb 6, 2023
d906658
ran black
sonachitchyan Feb 6, 2023
fd1076d
fixed an issue with one of the tests
sonachitchyan Feb 6, 2023
8c1359d
attempt of adding bound bound interaction coefficients
sonachitchyan Feb 7, 2023
625deed
fixed an issue with bound bound rates matrix
sonachitchyan Feb 20, 2023
efc91dd
added docstrings
sonachitchyan Feb 22, 2023
7e36921
ran black
sonachitchyan Feb 22, 2023
7c8869f
changed one of the methods to static
sonachitchyan Feb 23, 2023
8b43ebb
added test for bound bound rates part of the matrix
sonachitchyan Feb 23, 2023
fc31c1c
ran black
sonachitchyan Feb 23, 2023
d4b1e29
added docstrings to nlteexcitationdata
sonachitchyan Mar 14, 2023
409abde
got rid of unnecessary import
sonachitchyan Mar 14, 2023
88a362c
added a new parameter to the docsting of the method
sonachitchyan Mar 14, 2023
a3c1c23
got rid of the number conservation row for the bound-bound matrix as …
sonachitchyan Mar 14, 2023
a81f670
ran black
sonachitchyan Mar 14, 2023
7e60181
remodified the tests
sonachitchyan Mar 14, 2023
d23aaf1
Merge branch 'master' of github.com:tardis-sn/tardis into excitation_…
sonachitchyan Mar 29, 2023
333b5ae
fixed a loop issue
sonachitchyan Mar 30, 2023
5705c2c
added a todo comment
sonachitchyan Mar 30, 2023
02f33c4
renamed a function
sonachitchyan Mar 30, 2023
946d039
updated a docstring
sonachitchyan Mar 30, 2023
c370b6b
Update tardis/plasma/properties/nlte_rate_equation_solver.py
sonachitchyan Mar 30, 2023
cdfe71f
Update tardis/plasma/properties/nlte_rate_equation_solver.py
sonachitchyan Mar 30, 2023
0966d04
Update tardis/plasma/properties/nlte_rate_equation_solver.py
sonachitchyan Mar 30, 2023
d5c980c
got rid of t_electrons
sonachitchyan Mar 30, 2023
c7d6641
resolved an issue with tests
sonachitchyan Mar 30, 2023
405ed75
Merge branch 'excitation_first_guess_implementation' of github.com:ta…
sonachitchyan Mar 30, 2023
f3a6d4c
added additional information into a docstring
sonachitchyan Mar 30, 2023
b82b200
added a docstring
sonachitchyan Mar 30, 2023
8333e62
got rid of unnecessary grouping of rates
sonachitchyan Mar 30, 2023
af462be
Update tardis/plasma/properties/nlte_rate_equation_solver.py
sonachitchyan Mar 30, 2023
5167aa8
fixing a minor issue in tests
sonachitchyan Apr 2, 2023
6b086e1
Merge branch 'excitation_first_guess_implementation' of github.com:ta…
sonachitchyan Apr 2, 2023
4c0d3e0
Merge branch 'master' of github.com:tardis-sn/tardis into excitation_…
sonachitchyan Apr 5, 2023
993200e
separated nlte excitation coefficients
sonachitchyan Apr 5, 2023
8f0a341
running black
sonachitchyan Apr 5, 2023
cf805d9
separating beta sobolev related stuff from the rest of the bound boun…
sonachitchyan Apr 10, 2023
2166667
Update tardis/plasma/properties/nlte_rate_equation_solver.py
sonachitchyan Apr 12, 2023
259a0cc
factored prepare_bound_bound_rate_matrix
sonachitchyan Apr 12, 2023
f471a20
Merge branch 'excitation_first_guess_implementation' of github.com:ta…
sonachitchyan Apr 12, 2023
4b27db3
removed an unnecessary function for excitation rates
sonachitchyan Apr 12, 2023
0dc7660
removed unnecessary method for concatinating rates for NLTE excitation
sonachitchyan Apr 12, 2023
5130670
ran black on nlte_rate_equation_solver
sonachitchyan Apr 12, 2023
6770958
got rid of an unnecessary method
sonachitchyan Apr 12, 2023
e481e7b
fixed a typo
sonachitchyan Apr 12, 2023
1ac0ee1
small fixed
sonachitchyan Apr 12, 2023
dbfc1c8
modified the j_blues and beta_sobolevs used in the tests
sonachitchyan Apr 12, 2023
da26718
running black once again
sonachitchyan Apr 12, 2023
007910a
adding rate_matrix_index to first guess docstring
sonachitchyan Apr 12, 2023
2109509
Update tardis/plasma/properties/nlte_rate_equation_solver.py
sonachitchyan Apr 19, 2023
44e060f
Update tardis/plasma/properties/nlte_rate_equation_solver.py
sonachitchyan Apr 19, 2023
af8ad20
Update tardis/plasma/tests/test_nlte_excitation.py
sonachitchyan Apr 19, 2023
74c37f3
fixed a typo
sonachitchyan Apr 26, 2023
a432a25
switched from using the atomic_data_levels to number_of_levels
sonachitchyan Apr 26, 2023
5f34e1f
Merge branch 'excitation_first_guess_implementation' of github.com:ta…
sonachitchyan Apr 26, 2023
fbab174
Update tardis/plasma/properties/nlte_rate_equation_solver.py
sonachitchyan Apr 26, 2023
a0f4f0d
Update tardis/plasma/properties/nlte_rate_equation_solver.py
sonachitchyan Apr 26, 2023
39751b1
fixed the issue with tests
sonachitchyan Apr 26, 2023
51c03cb
Merge branch 'excitation_first_guess_implementation' of github.com:ta…
sonachitchyan Apr 26, 2023
d2e6952
ran black once again
sonachitchyan Apr 26, 2023
7bfa59a
left a comment for future generations of NLTE youth
sonachitchyan Apr 26, 2023
73193e8
ran black once again
sonachitchyan Apr 26, 2023
913cd7f
Update tardis/plasma/properties/nlte_rate_equation_solver.py
sonachitchyan May 3, 2023
3c2f68a
Merge branch 'adding_excitation_to_config' of github.com:tardis-sn/ta…
sonachitchyan May 3, 2023
e26020a
got rid of an unnecessary argument
sonachitchyan May 3, 2023
ebb36f1
Merge branch 'excitation_first_guess_implementation' of github.com:ta…
sonachitchyan May 3, 2023
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
41 changes: 41 additions & 0 deletions tardis/plasma/properties/nlte_excitation_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import logging

import numpy as np

logger = logging.getLogger(__name__)


class NLTEExcitationData(object):
chvogl marked this conversation as resolved.
Show resolved Hide resolved
def __init__(self, atom_data, nlte_excitation_species):
self.atom_data = atom_data
self.lines = atom_data.lines.reset_index()
self.nlte_excitation_species = nlte_excitation_species

if nlte_excitation_species:
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
logger.info("Preparing the NLTE data")
self._init_indices()

def _init_indices(self):
self.lines_idx = {}
self.lines_level_number_lower = {}
self.lines_level_number_upper = {}
self.A_uls = {}
self.B_uls = {}
self.B_lus = {}

for species in self.nlte_excitation_species:
lines_idx = np.where(
(self.lines.atomic_number == species[0])
& (self.lines.ion_number == species[1])
)
self.lines_idx[species] = lines_idx
self.lines_level_number_lower[
species
] = self.lines.level_number_lower.values[lines_idx].astype(int)
self.lines_level_number_upper[
species
] = self.lines.level_number_upper.values[lines_idx].astype(int)

self.A_uls[species] = self.atom_data.lines.A_ul.values[lines_idx]
self.B_uls[species] = self.atom_data.lines.B_ul.values[lines_idx]
self.B_lus[species] = self.atom_data.lines.B_lu.values[lines_idx]
249 changes: 242 additions & 7 deletions tardis/plasma/properties/nlte_rate_equation_solver.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import pandas as pd
import numpy as np
from scipy.optimize import root
from tardis.io.atom_data.base import NLTEData
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved

from tardis.plasma.properties.base import ProcessingPlasmaProperty
from tardis.plasma.properties.nlte_excitation_data import NLTEExcitationData

__all__ = [
"NLTERateEquationSolver",
Expand All @@ -25,6 +27,7 @@ def calculate(
phi,
rate_matrix_index,
number_density,
nlte_excitation_species,
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
):
"""Calculates ion number densities and electron densities using NLTE ionization.

Expand Down Expand Up @@ -65,6 +68,7 @@ def calculate(
Electron density with NLTE ionization treatment.
"""

# nlte_data = NLTEExcitationData(atomic_data, nlte_excitation_species) - will be used in a future PR
(
total_photo_ion_coefficients,
total_rad_recomb_coefficients,
Expand All @@ -79,6 +83,8 @@ def calculate(
partition_function,
levels,
level_boltzmann_factor,
nlte_excitation_species,
rate_matrix_index,
)

initial_electron_densities = number_density.sum(axis=0)
Expand All @@ -99,6 +105,7 @@ def calculate(
number_density[shell]
)
first_guess = self.prepare_first_guess(
rate_matrix_index,
atomic_numbers,
number_density[shell],
initial_electron_densities[shell],
Expand Down Expand Up @@ -369,6 +376,8 @@ def prepare_ion_recomb_coefficients_nlte_ion(
partition_function,
levels,
level_boltzmann_factor,
nlte_excitation_species,
rate_matrix_index,
):
"""
Prepares the ionization and recombination coefficients by grouping them for
Expand Down Expand Up @@ -420,6 +429,7 @@ def prepare_ion_recomb_coefficients_nlte_ion(
.groupby(level=("atomic_number", "ion_number"))
.sum()
)

total_rad_recomb_coefficients = (
(alpha_sp + alpha_stim)
.groupby(level=["atomic_number", "ion_number"])
Expand All @@ -438,6 +448,61 @@ def prepare_ion_recomb_coefficients_nlte_ion(
.groupby(level=("atomic_number", "ion_number"))
.sum()
)
if len(nlte_excitation_species) != 0:
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
total_photo_ion_coefficients_with_levels = (
(level_population_fraction.loc[gamma.index] * gamma)
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
.groupby(level=("atomic_number", "ion_number", "level_number"))
.sum()
)
total_rad_recomb_coefficients_with_levels = (
(alpha_sp + alpha_stim)
.groupby(level=("atomic_number", "ion_number", "level_number"))
.sum()
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
)

total_coll_ion_coefficients_with_levels = (
(
level_population_fraction.loc[coll_ion_coeff.index]
* coll_ion_coeff
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
)
.groupby(level=("atomic_number", "ion_number", "level_number"))
.sum()
)
total_coll_recomb_coefficients_with_levels = (
(coll_recomb_coeff)
.groupby(level=("atomic_number", "ion_number", "level_number"))
.sum()
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
)

total_photo_ion_coefficients = (
NLTERateEquationSolver.prepare_coefficient_matrices_excitation(
rate_matrix_index,
total_photo_ion_coefficients,
total_photo_ion_coefficients_with_levels,
)
)
total_rad_recomb_coefficients = (
NLTERateEquationSolver.prepare_coefficient_matrices_excitation(
rate_matrix_index,
total_rad_recomb_coefficients,
total_rad_recomb_coefficients_with_levels,
)
)
total_coll_ion_coefficients = (
NLTERateEquationSolver.prepare_coefficient_matrices_excitation(
rate_matrix_index,
total_coll_ion_coefficients,
total_coll_ion_coefficients_with_levels,
)
)
total_coll_recomb_coefficients = (
NLTERateEquationSolver.prepare_coefficient_matrices_excitation(
rate_matrix_index,
total_coll_recomb_coefficients,
total_coll_recomb_coefficients_with_levels,
)
)

return (
total_photo_ion_coefficients,
total_rad_recomb_coefficients,
Expand Down Expand Up @@ -555,7 +620,11 @@ def deriv_matrix_block(
return np.dot(deriv_matrix, current_ion_number_densities)

def prepare_first_guess(
self, atomic_numbers, number_density, electron_density
self,
rate_matrix_index,
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
atomic_numbers,
number_density,
electron_density,
):
"""Constructs a first guess for ion number densities and electron density, where all species are singly ionized.

Expand All @@ -573,13 +642,12 @@ def prepare_first_guess(
numpy.array
Guess for ion number densities and electron density.
"""
# TODO needs to be changed for excitation
array_size = (number_density.index.values + 1).sum() + 1
first_guess = np.zeros(array_size)
index = 1
first_guess = pd.Series(0.0, index=rate_matrix_index)
for atomic_number in atomic_numbers:
first_guess[index] = number_density.loc[atomic_number]
index += atomic_number + 1
first_guess.loc[(atomic_number, 1)][0] = number_density.loc[
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
atomic_number
]
first_guess = first_guess.values
first_guess[-1] = electron_density
return first_guess

Expand Down Expand Up @@ -699,3 +767,170 @@ def prepare_solution_vector(self, number_density):
)
solution_vector = np.hstack(solution_array + [0])
return solution_vector

@staticmethod
def prepare_coefficient_matrices_excitation(
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
rate_matrix_index,
coeff_matrix_without_exc,
coeff_matrix_with_exc,
):
coeff_array = np.zeros(
(rate_matrix_index.size, coeff_matrix_without_exc.shape[1])
)
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
size = 0
for i in range(rate_matrix_index.size):
if rate_matrix_index[i][2] != "lte_ion":
size += 1
size -= 1
coeff_array = np.zeros((size, coeff_matrix_without_exc.shape[1]))
index = []
row = 0
for i in range(rate_matrix_index.size):
if rate_matrix_index[i][2] == "nlte_ion":
coeff_array[row] = coeff_matrix_without_exc.loc[
rate_matrix_index[i][:-1]
]
index.append(rate_matrix_index[i])
elif (
rate_matrix_index[i][2] == "lte_ion"
or rate_matrix_index[i][2] == "n_e"
):
continue
else:
coeff_array[row] = coeff_matrix_with_exc.loc[
rate_matrix_index[i]
]
index.append(rate_matrix_index[i])
row += 1
index = pd.MultiIndex.from_tuples(
index, names=["atomic_number", "ion_number", "level_number"]
)
coeff_matrix = pd.DataFrame(
coeff_array, columns=coeff_matrix_without_exc.columns, index=index
)
return coeff_matrix

@staticmethod
def main_nlte_calculation_bound_bound(
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
atomic_data,
t_electrons,
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
j_blues,
beta_sobolev,
excitation_species,
nlte_data,
):
"""Calculates a matrix with bound-bound rates for NLTE excitation treatment.

Parameters
----------
atomic_data : Object
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
Atomic data from the atomic datafile.
t_electrons : Numpy Array, dtype float
Electron temperatures.
j_blues : Pandas DataFrame, dtype float
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
J_blue values as calculated in LTE.
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
beta_sobolev : Numpy Array, dtype float
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
Sobolev escape probability
excitation_species : tuple
Species treated in NLTE excitation.
nlte_data : NLTEExcitationData
Data relevant to NLTE exciation species.
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved

Returns
-------
numpy.array
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
Matrix with excitation-deexcitation rates(should be added to NLTE rate matrix for excitation treatment).
"""

number_of_levels = atomic_data.levels.energy.loc[
excitation_species
].count()
lnl = nlte_data.lines_level_number_lower[excitation_species]
lnu = nlte_data.lines_level_number_upper[excitation_species]
(lines_index,) = nlte_data.lines_idx[excitation_species]

try:
j_blues_filtered = j_blues.iloc[lines_index]
except AttributeError:
j_blues_filtered = j_blues
try:
beta_sobolev_filtered = beta_sobolev.iloc[lines_index]
except AttributeError:
beta_sobolev_filtered = beta_sobolev
A_uls = nlte_data.A_uls[excitation_species]
B_uls = nlte_data.B_uls[excitation_species]
B_lus = nlte_data.B_lus[excitation_species]
r_lu_index = lnu * number_of_levels + lnl
r_ul_index = lnl * number_of_levels + lnu
r_ul_matrix = np.zeros(
(number_of_levels, number_of_levels, len(t_electrons)),
dtype=np.float64,
)
r_ul_matrix_reshaped = r_ul_matrix.reshape(
(number_of_levels**2, len(t_electrons))
)
r_ul_matrix_reshaped[r_ul_index] = (
A_uls[np.newaxis].T + B_uls[np.newaxis].T * j_blues_filtered
)
r_ul_matrix_reshaped[r_ul_index] *= beta_sobolev_filtered
r_lu_matrix = np.zeros_like(r_ul_matrix)
r_lu_matrix_reshaped = r_lu_matrix.reshape(
(number_of_levels**2, len(t_electrons))
)
r_lu_matrix_reshaped[r_lu_index] = (
B_lus[np.newaxis].T * j_blues_filtered * beta_sobolev_filtered
)

rates_matrix_bound_bound = r_lu_matrix + r_ul_matrix
for i in range(number_of_levels):
rates_matrix_bound_bound[i, i] = -rates_matrix_bound_bound[
:, i
].sum(axis=0)
rates_matrix_bound_bound[0, :, :] = 1.0
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved
return rates_matrix_bound_bound

# TODO: for tests, do the same thing as for the ionization solver, but only H for excitation treatment
# TODO: beta sobolev needs to be recalculated for each iteration, because it depends on numberdensity
sonachitchyan marked this conversation as resolved.
Show resolved Hide resolved

def calculate_coll_exc_coefficients(
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this really needed? Can you not just do an indexing operation later when you loop over the nlte_excitation_species to build the rate matrices?

Copy link
Member Author

Choose a reason for hiding this comment

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

I was thinking of getting the rates once and just using them afterwards, to be consistent with other rates that we have

Copy link
Contributor

Choose a reason for hiding this comment

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

I still think this is unnecessarily complicated unless you have a solution for creating the collisional rate matrices that does not involve a for loop.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can get rid of it and construct it "on the go" while preparing the rate matrix.

self,
coll_exc_coeff,
coll_deexc_coeff,
nlte_excitation_species,
):
"""Calculates collision coefficients used for NLTE excitation treatment.

Parameters
----------
coll_exc_coeff : pandas.DataFrame, dtype float
Rate coefficient for collisional excitation.
coll_deexc_coeff : pandas.DataFrame, dtype float
Rate coefficient for collisional deexcitation.
nlte_excitation_species : list
List of tuples for (atomic number, ion number) which are treated in NLTE excitation.

Returns
-------
pandas.DataFrame, dtype float
Returns two dataframes, for collision excitation and deexcitation coefficients.
"""
initial_index = pd.MultiIndex.from_tuples(
[] * 4, names=coll_exc_coeff.index.names
)
filtered_coll_exc_coefficients = pd.DataFrame(
columns=coll_exc_coeff.columns, index=initial_index
)
filtered_coll_deexc_coefficients = pd.DataFrame(
columns=coll_exc_coeff.columns, index=initial_index
)
for species in nlte_excitation_species:
subset_exc = coll_exc_coeff.loc[[species[0], species[1]]]
subset_deexc = coll_deexc_coeff.loc[[species[0], species[1]]]
filtered_coll_exc_coefficients = pd.concat(
[filtered_coll_exc_coefficients, subset_exc]
)
filtered_coll_deexc_coefficients = pd.concat(
[filtered_coll_deexc_coefficients, subset_deexc]
)

return filtered_coll_exc_coefficients, filtered_coll_deexc_coefficients
1 change: 1 addition & 0 deletions tardis/plasma/tests/test_nlte_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ def test_critical_case_w0(nlte_raw_plasma_w0):
nlte_raw_plasma_w0.phi,
nlte_raw_plasma_w0.rate_matrix_index,
nlte_raw_plasma_w0.number_density,
nlte_raw_plasma_w0.nlte_excitation_species,
)[0]
ion_number_density_nlte = ion_number_density_nlte.values
ion_number_density_nlte[ion_number_density_nlte < 1e-10] = 0.0
Expand Down