Beispiel #1
0
    def nr_step(self):
        """
        Single stepping for Newton Raphson method
        Returns
        -------

        """
        system = self.system
        # evaluate discrete, differential, algebraic, and jacobians
        system.e_clear()
        system.l_update_var()
        system.f_update()
        system.g_update()
        system.l_check_eq()
        system.l_set_eq()
        system.fg_to_dae()
        system.j_update()

        # prepare and solve linear equations
        self.inc = -matrix([matrix(system.dae.f), matrix(system.dae.g)])

        self.A = sparse([[system.dae.fx, system.dae.gx],
                         [system.dae.fy, system.dae.gy]])

        self.inc = self.solver.solve(self.A, self.inc)

        system.dae.x += np.ravel(np.array(self.inc[:system.dae.n]))
        system.dae.y += np.ravel(np.array(self.inc[system.dae.n:]))

        mis = np.max(np.abs(system.dae.fg))
        self.mis.append(mis)

        system.vars_to_models()

        return mis
Beispiel #2
0
    def reset(self):
        """
        Reset internal states to pre-init condition.
        """
        self.deltat = 0
        self.deltatmin = 0
        self.deltatmax = 0
        self.h = 0
        self.next_pc = 0.1
        self.Teye = None
        self.qg = np.array([])

        self.converged = False
        self.last_converged = False
        self.busted = False
        self.niter = 0
        self._switch_idx = 0        # index into `System.switch_times`
        self._last_switch_t = -999  # the last event time
        self.custom_event = False
        self.mis = [1, 1]
        self.system.dae.t = np.array(0.0)
        self.pbar = None
        self.plotter = None
        self.plt = None             # short name for `plotter`

        self.initialized = False
Beispiel #3
0
    def __init__(self,
                 u,
                 mode='step',
                 delay=0,
                 name=None,
                 tex_name=None,
                 info=None):
        Discrete.__init__(self, name=name, tex_name=tex_name, info=info)

        if mode not in ('step', 'time'):
            raise ValueError(
                f'mode {mode} is invalid. Must be in "step" or "time"')

        self.u = u
        self.mode = mode
        self.delay = delay
        self.export_flags = ['v']
        self.export_flags_tex = ['v']

        self.t = np.array([0])
        self.v = np.array([0])
        self._v_mem = np.zeros((0, 1))
        self.rewind = False

        self.has_check_var = True
Beispiel #4
0
    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)
Beispiel #5
0
    def __init__(self,
                 u,
                 lower,
                 upper,
                 enable=True,
                 name=None,
                 tex_name=None,
                 info=None,
                 no_upper=False,
                 no_lower=False):
        super().__init__(name=name, tex_name=tex_name, info=info)
        self.u = u
        self.lower = lower
        self.upper = upper
        self.enable = enable
        self.no_upper = no_upper
        self.no_lower = no_lower

        self.zu = np.array([0])
        self.zl = np.array([0])
        self.zi = np.array([1])

        self.export_flags = ['zi']
        self.export_flags_tex = ['z_i']

        self.has_check_var = True

        if not self.no_lower:
            self.export_flags.append('zl')
            self.export_flags_tex.append('z_l')
            self.warn_flags.append(('zl', 'lower'))
        if not self.no_upper:
            self.export_flags.append('zu')
            self.export_flags_tex.append('z_u')
            self.warn_flags.append(('zu', 'upper'))
Beispiel #6
0
    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)
Beispiel #7
0
    def __init__(self,
                 u,
                 bound,
                 equal=False,
                 enable=True,
                 name=None,
                 tex_name=None,
                 info=None,
                 cache=False,
                 z0=0,
                 z1=1):
        super().__init__(name=name, tex_name=tex_name, info=info)
        self.u = u
        self.bound = dummify(bound)
        self.equal: bool = equal
        self.enable: bool = enable
        self.cache: bool = cache
        self._eval: bool = False  # if has been eval'ed and cached

        self.z0 = np.array([z0])  # negation of `self.z1`
        self.z1 = np.array(
            [z1])  # if the less-than condition (u < bound) is True
        self.export_flags = ['z0', 'z1']
        self.export_flags_tex = ['z_0', 'z_1']

        self.has_check_var = True
