예제 #1
0
파일: system.py 프로젝트: 1217720084/andes
    def j_update(self, models: Optional[Union[str, List, OrderedDict]] = None):
        models = self._get_models(models)
        self._call_models_method('j_update', models)

        self.dae.restore_sparse()
        # collect sparse values into sparse structures
        for j_name in self.dae.jac_name:
            j_size = self.dae.get_size(j_name)

            for mdl in models.values():
                for row, col, val in mdl.zip_ijv(j_name):
                    # TODO: use `spmatrix.ipadd` if available
                    # TODO: fix `ipadd` to get rid of type checking
                    if isinstance(val, np.float64):
                        # Workaround for CVXOPT's handling of np.float64
                        val = float(val)
                    if isinstance(val, (int, float)) or len(val) > 0:
                        try:
                            self.dae.__dict__[j_name] += spmatrix(
                                val, row, col, j_size, 'd')
                        except TypeError as e:
                            logger.error(
                                f'{mdl.class_name}: j_name {j_name}, row={row}, col={col}, val={val}, '
                                f'j_size={j_size}')
                            raise e
예제 #2
0
    def j_update(self, models: OrderedDict):
        """
        Call the Jacobian update method for models in sequence.

        The procedure is
        - Restore the sparsity pattern with :py:func:`andes.variables.dae.DAE.restore_sparse`
        - For each sparse matrix in (fx, fy, gx, gy), evaluate the Jacobian function calls and add values.

        Notes
        -----
        Updated Jacobians are immediately reflected in the DAE sparse matrices (fx, fy, gx, gy).
        """
        self.call_models('j_update', models)

        self.dae.restore_sparse()
        # collect sparse values into sparse structures
        for j_name in jac_names:
            j_size = self.dae.get_size(j_name)

            for mdl in models.values():
                for rows, cols, vals in mdl.triplets.zip_ijv(j_name):
                    try:
                        if self.config.ipadd and IP_ADD:
                            self.dae.__dict__[j_name].ipadd(vals, rows, cols)
                        else:
                            self.dae.__dict__[j_name] += spmatrix(
                                vals, rows, cols, j_size, 'd')
                    except TypeError as e:
                        logger.error(
                            "Error adding Jacobian triplets to existing sparsity pattern."
                        )
                        logger.error(
                            f'{mdl.class_name}: j_name {j_name}, row={rows}, col={cols}, val={vals}, '
                            f'j_size={j_size}')
                        raise e
예제 #3
0
    def j_update(self, models: Optional[Union[str, List, OrderedDict]] = None):
        """
        Call the Jacobian update method for each model.

        Notes
        -----
        Updated Jacobians are reflected in the numerical DAE.
        """
        models = self._get_models(models)
        self._call_models_method('j_update', models)

        self.dae.restore_sparse()
        # collect sparse values into sparse structures
        for j_name in jac_names:
            j_size = self.dae.get_size(j_name)

            for mdl in models.values():
                for rows, cols, vals in mdl.triplets.zip_ijv(j_name):
                    try:
                        if self.config.ipadd and IP_ADD:
                            self.dae.__dict__[j_name].ipadd(vals, rows, cols)
                        else:
                            self.dae.__dict__[j_name] += spmatrix(vals, rows, cols, j_size, 'd')
                    except TypeError as e:
                        logger.error("Error adding Jacobian triplets to existing sparsity pattern.")
                        logger.error(f'{mdl.class_name}: j_name {j_name}, row={rows}, col={cols}, val={vals}, '
                                     f'j_size={j_size}')
                        raise e
예제 #4
0
파일: dae.py 프로젝트: JiweiTian/andes
    def build_pattern(self, name):
        """
        Build sparse matrices with stored patterns.

        Call to `store_row_col_idx` should be made before this function.

        Parameters
        ----------
        name : name
            jac name
        """
        self.__dict__[name] = spmatrix(self.val_of(name), self.row_of(name),
                                       self.col_of(name), self.get_size(name),
                                       'd')
예제 #5
0
파일: dae.py 프로젝트: Hello-World-Py/andes
    def _compare_pattern(self, name):
        """
        Compare the sparsity pattern for the given Jacobian name.

        This function is for debugging the symbolic factorization error / sparsity pattern change.
        To use, add the following line in `System.j_update` for each `j_name` at the end:

            self.dae._compare_pattern(j_name)
        """
        self.__dict__[f'{name}_tpl'] = spmatrix(self.triplets.vjac[name],
                                                self.triplets.ijac[name],
                                                self.triplets.jjac[name],
                                                self.get_size(name), 'd')
        m_before = self.__dict__[f'{name}_tpl']
        m_after = self.__dict__[name]

        for i in range(len(m_after)):
            if m_after.I[i] != m_before.I[i] or m_after.J[i] != m_before.J[i]:
                raise KeyError
