def assign_memory(self, n): VarService.assign_memory(self, n) self.t_final = np.zeros_like(self.v) self.v_event = np.zeros_like(self.v) self.u_last = np.zeros_like(self.v) self.z = np.zeros_like(self.v) if isinstance(self.t_ext.v, (int, float)): self.t_ext.v = np.ones_like(self.u.v) * self.t_ext.v
def set(self, pos, attr, value): """ Set attributes of the BaseParam class to new values at the given positions. Parameters ---------- pos : int, list of integers Positions in arrays where the values should be set attr : 'v', 'vin' Name of the attribute to be set value : str, float or list of above New values """ if not isinstance(pos, Iterable): pos = [pos] if isinstance(self.__dict__[attr], list): for ii, p in enumerate(pos): val = self._sanitize(value[ii]) self.__dict__[attr][p] = val else: new_vals = np.zeros_like(value) for ii, p in enumerate(pos): new_vals[ii] = self._sanitize(value[ii]) self.__dict__[attr][:] = new_vals
def v(self): if not self._eval: self._v = np.zeros_like(self.u.v, dtype=float) if not self.cache or (not self._eval): self._v[:] = self.func(self.u.v) self._eval = True return self._v
def v(self): new = False if self._v is None: new = True self._v = np.zeros_like(self.param1.v, dtype=float) if not self.cache or new: self._v[:] = self.func(self.param1.v, self.param2.v) return self._v
def v(self): new = False if self._v is None: self._v = np.zeros_like(self.indexer.v, dtype=float) new = True if not self.cache or new: self._v[:] = np.array( [0 if i == self.to_flag else 1 for i in self.indexer.v]) return self._v
def check(self): """ Check the bounds and equality conditions. """ if not self.enable: return def _not_all_close(a, b): return np.logical_not(np.isclose(a, b)) if self._v is None: self._v = np.zeros_like(self.u.v) checks = [(self.lower, np.less_equal, "violation of the lower limit", "limit"), (self.upper, np.greater_equal, "violation of the upper limit", "limit"), (self.equal, _not_all_close, 'should be equal', "expected"), (self.not_equal, np.equal, 'should not be equal', "not expected")] for check in checks: limit = check[0] func = check[1] text = check[2] text2 = check[3] if limit is None: continue self.v[:] = np.logical_or(self.v, func(self.u.v, limit.v)) pos = np.argwhere(func(self.u.v, limit.v)).ravel() if len(pos) == 0: continue idx = [self.owner.idx.v[i] for i in pos] lim_v = limit.v * np.ones(self.n) title = f'{self.owner.class_name} {self.info} {text}.' err_dict = OrderedDict([ ('idx', idx), ('values', self.u.v[pos]), (f'{text2}', lim_v[pos]), ]) data = list(map(list, zip(*err_dict.values()))) tab = Tab(title=title, data=data, header=list(err_dict.keys())) if self.error_out: logger.error(tab.draw()) else: logger.warning(tab.draw()) self.v[:] = np.logical_not(self.v)
def v(self): new = False if self._v is None: self._v = np.zeros_like(self.u.v, dtype=float) new = True if not self.cache or new: # need to do it element-wise since `self.u.v` can be a list self._v[:] = np.array([self.flag if i == self.value else self.flag_neg for i in self.u.v]) return self._v
def v(self): new = False if self._v is None or not self.cache: self._v = np.zeros_like(self.old_val.v, dtype=float) new = True if not self.cache or new: new_v = self.new_val.v * np.ones_like(self.old_val.v) flt = self.filter(self.old_val.v) self._v[:] = new_v * flt + self.old_val.v * (1 - flt) return self._v
def v(self): if not self._eval: self._v = np.zeros_like(self.u.v, dtype=float) if not self.cache or (not self._eval): cond_out = self.func(self.u.v) self._v[:] = np.array( [self.flag if i == 1 else self.flag_neg for i in cond_out]) self._eval = True return self._v
def check(self, **kwargs): out = np.zeros_like(self.v) for idx, (bus, bus1, bus2) in enumerate(zip(self.bus.v, self.bus1.v, self.bus2.v)): if bus == bus1: out[idx] = 1 elif bus == bus2: out[idx] = -1 else: raise ValueError(f"bus {bus} is terminal of the line connecting {bus1} and {bus2}. " f"Check the data of {self.bus.owner.class_name}.{self.bus.name}") return out
def store_sparse_pattern(self, models: Optional[Union[str, List, OrderedDict]] = None): """ Collect and store the sparsity pattern of Jacobian matrices. This is a runtime function specific to cases. Notes ----- For `gy` matrix, always make sure the diagonal is reserved. It is a safeguard if the modeling user omitted the diagonal term in the equations. """ models = self._get_models(models) self._call_models_method('store_sparse_pattern', models) # add variable jacobian values for jname in jac_names: ii, jj, vv = list(), list(), list() if jname == 'gy': ii.extend(np.arange(self.dae.m)) jj.extend(np.arange(self.dae.m)) vv.extend(np.zeros(self.dae.m)) for mdl in models.values(): for row, col, val in mdl.triplets.zip_ijv(jname): ii.extend(row) jj.extend(col) vv.extend(np.zeros_like(row)) for row, col, val in mdl.triplets.zip_ijv(jname + 'c'): # process constant Jacobians separately ii.extend(row) jj.extend(col) vv.extend(val * np.ones_like(row)) if len(ii) > 0: ii = np.array(ii, dtype=int) jj = np.array(jj, dtype=int) vv = np.array(vv, dtype=float) self.dae.store_sparse_ijv(jname, ii, jj, vv) self.dae.build_pattern(jname)
def set_all(self, attr, value): """ Set attributes of the BaseParam class to new values for all positions. Parameters ---------- attr : 'v', 'vin' Name of the attribute to be set value : list of str, float or int New values """ if len(value) != self.n: raise ValueError("Value length does not match parameter numbers") if isinstance(self.__dict__[attr], list): for ii, val in enumerate(value): val = self._sanitize(val) self.__dict__[attr][ii] = val else: new_vals = np.zeros_like(value) for ii, val in enumerate(value): new_vals[ii] = self._sanitize(val) self.__dict__[attr][:] = new_vals
def init(self): """ Initialize the status, storage and values for TDS. Returns ------- array-like The initial values of xy. """ t0, _ = elapsed() system = self.system if self.initialized: return system.dae.xy self.reset() self._load_pert() # restore power flow solutions system.dae.x[:len(system.PFlow.x_sol)] = system.PFlow.x_sol system.dae.y[:len(system.PFlow.y_sol)] = system.PFlow.y_sol # Note: # calling `set_address` on `system.exist.pflow_tds` will point all variables # to the new array after extending `dae.y`. system.set_address(models=system.exist.pflow_tds) system.set_dae_names(models=system.exist.tds) system.dae.clear_ts() system.store_sparse_pattern(models=system.exist.pflow_tds) system.store_adder_setter(models=system.exist.pflow_tds) system.store_no_check_init(models=system.exist.pflow_tds) system.vars_to_models() system.init(system.exist.tds, routine='tds') # only store switch times when not replaying CSV data if self.data_csv is None: system.store_switch_times(system.exist.tds) # Build mass matrix into `self.Teye` self.Teye = spdiag(system.dae.Tf.tolist()) self.qg = np.zeros(system.dae.n + system.dae.m) self.initialized = True # test if residuals are close enough to zero if self.config.test_init: self.test_ok = self.test_init() # discard initialized values and use that from CSV if provided if self.data_csv is not None: system.dae.x[:] = self.data_csv[0, 1:system.dae.n + 1] system.dae.y[:] = self.data_csv[0, system.dae.n + 1:system.dae.n + system.dae.m + 1] system.vars_to_models() # connect to data streaming server if system.streaming.dimec is None: system.streaming.connect() if system.config.dime_enabled: # send out system data using DiME self.streaming_init() self.streaming_step() # if `dae.n == 1`, `calc_h_first` depends on new `dae.gy` self.calc_h() # allocate for internal variables self.x0 = np.zeros_like(system.dae.x) self.y0 = np.zeros_like(system.dae.y) self.f0 = np.zeros_like(system.dae.f) _, s1 = elapsed(t0) logger.info("Initialization for dynamics completed in %s.", s1) if self.test_ok is True: logger.info("Initialization was successful.") elif self.test_ok is False: logger.error("Initialization failed!!") else: logger.warning("Initialization results were not verified.") if system.dae.n == 0: tqdm.write('No differential equation detected.') return system.dae.xy