Beispiel #8
0
    def set_address(self, addr: np.ndarray, contiguous=False):
        """
        Set the address of internal variables.

        Parameters
        ----------
        addr : np.ndarray
            The assigned address for this variable
        contiguous : bool, optional
            If the addresses are contiguous
        """
        self.a = addr
        self.n = len(self.a)

        # NOT IN USE
        self.ae = np.array(self.a)
        self.av = np.array(self.a)
        # -----------

        self._contiguous = contiguous

        if self._contiguous:
            if self.e_setter is False:
                self.e_inplace = True

            if self.v_setter is False:
                self.v_inplace = True
Beispiel #9
0
    def __init__(self, system):
        self.system = system
        self.t = 0
        self.ts = DAETimeSeries(self)

        self.m, self.n, self.o = 0, 0, 0
        self.x, self.y, self.z = np.array([]), np.array([]), np.array([])
        self.f, self.g = np.array([]), np.array([])

        self.fx = None
        self.fy = None
        self.gx = None
        self.gy = None
        self.tx = None
        self.rx = None

        self.fx_pattern = None
        self.fy_pattern = None
        self.gx_pattern = None
        self.gy_pattern = None
        self.tx_pattern = None
        self.rx_pattern = None

        self.x_name, self.x_tex_name = [], []
        self.y_name, self.y_tex_name = [], []
        self.z_name, self.z_tex_name = [], []

        # ----- indices of sparse matrices -----
        self.ifx, self.jfx, self.vfx = list(), list(), list()
        self.ify, self.jfy, self.vfy = list(), list(), list()
        self.igx, self.jgx, self.vgx = list(), list(), list()
        self.igy, self.jgy, self.vgy = list(), list(), list()
        self.itx, self.jtx, self.vtx = list(), list(), list()
        self.irx, self.jrx, self.vrx = list(), list(), list()
Beispiel #10
0
    def nr_step(self):
        """
        Single step using Newton-Raphson method.

        Returns
        -------
        float
            maximum absolute mismatch
        """
        system = self.system
        # evaluate discrete, differential, algebraic, and Jacobians
        system.dae.clear_fg()
        system.l_update_var(self.models, niter=self.niter, err=self.mis[-1])
        system.s_update_var(self.models)
        system.f_update(self.models)
        system.g_update(self.models)
        system.l_update_eq(self.models)
        system.fg_to_dae()

        if self.config.method == 'NR':
            system.j_update(models=self.models)
        elif self.config.method == 'dishonest':
            if self.niter < self.config.n_factorize:
                system.j_update(self.models)

        # prepare and solve linear equations
        self.inc = -matrix([matrix(system.dae.f),
                            matrix(system.dae.g)])

        self.A = sparse([[system.dae.fx, system.dae.gx],
                         [system.dae.fy, system.dae.gy]])

        if not self.config.linsolve:
            self.inc = self.solver.solve(self.A, self.inc)
        else:
            self.inc = self.solver.linsolve(self.A, self.inc)

        system.dae.x += np.ravel(np.array(self.inc[:system.dae.n]))
        system.dae.y += np.ravel(np.array(self.inc[system.dae.n:]))

        # find out variables associated with maximum mismatches
        fmax = 0
        if system.dae.n > 0:
            fmax_idx = np.argmax(np.abs(system.dae.f))
            fmax = system.dae.f[fmax_idx]
            logger.debug("Max. diff mismatch %.10g on %s", fmax, system.dae.x_name[fmax_idx])

        gmax_idx = np.argmax(np.abs(system.dae.g))
        gmax = system.dae.g[gmax_idx]
        logger.debug("Max. algeb mismatch %.10g on %s", gmax, system.dae.y_name[gmax_idx])

        mis = max(abs(fmax), abs(gmax))
        if self.niter == 0:
            self.mis[0] = mis
        else:
            self.mis.append(mis)

        system.vars_to_models()

        return mis
Beispiel #11
0
    def setUp(self):
        self.lower = NumParam()
        self.upper = NumParam()
        self.u = Algeb()

        self.upper.v = np.array([2, 2, 2, 2, 2, 2, 2.8, 3.9])
        self.u.v = np.array([-3, -1.1, -5, 0, 1, 2, 3, 10])
        self.lower.v = np.array([-2, -1, 0.5, 0, 0.5, 1.5, 2, 3])
