Skip to content

Commit

Permalink
Add options.monitor_update_intverval
Browse files Browse the repository at this point in the history
  • Loading branch information
loganbvh committed Oct 28, 2023
1 parent 80239d6 commit fef4d2f
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 13 deletions.
2 changes: 2 additions & 0 deletions tdgl/solver/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class SolverOptions:
save_every: Save interval in units of solve steps.
progress_interval: Minimum number of solve steps between progress bar updates.
monitor: Plot data in real time as the simulation is running.
monitor_update_interval: The monitor update interval in seconds.
include_screening: Whether to include screening in the simulation.
max_iterations_per_step: The maximum number of screening iterations per solve
step.
Expand All @@ -78,6 +79,7 @@ class SolverOptions:
save_every: int = 100
progress_interval: int = 0
monitor: bool = False
monitor_update_interval: float = 1.0
field_units: str = "mT"
current_units: str = "uA"
include_screening: bool = False
Expand Down
31 changes: 19 additions & 12 deletions tdgl/solver/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ class Runner:
names: Names of the parameters.
data_handler: The data handler used to save to disk.
monitor: Launch a subprocess to plot results during the simulation.
monitor_update_interval: The monitor update interval in seconds.
fixed_values: Values that do not change over time, but should be added
to saved data.
fixed_names: Fixed data variable names.
Expand All @@ -248,6 +249,7 @@ def __init__(
names: Sequence[str],
data_handler: DataHandler,
monitor: bool = False,
monitor_update_interval: float = 1.0,
fixed_values: Union[List[Any], None] = None,
fixed_names: Union[Sequence, None] = None,
running_names_and_sizes: Union[Dict[str, int], None] = None,
Expand Down Expand Up @@ -280,6 +282,7 @@ def __init__(
self.logger = logger if logger is not None else logging.getLogger()
self.data_handler = data_handler
self.monitor = monitor
self.monitor_update_interval = monitor_update_interval

def run(self) -> bool:
"""Run the simulation loop.
Expand Down Expand Up @@ -378,18 +381,6 @@ def save_step(step):
self.state["step"] = i
self.state["time"] = self.time
self.state["dt"] = dt
if save and i == 1 and self.data_handler.tmp_file is not None:
self.data_handler.tmp_file.swmr_mode = True
if self.monitor:
cmd = [
sys.executable,
"-m",
"tdgl.visualize",
"--input",
self.data_handler.output_path,
"monitor",
]
_ = subprocess.Popen(cmd, start_new_session=True)
# Print progress if TQDM is disabled.
if prog_disabled and (i % self.options.progress_interval) == 0:
then, now = now, time.perf_counter()
Expand All @@ -405,6 +396,22 @@ def save_step(step):
if save:
save_step(i)
self.running_state.clear()

# Start the monitor subprocess
if save and i == 0 and self.data_handler.tmp_file is not None:
self.data_handler.tmp_file.swmr_mode = True
if self.monitor:
cmd = [
sys.executable,
"-m",
"tdgl.visualize",
"--input",
self.data_handler.output_path,
"monitor",
"--interval",
str(self.monitor_update_interval),
]
_ = subprocess.Popen(cmd, start_new_session=True)
# Run time step.
function_result = self.function(
self.state,
Expand Down
1 change: 1 addition & 0 deletions tdgl/solver/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,7 @@ def solve(self) -> Optional[Solution]:
options=options,
data_handler=data_handler,
monitor=options.monitor,
monitor_update_interval=options.monitor_update_interval,
initial_values=list(parameters.values()),
names=list(parameters),
fixed_values=fixed_values,
Expand Down
2 changes: 2 additions & 0 deletions tdgl/visualization/animate.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ def create_animation(
2.5 * max(1, num_plots // max_cols),
)
figure_kwargs.setdefault("figsize", default_figsize)
figure_kwargs.setdefault("sharex", True)
figure_kwargs.setdefault("sharey", True)

logger.info(f"Creating animation for {[obs.name for obs in quantities]!r}.")

Expand Down
2 changes: 2 additions & 0 deletions tdgl/visualization/interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ def __init__(
3 * max(1, self.num_plots // self.max_cols),
)
self.figure_kwargs.setdefault("figsize", default_figsize)
self.figure_kwargs.setdefault("sharex", True)
self.figure_kwargs.setdefault("sharey", True)

def show(self):
with h5py.File(self.input_file, "r") as h5file:
Expand Down
10 changes: 9 additions & 1 deletion tdgl/visualization/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
def monitor_solution(
h5path: str,
quantities: Union[str, Sequence[str]] = DEFAULT_QUANTITIES,
update_interval: float = 1.0,
shading: Literal["flat", "gouraud"] = "gouraud",
max_cols: int = 4,
dimensionless: bool = False,
Expand All @@ -28,6 +29,7 @@ def monitor_solution(
h5path: Path to the temporary HDF5 file generated when running
the solver with options.monitor=True
quantities: The names of the quantities to animate
update_interval: The update interval in seconds
shading: Shading method, "flat" or "gouraud". See matplotlib.pyplot.tripcolor.
dimensionless: Use dimensionless units for axes
xlim: x-axis limits
Expand Down Expand Up @@ -57,6 +59,8 @@ def monitor_solution(
3.0 * max(1, num_plots // max_cols),
)
figure_kwargs.setdefault("figsize", default_figsize)
figure_kwargs.setdefault("sharex", True)
figure_kwargs.setdefault("sharey", True)

with h5py.File(h5path, "r", swmr=True, libver="latest") as h5file:
device = Device.from_hdf5(h5file["solution/device"])
Expand Down Expand Up @@ -102,6 +106,10 @@ def monitor_solution(
ax.set_xlim(xlim)
ax.set_ylim(ylim)

fig.suptitle("Step: 0")
fig.canvas.draw_idle()
fig.canvas.start_event_loop(update_interval)

Check warning on line 111 in tdgl/visualization/monitor.py

View check run for this annotation

Codecov / codecov/patch

tdgl/visualization/monitor.py#L109-L111

Added lines #L109 - L111 were not covered by tests

vmins = [+np.inf for _ in quantities]
vmaxs = [-np.inf for _ in quantities]

Expand Down Expand Up @@ -145,7 +153,7 @@ def update():
collection.set_array(values)
collection.set_clim(vmins[i], vmaxs[i])
fig.canvas.draw_idle()
fig.canvas.start_event_loop(1e-3)
fig.canvas.start_event_loop(update_interval)

Check warning on line 156 in tdgl/visualization/monitor.py

View check run for this annotation

Codecov / codecov/patch

tdgl/visualization/monitor.py#L156

Added line #L156 was not covered by tests

try:
while True:
Expand Down
2 changes: 2 additions & 0 deletions tdgl/visualization/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ def generate_snapshots(
2.5 * max(1, num_plots // max_cols),
)
figure_kwargs.setdefault("figsize", default_figsize)
figure_kwargs.setdefault("sharex", True)
figure_kwargs.setdefault("sharey", True)

solution = Solution.from_hdf5(input_path)
device = solution.device
Expand Down
4 changes: 4 additions & 0 deletions tdgl/visualize.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ def make_parser() -> argparse.ArgumentParser:
monitor_parser = subparsers.add_parser(
"monitor", help="Visualize the results of a simulation as it is running."
)
monitor_parser.add_argument(
"--interval", type=float, default=1, help="Monitor update interval in seconds."
)
monitor_parser.add_argument(*quantities_args, **quantities_kwargs)
monitor_parser.set_defaults(func=monitor_tdgl)

Expand Down Expand Up @@ -201,6 +204,7 @@ def monitor_tdgl(args: argparse.Namespace) -> None:
h5path = os.path.join(dirname, fname)
kwargs = dict(
h5path=h5path,
update_interval=args.interval,
shading=args.shading,
xlim=args.xlim,
ylim=args.ylim,
Expand Down

0 comments on commit fef4d2f

Please sign in to comment.