1- from typing import Dict , Optional
1+ from typing import Dict , Optional , Sequence
22import datetime
33import numpy as np
44
@@ -309,12 +309,12 @@ def _update_3d_fields(self):
309309 Ey [1 :- 1 , :, 1 :- 1 ] = factor_ey * Ey [1 :- 1 , :, 1 :- 1 ] + source_ey * (curlH_y )
310310 Ez [:, 1 :- 1 , 1 :- 1 ] = factor_ez * Ez [:, 1 :- 1 , 1 :- 1 ] + source_ez * (curlH_z )
311311
312- def initialize_simulation (self , save = True , live = True , axis_scale = [- 1 ,1 ], save_animation = False ,
313- animation_filename = 'fdtd_animation.mp4' , clean_visualization = True ,
312+ def initialize_simulation (self , save = True , live = True , axis_scale = [- 1 ,1 ], save_animation = False ,
313+ animation_filename = 'fdtd_animation.mp4' , clean_visualization = True ,
314314 save_fields = None , decimate_save = 1 , accumulate_power = False ,
315- save_memory_mode = False ):
315+ save_memory_mode = False , fields_to_cache : Optional [ Sequence [ str ]] = None ):
316316 """Initialize the simulation before running steps.
317-
317+
318318 Args:
319319 save: Whether to save field data at each step.
320320 live: Whether to show live animation of the simulation.
@@ -325,14 +325,16 @@ def initialize_simulation(self, save=True, live=True, axis_scale=[-1,1], save_an
325325 decimate_save: Save only every nth time step (1 = save all, 10 = save every 10th step)
326326 accumulate_power: Instead of saving all fields, accumulate power and save that
327327 save_memory_mode: If True, avoid storing all field data and only keep monitors/power
328+ fields_to_cache: Fields that should always be cached (complex values preserved)
328329 """
329330 # Set default save_fields based on dimensionality
330331 if save_fields is None :
331332 if self .is_3d :
332333 save_fields = ['Ex' , 'Ey' , 'Ez' , 'Hx' , 'Hy' , 'Hz' ]
333334 else :
334335 save_fields = ['Ez' , 'Hx' , 'Hy' ]
335-
336+ self ._cache_fields = list (fields_to_cache ) if fields_to_cache else []
337+
336338 # Record start time
337339 self .start_time = datetime .datetime .now ()
338340 # Initialize simulation state
@@ -344,11 +346,15 @@ def initialize_simulation(self, save=True, live=True, axis_scale=[-1,1], save_an
344346 self ._decimate_save = decimate_save
345347 self ._live = live
346348 self ._axis_scale = axis_scale
347-
349+
350+ # Reset stored results for a new run
351+ for key in list (self .results .keys ()):
352+ self .results [key ] = []
353+
348354 # Save mode flags as class attributes for monitor access
349355 self .save_memory_mode = save_memory_mode
350356 self .accumulate_power = accumulate_power
351-
357+
352358 # Display simulation header and parameters
353359 sim_params = {
354360 "Domain size" : f"{ self .design .width :.2e} x { self .design .height :.2e} m" ,
@@ -392,9 +398,10 @@ def initialize_simulation(self, save=True, live=True, axis_scale=[-1,1], save_an
392398 self ._effective_save_freq = save_freq * decimate_save
393399
394400 # If in save_memory_mode, clear any existing results to start fresh
395- if save_memory_mode :
401+ if save_memory_mode and not self . _cache_fields :
396402 for field in self .results :
397- if field != 't' : self .results [field ] = []
403+ if field != 't' :
404+ self .results [field ] = []
398405 display_status ("Memory-saving mode active: Only storing monitor data and/or power accumulation" , "info" )
399406
400407 def step (self ) -> bool :
@@ -429,14 +436,29 @@ def finalize_simulation(self):
429436 # Display memory usage estimate
430437 memory_usage = self .estimate_memory_usage (time_steps = self .num_steps , save_fields = self ._save_fields )
431438 display_status (f"Estimated memory usage: { memory_usage ['Full simulation' ]['Total memory (MB)' ]:.2f} MB" , "info" )
439+ objective_results : Dict [str , float ] = {}
440+ for idx , monitor in enumerate (self .monitors ):
441+ if hasattr (monitor , 'evaluate_objective' ):
442+ value = monitor .evaluate_objective ()
443+ else :
444+ value = None
445+ if value is None :
446+ continue
447+ key = getattr (monitor , 'name' , None ) or f"monitor_{ idx } "
448+ objective_results [key ] = value
449+ if objective_results :
450+ self .results ['objectives' ] = objective_results
451+ else :
452+ self .results .pop ('objectives' , None )
453+ self .last_objectives = objective_results
432454 return self .results
433455
434- def run (self , steps : Optional [int ] = None , save = True , live = True , axis_scale = [- 1 ,1 ], save_animation = False ,
435- animation_filename = 'fdtd_animation.mp4' , clean_visualization = True ,
456+ def run (self , steps : Optional [int ] = None , save = True , live = True , axis_scale = [- 1 ,1 ], save_animation = False ,
457+ animation_filename = 'fdtd_animation.mp4' , clean_visualization = True ,
436458 save_fields = None , decimate_save = 1 , accumulate_power = False ,
437- save_memory_mode = False ) -> Dict :
459+ save_memory_mode = False , fields_to_cache : Optional [ Sequence [ str ]] = None ) -> Dict :
438460 """Run the complete simulation using the new step-by-step approach.
439-
461+
440462 Args:
441463 steps: Number of steps to run. If None, run until the end of the time array.
442464 save: Whether to save field data at each step.
@@ -448,18 +470,20 @@ def run(self, steps: Optional[int] = None, save=True, live=True, axis_scale=[-1,
448470 decimate_save: Save only every nth time step (1 = save all, 10 = save every 10th step)
449471 accumulate_power: Instead of saving all fields, accumulate power and save that
450472 save_memory_mode: If True, avoid storing all field data and only keep monitors/power
451-
473+ fields_to_cache: Fields that should always be cached even when memory saving
474+
452475 Returns:
453476 Dictionary containing the simulation results.
454477 """
455478 # Initialize the simulation
456- self .initialize_simulation (save = save , live = live , axis_scale = axis_scale ,
457- save_animation = save_animation ,
479+ self .initialize_simulation (save = save , live = live , axis_scale = axis_scale ,
480+ save_animation = save_animation ,
458481 animation_filename = animation_filename ,
459482 clean_visualization = clean_visualization ,
460483 save_fields = save_fields , decimate_save = decimate_save ,
461- accumulate_power = accumulate_power ,
462- save_memory_mode = save_memory_mode )
484+ accumulate_power = accumulate_power ,
485+ save_memory_mode = save_memory_mode ,
486+ fields_to_cache = fields_to_cache )
463487
464488 # Run the simulation with progress tracking
465489 with create_rich_progress () as progress :
0 commit comments