Beispiel #12
0
    def linsolve(self, A, b):
        """
        Solve linear equation set ``Ax = b`` and returns the solutions in a 1-D array.

        This function performs both symbolic and numeric factorizations every time, and can be slower than
        ``Solver.solve``.

        Parameters
        ----------
        A
            Sparse matrix

        b
            RHS of the equation

        Returns
        -------
        The solution in a 1-D np array.
        """
        if self.sparselib == 'umfpack':
            try:
                umfpack.linsolve(A, b)
            except ArithmeticError:
                logger.error('Singular matrix. Case is not solvable')
            return np.ravel(b)

        elif self.sparselib == 'klu':
            try:
                klu.linsolve(A, b)
            except ArithmeticError:
                logger.error('Singular matrix. Case is not solvable')
            return np.ravel(b)

        elif self.sparselib in ('spsolve', 'cupy'):
            ccs = A.CCS
            size = A.size
            data = np.array(ccs[2]).reshape((-1,))
            indices = np.array(ccs[1]).reshape((-1,))
            indptr = np.array(ccs[0]).reshape((-1,))

            A = csc_matrix((data, indices, indptr), shape=size)

            if self.sparselib == 'spsolve':
                x = spsolve(A, b)
                return np.ravel(x)

            elif self.sparselib == 'cupy':
                # delayed import for startup speed
                import cupy as cp  # NOQA
                from cupyx.scipy.sparse import csc_matrix as csc_cu  # NOQA
                from cupyx.scipy.sparse.linalg.solve import lsqr as cu_lsqr  # NOQA

                cu_A = csc_cu(A)
                cu_b = cp.array(np.array(b).reshape((-1,)))
                x = cu_lsqr(cu_A, cu_b)

                return np.ravel(cp.asnumpy(x[0]))
Beispiel #13
0
    def store_switch_times(self, models, eps=1e-4):
        """
        Store event switching time in a sorted Numpy array in ``System.switch_times``
        and an OrderedDict ``System.switch_dict``.

        ``System.switch_dict`` has keys as event times and values as the OrderedDict
        of model names and instances associated with the event.

        Parameters
        ----------
        models : OrderedDict
            model name : model instance
        eps : float
            The small time step size to use immediately before
            and after the event

        Returns
        -------
        array-like
            self.switch_times
        """
        out = np.array([], dtype=np.float)

        if self.options.get('flat') is True:
            return out

        names = []
        for instance in models.values():
            times = np.array(instance.get_times()).ravel()
            out = np.append(out, times)
            out = np.append(out, times - eps)
            out = np.append(out, times + eps)
            names.extend([instance.class_name] * (3 * len(times)))

        # sort
        sort_idx = np.argsort(out).astype(int)
        out = out[sort_idx]
        names = [names[i] for i in sort_idx]

        # select t > current time
        ltzero_idx = np.where(out >= self.dae.t)[0]
        out = out[ltzero_idx]
        names = [names[i] for i in ltzero_idx]

        # make into an OrderedDict with unique keys and model names combined
        for i, j in zip(out, names):
            if i not in self.switch_dict:
                self.switch_dict[i] = {j: self.models[j]}
            else:
                self.switch_dict[i].update({j: self.models[j]})

        self.switch_times = np.array(list(self.switch_dict.keys()))

        # self.switch_times = out
        self.n_switches = len(self.switch_times)
        return self.switch_times
Beispiel #14
0
    def __init__(self, dae=None):
        self.dae = dae
        self._data = OrderedDict()
        self._z = OrderedDict()

        self.t = np.array([])
        self.xy = np.array([])
        self.z = np.array([])
        self.df = None
        self.df_z = None
