From 602e7e4ed5ff455ed35fdb0b8253d41a6a0a5fd8 Mon Sep 17 00:00:00 2001 From: Christopher Teubert Date: Thu, 19 May 2022 15:22:26 -0700 Subject: [PATCH 1/6] Fixed issue with containers --- src/prog_models/utils/containers.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/prog_models/utils/containers.py b/src/prog_models/utils/containers.py index a732231b5..324dbc73d 100644 --- a/src/prog_models/utils/containers.py +++ b/src/prog_models/utils/containers.py @@ -52,7 +52,9 @@ def __len__(self) -> int: return len(self._keys) def __eq__(self, other : "DictLikeMatrixWrapper") -> bool: - return self._keys == other._keys and (self.matrix == other.matrix).all() + if isinstance(other, dict): + return list(self.keys()) == list(other.keys()) and (self.matrix == np.array([[other[key]] for key in self._keys])).all() + return self.keys() == other.keys() and (self.matrix == other.matrix).all() def __hash__(self): return hash(self.keys) + hash(self.matrix) @@ -60,6 +62,9 @@ def __hash__(self): def __str__(self) -> str: return self.__repr__() + def copy(self) -> "DictLikeMatrixWrapper": + return DictLikeMatrixWrapper(self._keys, self.matrix.copy()) + def keys(self) -> list: return self._keys From f8d7443fe537b10425c43ee7fecd822f437ca722 Mon Sep 17 00:00:00 2001 From: Christopher Teubert Date: Thu, 19 May 2022 15:25:20 -0700 Subject: [PATCH 2/6] fix tuple issue --- src/prog_models/prognostics_model.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/prog_models/prognostics_model.py b/src/prog_models/prognostics_model.py index f594dfbef..c78caf5a1 100644 --- a/src/prog_models/prognostics_model.py +++ b/src/prog_models/prognostics_model.py @@ -1430,17 +1430,30 @@ def simulate_to_threshold(self, future_loading_eqn, first_output = None, thresho if config['dt'] != None: warn("dt is not used in DMD approximation") - if config['save_freq'] == dmd_dt and config['save_pts'] == []: + if ( + config['save_freq'] == dmd_dt or + ( + isinstance(config['save_freq'], tuple) and + config['save_freq'][0]%dmd_dt < 1e-9 and + config['save_freq'][1] == dmd_dt + ) + ) and config['save_pts'] == []: # In this case, the user wants what the DMD approximation returns return results - # In this case, the user wants something different than what the DMD approximation retuns, so we must interpolate # Define time vector based on user specifications time_basic = [results.times[0], results.times[-1]] time_basic.extend(config['save_pts']) if config['save_freq'] != None: - # Add Save Frequency - time_array = np.arange(results.times[0]+config['save_freq'],results.times[-1],config['save_freq']) + if isinstance(config['save_freq'], tuple): + # Tuple used to specify start and frequency + t_step = config['save_freq'][1] + # Use starting time or the next multiple + t_start = config['save_freq'][0] + start = max(t_start, results.times[0] - (results.times[0]-t_start)%t_step) + time_array = np.arange(start+t_step,results.times[-1],t_step) + else: + time_array = np.arange(results.times[0]+config['save_freq'],results.times[-1],config['save_freq']) time_basic.extend(time_array.tolist()) time_interp = sorted(time_basic) From 2a8473b1beec1797e99fc7a7aeac3cb015c716bb Mon Sep 17 00:00:00 2001 From: Christopher Teubert Date: Thu, 19 May 2022 15:27:10 -0700 Subject: [PATCH 3/6] Remove unnecessary deepcopies --- src/prog_models/prognostics_model.py | 8 ++++---- src/prog_models/sim_result.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/prog_models/prognostics_model.py b/src/prog_models/prognostics_model.py index f594dfbef..76c67b915 100644 --- a/src/prog_models/prognostics_model.py +++ b/src/prog_models/prognostics_model.py @@ -1160,10 +1160,10 @@ def generate_surrogate(self, load_functions, method = 'dmd', **kwargs): config.update(kwargs) # List of user-define values to include in surrogate model: - states_dmd = deepcopy(self.states) - inputs_dmd = deepcopy(self.inputs) - outputs_dmd = deepcopy(self.outputs) - events_dmd = deepcopy(self.events) + states_dmd = self.states.copy() + inputs_dmd = self.inputs.copy() + outputs_dmd = self.outputs.copy() + events_dmd = self.events.copy() # Validate user inputs try: diff --git a/src/prog_models/sim_result.py b/src/prog_models/sim_result.py index 77ff7db3e..26b133910 100644 --- a/src/prog_models/sim_result.py +++ b/src/prog_models/sim_result.py @@ -20,7 +20,7 @@ class SimResult(UserList): __slots__ = ['times', 'data'] # Optimization def __init__(self, times : list = [], data : list = []): - self.times = deepcopy(times) + self.times = times.copy() self.data = deepcopy(data) def __eq__(self, other : "SimResult") -> bool: @@ -174,7 +174,7 @@ def __init__(self, fcn : Callable, times : list = [], states : list = []) -> Non data (array(dict)): Data points where data[n] corresponds to times[n] """ self.fcn = fcn - self.times = deepcopy(times) + self.times = times.copy() self.states = deepcopy(states) self.__data = None @@ -207,7 +207,7 @@ def extend(self, other : "LazySimResult") -> None: """ if (isinstance(other, self.__class__)): - self.times.extend(deepcopy(other.times)) # lgtm [py/modification-of-default-value] + self.times.extend(other.times) # lgtm [py/modification-of-default-value] self.states.extend(deepcopy(other.states)) # lgtm [py/modification-of-default-value] if self.__data is None or not other.is_cached(): self.__data = None From ff9c613f64cba564f8007ec3ac65bf11aad05c3c Mon Sep 17 00:00:00 2001 From: Christopher Teubert Date: Mon, 23 May 2022 14:33:26 -0700 Subject: [PATCH 4/6] Fix state copying --- src/prog_models/prognostics_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prog_models/prognostics_model.py b/src/prog_models/prognostics_model.py index dce4b938b..3aa077309 100644 --- a/src/prog_models/prognostics_model.py +++ b/src/prog_models/prognostics_model.py @@ -771,7 +771,7 @@ def simulate_to_threshold(self, future_loading_eqn : Callable, first_output : di t = config['t0'] u = future_loading_eqn(t) if 'x' in config: - x = config['x'] + x = deepcopy(config['x']) else: x = self.initialize(u, first_output) From e4014034f7dadb274007d78d636195871ae40d2e Mon Sep 17 00:00:00 2001 From: Christopher Teubert Date: Tue, 24 May 2022 10:47:11 -0700 Subject: [PATCH 5/6] Clean sim_to_thresh --- src/prog_models/prognostics_model.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/prog_models/prognostics_model.py b/src/prog_models/prognostics_model.py index 3aa077309..a17e852b7 100644 --- a/src/prog_models/prognostics_model.py +++ b/src/prog_models/prognostics_model.py @@ -1409,17 +1409,17 @@ def next_state(self, x, u, _): def simulate_to_threshold(self, future_loading_eqn, first_output = None, threshold_keys = None, **kwargs): # Save keyword arguments same as DMD training for approximation - kwargs_temp = { - 'save_freq': dmd_dt, - 'dt': dmd_dt - } kwargs_sim = kwargs.copy() - kwargs_sim.update(kwargs_temp) + kwargs_sim['save_freq'] = dmd_dt + kwargs_sim['dt'] = dmd_dt # Simulate to threshold at DMD time step results = super().simulate_to_threshold(future_loading_eqn,first_output, threshold_keys, **kwargs_sim) # Interpolate results to be at user-desired time step + if 'dt' in kwargs: + warn("dt is not used in DMD approximation") + # Default parameters config = { 'dt': None, @@ -1427,19 +1427,15 @@ def simulate_to_threshold(self, future_loading_eqn, first_output = None, thresho 'save_pts': [] } config.update(kwargs) - if config['dt'] != None: - warn("dt is not used in DMD approximation") - if ( - config['save_freq'] == dmd_dt or - ( - isinstance(config['save_freq'], tuple) and - config['save_freq'][0]%dmd_dt < 1e-9 and - config['save_freq'][1] == dmd_dt - ) - ) and config['save_pts'] == []: + if (kwargs['save_freq'] == dmd_dt or + (isinstance(kwargs['save_freq'], tuple) and + kwargs['save_freq'][0]%dmd_dt < 1e-9 and + kwargs['save_freq'][1] == dmd_dt) + ) and ('save_pts' not in kwargs or kwargs['save_pts'] == []): # In this case, the user wants what the DMD approximation returns return results + # In this case, the user wants something different than what the DMD approximation retuns, so we must interpolate # Define time vector based on user specifications time_basic = [results.times[0], results.times[-1]] From 5a17a534f7f8d71084fd02841c99fdaec203524f Mon Sep 17 00:00:00 2001 From: Christopher Teubert Date: Tue, 24 May 2022 11:07:58 -0700 Subject: [PATCH 6/6] Fix changes --- src/prog_models/prognostics_model.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/prog_models/prognostics_model.py b/src/prog_models/prognostics_model.py index a17e852b7..ee2a3410b 100644 --- a/src/prog_models/prognostics_model.py +++ b/src/prog_models/prognostics_model.py @@ -1428,11 +1428,11 @@ def simulate_to_threshold(self, future_loading_eqn, first_output = None, thresho } config.update(kwargs) - if (kwargs['save_freq'] == dmd_dt or - (isinstance(kwargs['save_freq'], tuple) and - kwargs['save_freq'][0]%dmd_dt < 1e-9 and - kwargs['save_freq'][1] == dmd_dt) - ) and ('save_pts' not in kwargs or kwargs['save_pts'] == []): + if (config['save_freq'] == dmd_dt or + (isinstance(config['save_freq'], tuple) and + config['save_freq'][0]%dmd_dt < 1e-9 and + config['save_freq'][1] == dmd_dt) + ) and config['save_pts'] == []: # In this case, the user wants what the DMD approximation returns return results