Skip to content

Commit eaf1f0a

Browse files
marco-rudolph-insidetylerflex
authored andcommitted
Add access to field decay values in SimulationData
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
1 parent 7464cfc commit eaf1f0a

File tree

3 files changed

+57
-13
lines changed

3 files changed

+57
-13
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
- Access field decay values in `SimulationData` via `sim_data.field_decay` as `TimeDataArray`.
12+
1013
### Changed
1114
- By default, batch downloads will skip files that already exist locally. To force re-downloading and replace existing files, pass the `replace_existing=True` argument to `Batch.load()`, `Batch.download()`, or `BatchData.load()`.
1215
- The `BatchData.load_sim_data()` function now overwrites any previously downloaded simulation files (instead of skipping them).

tests/test_data/test_sim_data.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,38 @@ def test_final_decay():
229229
assert dv == 0.11
230230

231231

232+
def test_field_decay_array():
233+
sim_data = make_sim_data()
234+
log_extended = (
235+
sim_data.log + "\n- Time step 1392 / time 1.33e-13s ( 19 % done), field decay: 6.58e-01"
236+
)
237+
sim_data = sim_data.copy(update={"log": log_extended})
238+
239+
fd = sim_data.field_decay
240+
steps = fd.coords["t"].values
241+
decay_values = fd.values
242+
243+
assert len(fd) == 2
244+
assert int(steps[0]) == 827
245+
assert int(steps[1]) == 1392
246+
assert float(decay_values[0]) == 0.11
247+
assert float(decay_values[1]) == 0.658
248+
249+
250+
def test_decay_missing_in_log():
251+
sim_data = make_sim_data()
252+
sim_data = sim_data.copy(update={"log": "no regex matches in this log"})
253+
dv = sim_data.final_decay_value
254+
assert dv == 1.0
255+
256+
257+
def test_field_decay_log_none():
258+
sim_data = make_sim_data()
259+
sim_data = sim_data.copy(update={"log": None})
260+
with pytest.raises(DataError):
261+
_ = sim_data.field_decay
262+
263+
232264
def test_to_dict():
233265
sim_data = make_sim_data()
234266
j = sim_data.dict()

tidy3d/components/data/sim_data.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import json
66
import pathlib
7+
import re
78
from abc import ABC
89
from collections import defaultdict
910
from typing import Callable, Optional, Union
@@ -14,7 +15,7 @@
1415
import xarray as xr
1516

1617
from tidy3d.components.autograd.utils import split_list
17-
from tidy3d.components.base import JSON_TAG, Tidy3dBaseModel
18+
from tidy3d.components.base import JSON_TAG, Tidy3dBaseModel, cached_property
1819
from tidy3d.components.base_sim.data.sim_data import AbstractSimulationData
1920
from tidy3d.components.file_util import replace_values
2021
from tidy3d.components.monitor import Monitor
@@ -29,7 +30,7 @@
2930
from tidy3d.exceptions import DataError, FileError, Tidy3dKeyError
3031
from tidy3d.log import log
3132

32-
from .data_array import FreqDataArray
33+
from .data_array import FreqDataArray, TimeDataArray
3334
from .monitor_data import AbstractFieldData, FieldTimeData, MonitorDataType, MonitorDataTypes
3435

3536
DATA_TYPE_MAP = {data.__fields__["monitor"].type_: data for data in MonitorDataTypes}
@@ -931,21 +932,29 @@ class SimulationData(AbstractYeeGridSimulationData):
931932
description="A boolean flag denoting whether the simulation run diverged.",
932933
)
933934

934-
@property
935-
def final_decay_value(self) -> float:
936-
"""Returns value of the field decay at the final time step."""
935+
@cached_property
936+
def field_decay(self) -> TimeDataArray:
937+
"""Returns a TimeDataArray of field decay values over time steps."""
937938
log_str = self.log
938939
if log_str is None:
939940
raise DataError(
940-
"No log string in the SimulationData object, can't find final decay value."
941+
"No log string in the SimulationData object, can't extract field decay."
941942
)
942-
lines = log_str.split("\n")
943-
decay_lines = [line for line in lines if "field decay" in line]
944-
final_decay = 1.0
945-
if len(decay_lines) > 0:
946-
final_decay_line = decay_lines[-1]
947-
final_decay = float(final_decay_line.split("field decay: ")[-1])
948-
return final_decay
943+
944+
matches = re.findall(r"- Time step\s+(\d+)\s+/.*?field decay:\s*([0-9.eE+-]+)", log_str)
945+
946+
steps = [int(m[0]) for m in matches]
947+
decays = [float(m[1]) for m in matches]
948+
return TimeDataArray(decays, coords={"t": steps})
949+
950+
@property
951+
def final_decay_value(self) -> float:
952+
"""Returns value of the field decay at the final time step."""
953+
field_decay = self.field_decay
954+
if len(field_decay) == 0:
955+
log.warning("No field decay values found, using 1.0 as final decay value.")
956+
return 1.0
957+
return float(field_decay.values[-1])
949958

950959
def source_spectrum(self, source_index: int) -> Callable:
951960
"""Get a spectrum normalization function for a given source index."""

0 commit comments

Comments
 (0)