Beispiel #15
0
    def __init__(
        self,
        name: Optional[str] = None,
        tex_name: Optional[str] = None,
        info: Optional[str] = None,
        unit: Optional[str] = None,
        v_str: Optional[Union[str, float]] = None,
        v_iter: Optional[str] = None,
        e_str: Optional[str] = None,
        discrete: Optional[Discrete] = None,
        v_setter: Optional[bool] = False,
        e_setter: Optional[bool] = False,
        addressable: Optional[bool] = True,
        export: Optional[bool] = True,
        diag_eps: Optional[float] = 0.0,
    ):

        self.name = name
        self.info = info
        self.unit = unit

        self.tex_name = tex_name if tex_name else name
        self.owner = None  # instance of the owner Model
        self.id = None  # variable internal index inside a model (assigned in run time) FIXME: not in use

        self.v_str = v_str  # equation string (v = v_str) for variable initialization
        self.v_iter = v_iter  # the implicit equation (0 = v_iter) for iterative initialization
        self.e_str = e_str  # string for symbolic equation

        self.discrete = discrete
        self.v_setter = v_setter  # True if this variable sets the variable value
        self.e_setter = e_setter  # True if this var sets the equation value
        self.addressable = addressable  # True if this var needs to be assigned an address FIXME: not in use
        self.export = export  # True if this var's value needs to exported
        self.diag_eps = diag_eps  # small diagonal value (1e-6) to be added to `dae.gy`

        # attributes assigned by `set_address`
        self.n = 0
        self.a: ndarray = np.array([], dtype=int)  # address array
        self.v: ndarray = np.array([], dtype=np.float)  # variable value array
        self.e: ndarray = np.array([], dtype=np.float)  # equation value array

        self.av: ndarray = np.array(
            [], dtype=int)  # FIXME: future var. address array
        self.ae: ndarray = np.array(
            [], dtype=int)  # FIXME: future equation address array

        # internal flags
        # NOTE:
        # contiguous is only True for internal variables of models with flag ``collate`` equal to ``False``.
        self._contiguous = False  # True if if address is contiguous to allow slicing into arrays without copy.

        self.e_inplace = False  # True if `self.e` is in-place access to `System.dae.__dict__[self.e_code]`
        self.v_inplace = False  # True if `self.v` is in-place access to `System.dae.__dict__[self.v_code]`
        self.allow_none = False  # True to allow None in address (NOT IN USE)
Beispiel #16
0
    def link_external(self, ext_model):
        """
        Update variable addresses provided by external models

        This method sets attributes including `parent_model`,
        `parent_instance`, `uid`, `a`, `n`, `e_code` and
        `v_code`. It initializes the `e` and `v` to zero.

        Returns
        -------
        None

        Parameters
        ----------
        ext_model : Model
            Instance of the parent model
        """
        self.parent = ext_model

        if isinstance(ext_model, GroupBase):
            if self.indexer.n > 0 and isinstance(self.indexer.v[0],
                                                 (list, np.ndarray)):
                self._n = [len(i) for i in self.indexer.v
                           ]  # number of elements in each sublist
                self._idx = np.concatenate(
                    [np.array(i) for i in self.indexer.v])
            else:
                self._n = [len(self.indexer.v)]
                self._idx = self.indexer.v

            self.a = ext_model.get(src=self.src, idx=self._idx,
                                   attr='a').astype(int)
            self.n = len(self.a)
            self.v = np.zeros(self.n)
            self.e = np.zeros(self.n)

        else:
            original_var = ext_model.__dict__[self.src]

            if self.indexer is not None:
                uid = ext_model.idx2uid(self.indexer.v)
            else:
                uid = np.arange(ext_model.n, dtype=int)

            self._n = [len(uid)]
            if len(uid) > 0:
                self.a = original_var.a[uid]
            else:
                self.a = np.array([], dtype=int)

            # set initial v and e values to zero
            self.n = len(self.a)
            self.v = np.zeros(self.n)
            self.e = np.zeros(self.n)
Beispiel #17
0
    def run(self, **kwargs):
        succeed = False
        system = self.system
        self.singular_idx = np.array([], dtype=int)

        if system.PFlow.converged is False:
            logger.warning(
                'Power flow not solved. Eig analysis will not continue.')
            return succeed
        else:
            if system.TDS.initialized is False:
                system.TDS.init()
                system.TDS._itm_step()

        if system.dae.n == 0:
            logger.error('No dynamic model. Eig analysis will not continue.')

        else:
            if sum(system.dae.Tf != 0) != len(system.dae.Tf):
                self.singular_idx = np.argwhere(np.equal(
                    system.dae.Tf, 0.0)).ravel().astype(int)
                logger.info(
                    f"System contains {len(self.singular_idx)} zero time constants. "
                )
                logger.debug([system.dae.x_name[i] for i in self.singular_idx])

            self.x_name = np.array(system.dae.x_name)
            self.x_name = np.delete(self.x_name, self.singular_idx)

            self.summary()
            t1, s = elapsed()

            self.calc_state_matrix()
            self.remove_singular_rc()
            self.calc_part_factor()

            if not self.system.files.no_output:
                self.report()
                if system.options.get('state_matrix') is True:
                    self.export_state_matrix()

            if self.config.plot:
                self.plot()
            _, s = elapsed(t1)
            logger.info('Eigenvalue analysis finished in {:s}.'.format(s))

            succeed = True

        system.exit_code = 0 if succeed else 1
        return succeed