예제 #6
0
파일: dae.py 프로젝트: treymingee/andes
    def restore_sparse(self, names=None):
        """
        Restore all sparse matrices to the sparsity pattern
        filled with zeros (for variable Jacobian elements)
        and non-zero constants.

        Parameters
        ----------
        names : None or list
            List of Jacobian names to restore sparsity pattern
        """
        if names is None:
            names = jac_names
        elif isinstance(names, str):
            names = [names]

        for name in names:
            self.__dict__[name] = spmatrix(self.tpl[name].V, self.tpl[name].I,
                                           self.tpl[name].J,
                                           self.tpl[name].size, 'd')
예제 #7
0
파일: dae.py 프로젝트: Hello-World-Py/andes
    def build_pattern(self, name):
        """
        Build sparse matrices with stored patterns.

        Call to `store_row_col_idx` should be made before this function.

        Parameters
        ----------
        name : name
            jac name
        """
        try:
            self.__dict__[name] = spmatrix(self.triplets.vjac[name],
                                           self.triplets.ijac[name],
                                           self.triplets.jjac[name],
                                           self.get_size(name), 'd')
        except TypeError as e:
            logger.error(
                "Your new model might have accessed an Algeb using ExtState, or vice versa."
            )
            raise e
예제 #8
0
파일: eig.py 프로젝트: jinningwang/andes
    def reorder_As(self):
        """
        reorder As by moving rows and cols associated with zero time constants to the end.

        Returns `fx`, `fy`, `gx`, `gy`, `Tf`.
        """
        system = self.system
        rows = np.arange(system.dae.n, dtype=int)
        cols = np.arange(system.dae.n, dtype=int)
        vals = np.ones(system.dae.n, dtype=float)

        swaps = []
        bidx = self.non_zeros
        for ii in range(system.dae.n - self.non_zeros):
            if ii in self.singular_idx:
                while (bidx in self.singular_idx):
                    bidx += 1
                cols[ii] = bidx
                rows[bidx] = ii
                swaps.append((ii, bidx))

        # swap the variable names
        for fr, bk in swaps:
            bk_name = self.x_name[bk]
            self.x_name[fr] = bk_name
        self.x_name = self.x_name[:self.non_zeros]

        # compute the permutation matrix for `As` containing non-states
        perm = spmatrix(matrix(vals), matrix(rows), matrix(cols))
        As_perm = perm * sparse(self.As) * perm
        self.As_perm = As_perm

        nfx = As_perm[:self.non_zeros, :self.non_zeros]
        nfy = As_perm[:self.non_zeros, self.non_zeros:]
        ngx = As_perm[self.non_zeros:, :self.non_zeros]
        ngy = As_perm[self.non_zeros:, self.non_zeros:]
        nTf = np.delete(system.dae.Tf, self.singular_idx)

        return nfx, nfy, ngx, ngy, nTf
예제 #9
0
파일: eig.py 프로젝트: jinningwang/andes
    def calc_part_factor(self, As=None):
        """
        Compute participation factor of states in eigenvalues.

        Returns
        -------

        """
        if As is None:
            As = self.As
        mu, N = np.linalg.eig(As)

        N = matrix(N)
        n = len(mu)
        idx = range(n)

        mu_complex = np.zeros_like(mu, dtype=complex)
        W = matrix(spmatrix(1.0, idx, idx, As.size, N.typecode))
        gesv(N, W)

        partfact = mul(abs(W.T), abs(N))

        b = matrix(1.0, (1, n))
        WN = b * partfact
        partfact = partfact.T

        for item in idx:
            mu_real = float(mu[item].real)
            mu_imag = float(mu[item].imag)
            mu_complex[item] = complex(round(mu_real, 5), round(mu_imag, 5))
            partfact[item, :] /= WN[item]

        # participation factor
        self.mu = matrix(mu_complex)
        self.part_fact = matrix(partfact)

        return self.mu, self.part_fact
예제 #10
0
파일: eig.py 프로젝트: 1217720084/andes
    def calc_part_factor(self):
        """
        Compute participation factor of states in eigenvalues

        Returns
        -------

        """
        mu, N = np.linalg.eig(self.As)
        # TODO: use scipy.sparse.linalg.eigs(self.As)

        N = matrix(N)
        n = len(mu)
        idx = range(n)

        mu_complex = np.array([0] * n, dtype=complex)
        W = matrix(spmatrix(1.0, idx, idx, (n, n), N.typecode))
        gesv(N, W)

        partfact = mul(abs(W.T), abs(N))

        b = matrix(1.0, (1, n))
        WN = b * partfact
        partfact = partfact.T

        for item in idx:
            mu_real = float(mu[item].real)
            mu_imag = float(mu[item].imag)
            mu_complex[item] = complex(round(mu_real, 4), round(mu_imag, 4))
            partfact[item, :] /= WN[item]

        # participation factor
        self.mu = matrix(mu_complex)
        self.part_fact = matrix(partfact)

        return self.mu, self.part_fact