def calc_state_matrix(self): r""" Return state matrix and store to ``self.As``. Notes ----- For systems with the form .. math :: T \dot{x} = f(x, y) \\ 0 = g(x, y) The state matrix is calculated from .. math :: A_s = T^{-1} (f_x - f_y * g_y^{-1} * g_x) Returns ------- cvxopt.matrix state matrix """ system = self.system gyx = matrix(system.dae.gx) self.solver.linsolve(system.dae.gy, gyx) Tfnz = system.dae.Tf + np.ones_like(system.dae.Tf) * np.equal( system.dae.Tf, 0.0) iTf = spdiag((1 / Tfnz).tolist()) self.As = matrix(iTf * (system.dae.fx - system.dae.fy * gyx)) return self.As
def warn_init_limit(self): """ Warn if initialized at limits. """ if self.no_warn: return for f, limit in self.warn_flags: if f not in self.export_flags: logger.error(f'warn_flags contain unknown flag {f}') continue pos = np.argwhere(np.not_equal(self.__dict__[f], 0)).ravel() if not len(pos): continue err_msg = f'{self.owner.class_name}.{self.name} {self.__dict__[limit].name} at limits' if isinstance(self.__dict__[limit].v, np.ndarray): lim_value = self.__dict__[limit].v[pos] else: lim_value = self.__dict__[limit].v err_data = { 'idx': [self.owner.idx.v[i] for i in pos], 'Flag': [f] * len(pos), 'Input Value': self.u.v[pos], 'Limit': lim_value * np.ones_like(pos), } tab = Tab(title=err_msg, header=err_data.keys(), data=list(map(list, zip(*err_data.values())))) logger.warning(tab.draw())
def to_array(self): """ Converts field ``v`` to the NumPy array type. to enable array-based calculation. Must be called after adding all elements. Store a copy of original input values to field ``vin``. Set ``pu_coeff`` to all ones. Warnings -------- After this call, `add` will not be allowed to avoid unexpected issues. """ self.v = np.array(self.v, dtype=self.vtype) # data quality check # ---------------------------------------- # NOTE: temporarily disabled due to nested parameters # if np.sum(np.isnan(self.v)) > 0: # raise ValueError(f'Param <{self.name} contains NaN.') if self.v.dtype != np.object: self.v[self.v == np.inf] = 1e8 self.v[self.v == -np.inf] = -1e8 # ---------------------------------------- self.vin = np.array(self.v, dtype=self.vtype) self.pu_coeff = np.ones_like(self.v, dtype=float)
def to_array(self): """ Convert ``v`` to np.ndarray after adding elements. Store a copy if the input in `vin`. Set ``pu_coeff`` to all ones. The conversion enables array-based calculation. Warnings -------- After this call, `add` will not be allowed, because data will not be copied over to ``vin``. """ # data quality check # ---------------------------------------- self.v = np.array(self.v, dtype=float) # NOTE: temporarily disabled due to nested parameters # if np.sum(np.isnan(self.v)) > 0: # raise ValueError(f'Param <{self.name} contains NaN.') self.v[self.v == np.inf] = 1e8 self.v[self.v == -np.inf] = -1e8 # ---------------------------------------- self.vin = np.array(self.v, dtype=float) self.pu_coeff = np.ones_like(self.v)
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 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 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)