Beispiel #18
0
    def __init__(self, dae=None):
        self.dae = dae

        # internal dict storage
        self._xy = OrderedDict()
        self._z = OrderedDict()

        self.t = np.array([])
        self.xy = np.array([]).reshape((-1, 1))
        self.z = np.array([]).reshape((-1, 1))

        # data frame members
        self.df = None
        self.df_z = None
Beispiel #19
0
    def store_sparse_pattern(self,
                             models: Optional[Union[str, List,
                                                    OrderedDict]] = None):
        models = self._get_models(models)
        self._call_models_method('store_sparse_pattern', models)

        # add variable jacobian values
        for j_name in self.dae.jac_name:
            ii, jj, vv = list(), list(), list()

            # 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
            if j_name == 'gy':
                ii.extend(np.arange(self.dae.m))
                jj.extend(np.arange(self.dae.m))
                vv.extend(np.zeros(self.dae.m))

            # logger.debug(f'Jac <{j_name}>, row={ii}')

            for mdl in models.values():
                row_idx = mdl.row_of(f'{j_name}')
                col_idx = mdl.col_of(f'{j_name}')

                # logger.debug(f'Model <{name}>, row={row_idx}')
                ii.extend(row_idx)
                jj.extend(col_idx)
                vv.extend(np.zeros(len(np.array(row_idx))))

                # add the constant jacobian values
                for row, col, val in mdl.zip_ijv(f'{j_name}c'):
                    ii.extend(row)
                    jj.extend(col)

                    if isinstance(val, (float, int)):
                        vv.extend(val * np.ones(len(row)))
                    elif isinstance(val, (list, np.ndarray)):
                        vv.extend(val)
                    else:
                        raise TypeError(
                            f'Unknown type {type(val)} in constant jacobian {j_name}'
                        )

            if len(ii) > 0:
                ii = np.array(ii).astype(int)
                jj = np.array(jj).astype(int)
                vv = np.array(vv).astype(float)

            self.dae.store_sparse_ijv(j_name, ii, jj, vv)
            self.dae.build_pattern(j_name)
Beispiel #20
0
    def nr_step(self):
        """
        Single step using Newton-Raphson method.

        Returns
        -------
        float
            maximum absolute mismatch
        """
        system = self.system
        # evaluate discrete, differential, algebraic, and Jacobians
        system.dae.clear_fg()
        system.l_update_var(self.models, niter=self.niter, err=self.mis[-1])
        system.s_update_var(self.models)
        system.f_update(self.models)
        system.g_update(self.models)
        system.l_update_eq(self.models)
        system.fg_to_dae()

        if self.config.method == 'NR':
            system.j_update(models=self.models)
        elif self.config.method == 'dishonest':
            if self.niter < self.config.n_factorize:
                system.j_update(self.models)

        # prepare and solve linear equations
        self.inc = -matrix([matrix(system.dae.f), matrix(system.dae.g)])

        self.A = sparse([[system.dae.fx, system.dae.gx],
                         [system.dae.fy, system.dae.gy]])

        if not self.config.linsolve:
            self.inc = self.solver.solve(self.A, self.inc)
        else:
            self.inc = self.solver.linsolve(self.A, self.inc)

        system.dae.x += np.ravel(np.array(self.inc[:system.dae.n]))
        system.dae.y += np.ravel(np.array(self.inc[system.dae.n:]))

        mis = np.max(np.abs(system.dae.fg))

        if self.niter == 0:
            self.mis[0] = mis
        else:
            self.mis.append(mis)

        system.vars_to_models()

        return mis
