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

New feature: eigenfunction subset #75

Merged
merged 43 commits into from
Sep 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
d14ca83
added eigenfunction subset switches
n-claes Jul 30, 2021
3a76f53
rework of eigenfunction module to support subset selection
n-claes Aug 3, 2021
cf7acf1
saved subset info to file + updated pylbo reader
n-claes Aug 4, 2021
b73999a
pylbo: updated eigenfunction plotting to new subset data
n-claes Aug 4, 2021
257782d
added subset test datasets + updated loading tests for pylbo
n-claes Aug 5, 2021
3f76bcc
pylbo: added eigenfunction subset tests + subset bugfix in data conta…
n-claes Aug 5, 2021
116169c
added regression tests for ef subset data
n-claes Aug 5, 2021
38c84bc
removed old mod_eigenfunctions
n-claes Aug 5, 2021
6bf9e22
moved postprocessing to eigenfunctions directory + renamed
n-claes Aug 5, 2021
af2dd3c
refactoring post_processed -> derived eigenfunctions to avoid confusion
n-claes Aug 5, 2021
4decb7b
added is_zero function to mod_check_values
n-claes Aug 5, 2021
4ba83c9
updated & cleaned eigenfunction initialisation routines
n-claes Aug 5, 2021
d768053
reworked interpolation logic for derived eigenfunction quantities
n-claes Aug 5, 2021
86e4898
simplified entropy calculation routine
n-claes Aug 5, 2021
757fb63
extracted eigenfunction operations into new submodule
n-claes Aug 5, 2021
4a80276
simplified velocity divergence eigenfunction routine
n-claes Aug 5, 2021
f071c8f
simplified velocity curl eigenfunction routine
n-claes Aug 5, 2021
1368cd0
simplified parallel/perp velocity curl components in eigenfunctions
n-claes Aug 6, 2021
103fdea
simplified magnetic field eigenfunction components
n-claes Aug 6, 2021
cd4312f
simplified div(B) eigenfunction calculation
n-claes Aug 6, 2021
049a9ec
simplified curl(B) eigenfunction calculation
n-claes Aug 10, 2021
606d2b4
simplified vpara/vperp eigenfunction calculation
n-claes Aug 10, 2021
4e6f72b
compilation fixes and minor edits
n-claes Aug 12, 2021
b15f3e8
modified interpolation routine to allow for optional out-of-array loo…
n-claes Aug 13, 2021
da0f237
minor refactoring & cleaning
n-claes Aug 13, 2021
4f03f60
pylbo: minor bugfixes in plotting pp quantities
n-claes Aug 13, 2021
1145f03
pylbo: updates to datfile reader
n-claes Aug 13, 2021
87360ce
fix weird compilation error
n-claes Aug 13, 2021
00dede2
added regression test for derived ef quantities
n-claes Aug 13, 2021
581f2fb
cleanup of entropy and div(v) routines
n-claes Aug 13, 2021
543a1c1
cleanup of derived eigenfunction quantities submodule
n-claes Aug 13, 2021
3a44d50
segfault bugfix when accessing eigenfunction arrays
n-claes Aug 16, 2021
733f383
added docstrings to new routines
n-claes Aug 16, 2021
837f4d0
refactored some module names
n-claes Aug 16, 2021
c4a338f
moved pp quantities to dedicated submodule
n-claes Aug 16, 2021
c9b19e3
added unit tests for new spline functions & valuechecks
n-claes Aug 16, 2021
0657f94
cleaned up unnecessary before routine calls during unit testing
n-claes Aug 16, 2021
87110f1
bugfix array access pp quantities
n-claes Aug 16, 2021
29c62a0
added unit tests for eigenfunctions
n-claes Aug 16, 2021
cffb164
unit tests for eigenfunction subset selection
n-claes Aug 16, 2021
e227766
pylbo: added unit tests for derived eigenfunctions
n-claes Aug 17, 2021
27a174d
pylbo: refactored postprocessed -> derived eigenfunctions
n-claes Aug 17, 2021
f862e0b
implemented custom findloc function for gfortran <9.0 compatibility
n-claes Aug 21, 2021
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ test_legolas
*.egg*
!/tests/regression_tests/answers/*.dat
!/tests/regression_tests/answers/*.log
!/tests/pylbo_tests/utility_files/*.dat
!/tests/pylbo_tests/utility_files/*.log

5 changes: 4 additions & 1 deletion post_processing/pylbo/automation/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@
"savelist": [
("write_matrices", bool),
("write_eigenfunctions", bool),
("write_postprocessed", bool),
("write_derived_eigenfunctions", bool),
("show_results", bool),
("basename_datfile", str),
("basename_logfile", str),
("output_folder", str),
("logging_level", (int, np.integer)),
("dry_run", bool),
("write_eigenfunction_subset", bool),
("eigenfunction_subset_center", complex),
("eigenfunction_subset_radius", (int, np.integer, float)),
],
"physicslist": [
("mhd_gamma", float),
Expand Down
94 changes: 53 additions & 41 deletions post_processing/pylbo/data_containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
read_matrix_A,
read_ef_grid,
read_eigenfunction,
read_postprocessed,
read_derived_eigenfunction,
)
from pylbo.utilities.logger import pylboLogger
from pylbo.exceptions import MatricesNotPresent
Expand Down Expand Up @@ -90,11 +90,11 @@ def ef_names(self):
pass

@abstractmethod
def pp_written(self):
def derived_efs_written(self):
pass

@abstractmethod
def pp_names(self):
def derived_ef_names(self):
pass

@abstractmethod
Expand Down Expand Up @@ -254,29 +254,41 @@ def ef_grid(self):
return None

@property
def pp_written(self):
def ef_subset(self):
"""
Checks if post-processed quantities are present.
Checks if dataset contains a subset of the eigenfunctions

Returns
-------
pp_written : bool
If `True`, post-processed quantities are present in the datfile.
bool
`True` if subset present, `False` otherwise
"""
return self.header["postprocessed_written"]
return self.header["eigenfunction_subset_used"]

@property
def pp_names(self):
def derived_efs_written(self):
"""
Retrieves the post-processed quantity names.
Checks if derived eigenfunctions are present.

Returns
-------
pp_names : numpy.ndarray
Array containing the names of the post-processed quantities as strings.
None if no post-processed quantities are present.
bool
If `True`, derived eigenfunctions are present in the datfile.
"""
return self.header.get("pp_names", None)
return self.header["derived_eigenfuncs_written"]

@property
def derived_ef_names(self):
"""
Retrieves the derived eigenfunction names.

Returns
-------
numpy.ndarray
Array containing the names of the derived eigenfunctions as strings.
None if no derived eigenfunctions are present.
"""
return self.header.get("derived_ef_names", None)

@staticmethod
def _get_values(array, which_values):
Expand Down Expand Up @@ -554,13 +566,14 @@ def get_eigenfunctions(self, ev_guesses=None, ev_idxs=None):
with open(self.datfile, "rb") as istream:
for dict_idx, ef_idx in enumerate(idxs):
efs = read_eigenfunction(istream, self.header, ef_idx)
efs.update({"eigenvalue": self.eigenvalues[ef_idx]})
if efs is not None:
efs.update({"eigenvalue": self.eigenvalues[ef_idx]})
eigenfuncs[dict_idx] = efs
return eigenfuncs

def get_postprocessed(self, ev_guesses=None, ev_idxs=None):
def get_derived_eigenfunctions(self, ev_guesses=None, ev_idxs=None):
"""
Returns the post-processed quantities based on given eigenvalue guesses or their
Returns the derived eigenfunctions based on given eigenvalue guesses or their
indices. An array will be returned where every item is a dictionary, containing
both the eigenvalue and its quantities. Either eigenvalue guesses or
indices can be supplied, but not both.
Expand All @@ -574,31 +587,30 @@ def get_postprocessed(self, ev_guesses=None, ev_idxs=None):

Returns
-------
postprocessed : numpy.ndarray(dtype=dict, ndim=1)
Array containing the post-processed quantities and eigenvalues
numpy.ndarray(dtype=dict, ndim=1)
Array containing the derived eigenfunctions and eigenvalues
corresponding to the supplied indices. Every index in this array
contains a dictionary with the post-processed quantities and
contains a dictionary with the derived eigenfunctions and
corresponding eigenvalue. The keys of each dictionary are the
post-processed quantity names.
corresponding eigenfunction names.
"""
if ev_guesses is not None and ev_idxs is not None:
raise ValueError(
"get_postprocessed: either provide guesses or indices but not both"
)
raise ValueError("either provide guesses or indices but not both")
if ev_guesses is not None:
idxs, _ = self.get_nearest_eigenvalues(ev_guesses)
else:
idxs = transform_to_numpy(ev_idxs)
for idx in idxs:
if not isinstance(idx, (int, np.int64)):
raise ValueError("get_postprocessed: ev_idxs should be integers")
postprocessed = np.array([{}] * len(idxs), dtype=dict)
raise ValueError("ev_idxs should be integers")
derived_efs = np.array([{}] * len(idxs), dtype=dict)
with open(self.datfile, "rb") as istream:
for dict_idx, pp_idx in enumerate(idxs):
ppq = read_postprocessed(istream, self.header, pp_idx)
ppq.update({"eigenvalue": self.eigenvalues[pp_idx]})
postprocessed[dict_idx] = ppq
return postprocessed
for dict_idx, ef_idx in enumerate(idxs):
defs = read_derived_eigenfunction(istream, self.header, ef_idx)
if defs is not None:
defs.update({"eigenvalue": self.eigenvalues[ef_idx]})
derived_efs[dict_idx] = defs
return derived_efs

def get_nearest_eigenvalues(self, ev_guesses):
"""
Expand Down Expand Up @@ -701,29 +713,29 @@ def ef_grid(self):
return np.array([ds.ef_grid for ds in self.datasets], dtype=object)

@property
def pp_written(self):
def derived_efs_written(self):
"""
Checks if the post-processed quantities are written.
Checks if the derived eigenfunctions are written.

Returns
-------
pp_written : numpy.ndarray
numpy.ndarray(dtype=bool)
An array of bools corresponding to the various datasets, `True` if a
dataset has post-processed quantities present.
dataset has derived eigenfunctions present.
"""
return np.array([ds.pp_written for ds in self.datasets])
return np.array([ds.derived_efs_written for ds in self.datasets])

@property
def pp_names(self):
def derived_ef_names(self):
"""
Returns the post-processed quantity names.
Returns the derived eigenfunction names.

Returns
-------
pp_names : numpy.ndarray
An array with the post-processed quantity names as strings.
numpy.ndarray(dtype=str)
An array with the derived eigenfunction names as strings.
"""
names = np.array([ds.pp_names for ds in self.datasets], dtype=object)
names = np.array([ds.derived_ef_names for ds in self.datasets], dtype=object)
for item in names:
if item is None:
continue
Expand Down
18 changes: 0 additions & 18 deletions post_processing/pylbo/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,24 +47,6 @@ def __str__(self):
return f"{self.msg}"


class PostprocessedNotPresent(LegolasException):
"""
Handles trying to query for post-processed quantities when these
are not present in the datfile.

Parameters
----------
msg : str
The error message to pass on.
"""

def __init__(self, msg):
self.msg = msg

def __str__(self):
return f"{self.msg}"


class MatricesNotPresent(LegolasException):
"""
Handles trying to query for matrices when these
Expand Down
32 changes: 17 additions & 15 deletions post_processing/pylbo/file_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,14 @@ def load(datfile):
pylboLogger.info("matrices present in datfile")
if ds.header["eigenfuncs_written"]:
pylboLogger.info("eigenfunctions present in datfile")
if ds.header.get("postprocessed_written", False):
pylboLogger.info("post-processed quantities present in datfile")
if ds.header.get("derived_eigenfuncs_written", False):
pylboLogger.info("derived eigenfunctions present in datfile")
if ds.header.get("eigenfunction_subset_used", False):
saved_efs = len(ds.header["ef_written_idxs"])
total_efs = len(ds.eigenvalues)
pylboLogger.info(
f"subset saved: {saved_efs}/{total_efs} eigenvalues have eigenfunctions"
)
pylboLogger.info("-" * 75)
return ds

Expand Down Expand Up @@ -150,22 +156,18 @@ def load_series(datfiles):
if efs_present.pop():
pylboLogger.info("eigenfunctions present in all datfiles")

# check presence of post-processed quantities
pp_present = set(
[ds.header.get("postprocessed_written", False) for ds in series.datasets]
# check presence of derived eigenfunctions
defs_present = set(
[ds.header.get("derived_eigenfuncs_written", False) for ds in series.datasets]
)
if len(pp_present) == 0:
pylboLogger.info("no post-processed quantities present")
elif len(pp_present) > 1:
pylboLogger.info(
"post-processed quantities present in some datfiles, but not all"
)
if len(defs_present) == 0:
pylboLogger.info("no derived eigenfunctions present")
elif len(defs_present) > 1:
pylboLogger.info("derived eigenfunctions present in some datfiles, but not all")
else:
if pp_present.pop():
pylboLogger.info("post-processed quantities present in all datfiles")

if defs_present.pop():
pylboLogger.info("derived eigenfunctions present in all datfiles")
pylboLogger.info("-" * 75)

return series


Expand Down
Loading