Beispiel #21
0
    def __init__(self, system=None, config=None):
        super().__init__(system, config)
        self.config.add(
            OrderedDict((
                ('tol', 1e-6),
                ('t0', 0.0),
                ('tf', 20.0),
                ('fixt', 1),
                ('shrinkt', 1),
                ('tstep', 1 / 30),
                ('max_iter', 15),
            )))
        self.config.add_extra(
            "_help",
            tol="convergence tolerance",
            t0="simulation starting time",
            tf="simulation ending time",
            fixt="use fixed step size (1) or variable (0)",
            shrinkt='shrink step size for fixed method if not converged',
            tstep='the initial step step size',
            max_iter='maximum number of iterations',
        )
        self.config.add_extra(
            "_alt",
            tol="float",
            t0=">=0",
            tf=">t0",
            fixt=(0, 1),
            shrinkt=(0, 1),
            tstep='float',
            max_iter='>=10',
        )
        # overwrite `tf` from command line
        if system.options.get('tf') is not None:
            self.config.tf = system.options.get('tf')

        # to be computed
        self.deltat = 0
        self.deltatmin = 0
        self.deltatmax = 0
        self.h = 0
        self.next_pc = 0
        self.eye = None
        self.Teye = None
        self.qg = np.array([])
        self.tol_zero = self.config.tol / 100

        # internal status
        self.converged = False
        self.busted = False
        self.err_msg = ''
        self.niter = 0
        self._switch_idx = 0  # index into `System.switch_times`
        self._last_switch_t = -999  # the last critical time
        self.mis = 1
        self.pbar = None
        self.callpert = None
        self.plotter = None
        self.plt = None
        self.initialized = False
Beispiel #22
0
    def unpack(self, df=False):
        """
        Unpack stored data in `_xy` and `_z` into arrays `t`, `xy`, and `z`.

        Parameters
        ----------
        df : bool
            True to construct DataFrames `self.df` and `self.df_z` (time-consuming).
        """
        if df is True:
            self.df = pd.DataFrame.from_dict(self._xy,
                                             orient='index',
                                             columns=self.dae.xy_name)
            self.t = self.df.index.to_numpy()
            self.xy = self.df.to_numpy()

            self.df_z = pd.DataFrame.from_dict(self._z,
                                               orient='index',
                                               columns=self.dae.z_name)
            self.z = self.df_z.to_numpy()
        else:
            n_steps = len(self._xy)
            self.t = np.array(list(self._xy.keys()))
            self.xy = np.zeros((n_steps, self.dae.m + self.dae.n))
            self.z = np.zeros((n_steps, self.dae.o))

            for idx, xy in enumerate(self._xy.values()):
                self.xy[idx, :] = xy

            for idx, z in enumerate(self._z.values()):
                self.z[idx, :] = z
Beispiel #23
0
    def __init__(self, u, center, lower, upper, enable=True):
        """

        """
        super().__init__(u, lower, upper, enable=enable)
        self.center = center

        # default state if not enabled
        self.zi = np.array([0.])
        self.zl = np.array([0.])
        self.zu = np.array([0.])
        self.zur = np.array([0.])
        self.zlr = np.array([0.])

        self.export_flags = ['zl', 'zi', 'zu', 'zur', 'zlr']
        self.export_flags_tex = ['z_l', 'z_i', 'z_u', 'z_ur', 'z_lr']
Beispiel #24
0
    def __init__(self,
                 u,
                 lower,
                 upper,
                 enable=True,
                 no_lower=False,
                 no_upper=False,
                 lower_cond=None,
                 upper_cond=None,
                 name=None,
                 tex_name=None,
                 info=None):
        Discrete.__init__(self, name=name, tex_name=tex_name, info=info)
        self.u = u
        self.rate_lower = dummify(lower)
        self.rate_upper = dummify(upper)

        # `lower_cond` and `upper_cond` are arrays of 0/1 indicating whether
        # the corresponding rate limit should be *enabled*.
        # 0 - disabled, 1 - enabled.
        # If is `None`, all rate limiters will be enabled.

        self.rate_lower_cond = dummify(lower_cond)
        self.rate_upper_cond = dummify(upper_cond)

        self.rate_no_lower = no_lower
        self.rate_no_upper = no_upper
        self.enable = enable

        self.zur = np.array([0])
        self.zlr = np.array([0])

        self.has_check_eq = True

        # Note: save ops by not calculating `zir`
        # self.zir = np.array([1])
        # self.export_flags = ['zir']
        # self.export_flags_tex = ['z_{ir}']

        if not self.rate_no_lower:
            self.export_flags.append('zlr')
            self.export_flags_tex.append('z_{lr}')
            self.warn_flags.append(('zlr', 'lower'))
        if not self.rate_no_upper:
            self.export_flags.append('zur')
            self.export_flags_tex.append('z_{ur}')
            self.warn_flags.append(('zur', 'upper'))
Beispiel #25
0
class System(object):
    """
    New power system class
    """
    def __init__(self,
                 case: Optional[str] = None,
                 name: Optional[str] = None,
                 config_path: Optional[str] = None,
                 options: Optional[Dict] = None,
                 **kwargs):
        self.name = name
        self.options = {} if options is None else options
        if kwargs:
            self.options.update(kwargs)
        self.calls = OrderedDict()
        self.models = OrderedDict()
        self.groups = OrderedDict()
        self.programs = OrderedDict()
        self.switch_times = np.array([])

        # get and load default config file
        self.config = Config(self.__class__.__name__)
        self._config_path = get_config_path(
        ) if not config_path else config_path
        self._config_from_file = self.load_config(self._config_path)
        self.config.load(self._config_from_file)

        # custom configuration for system goes after this line
        self.config.add(
            OrderedDict((
                ('freq', 60),
                ('mva', 100),
                ('store_z', 0),
            )))

        self.files = FileMan()
        self.files.set(case=case, **self.options)

        self.dae = DAE(system=self)

        # dynamic imports: routine import need to query model flags
        self._group_import()
        self._model_import()
        self._routine_import()

        self._models_with_flag = {
            'pflow': self.get_models_with_flag('pflow'),
            'tds': self.get_models_with_flag('tds'),
            'pflow_and_tds': self.get_models_with_flag(('tds', 'pflow')),
        }

        # ------------------------------
        # FIXME: reduce clutter with defaultdict `adders` and `setters`, each with `x`, `y`, `f`, and `g`
        self.f_adders, self.f_setters = list(), list()
        self.g_adders, self.g_setters = list(), list()

        self.x_adders, self.x_setters = list(), list()
        self.y_adders, self.y_setters = list(), list()
        self.antiwindups = list()
Beispiel #26
0
    def __init__(self, dae=None):
        self.dae = dae

        # internal dict storage
        self._data = OrderedDict()
        self._z = OrderedDict()

        self.t = np.array([])
        self.xy = np.array([])
        self.z = np.array([])

        # data frame members
        self.df = None
        self.df_z = None

        # flags
        self._need_unpack = True
Beispiel #27
0
    def __init__(self, system, config):
        ModelData.__init__(self)
        self.bus = IdxParam(
            model='Bus',
            info="linked bus idx",
            mandatory=True,
        )
        self.tf = TimerParam(
            info='Fault start time for the bus',
            mandatory=True,
            callback=self.apply_fault,
        )
        self.tc = TimerParam(
            info='Fault end time for the bus',
            callback=self.clear_fault,
        )
        self.xf = NumParam(
            info='Fault to ground impedance',
            default=1e-4,
            tex_name='x_f',
        )
        self.rf = NumParam(
            info='Fault to ground resistance',
            default=0,
            tex_name='x_f',
        )

        Model.__init__(self, system, config)
        self.flags.update({'tds': True})
        self.group = 'TimedEvent'
        self.gf = ConstService(
            tex_name='g_{f}',
            v_str='re(1/(rf + 1j * xf))',
        )
        self.bf = ConstService(
            tex_name='b_{f}',
            v_str='im(1/(rf + 1j * xf))',
        )
        self.uf = ConstService(
            tex_name='u_f',
            v_str='0',
        )

        self.a = ExtAlgeb(
            model='Bus',
            src='a',
            indexer=self.bus,
            tex_name=r'\theta',
            e_str='u * uf * (v ** 2 * gf)',
        )
        self.v = ExtAlgeb(
            model='Bus',
            src='v',
            indexer=self.bus,
            tex_name=r'V',
            e_str='u * uf * (v ** 2 * bf)',
        )
        self._vstore = np.array([])
Beispiel #28
0
 def __init__(self,
              v_str: Optional[str] = None,
              v_numeric: Optional[Callable] = None,
              vtype: Optional[type] = None,
              name: Optional[str] = None, tex_name=None, info=None):
     super().__init__(name=name, vtype=vtype, tex_name=tex_name, info=info)
     self.v_str = v_str
     self.v_numeric = v_numeric
     self.v: Union[float, int, ndarray] = np.array([0.])
Beispiel #29
0
    def init(self, routine):
        """
        Set values for the very first time step.
        """

        Model.init(self, routine)

        self.apply_exact(np.array(self.system.TDS.config.t0))
        logger.debug('<%s>: Initialization done', self.class_name)
Beispiel #30
0
    def v(self):
        if self._v is None:
            self._v = [v1 if not np.isnan(v1)
                       else v2
                       for v1, v2 in zip(self.optional.v, self.fallback.v)]

            self._v = np.array(self._v)

        return self._v