Ejemplo n.º 1
0
    def calc_eigen_coeffs(
        self,
        F_z_t0: DataArray = None,
    ):
        """Calculates the coefficients from the eigenvalues and eigenvectors for the
        time evolution equation.

        Parameters
        ----------
        F_z_t0
            Initial fractional abundance for given impurity element. (Optional)

        Returns
        -------
        eig_coeffs
            Coefficients calculated from the eigenvalues and eigenvectors needed
            for the time evolution equation.
        F_z_t0
            Initial fractional abundance, either user-provided or fully neutral
            eg. [1.0, 0.0, 0.0, 0.0, 0.0] for Beryllium.
        """
        x1_coord = self.x1_coord

        if F_z_t0 is None:
            # mypy doesn't understand contionals or reassignments either.
            F_z_t0 = np.zeros(self.F_z_tinf.shape, dtype=np.complex128)  # type: ignore
            F_z_t0[0, :] = np.array(  # type: ignore
                [1.0 + 0.0j for i in range(x1_coord.size)]
            )

            F_z_t0 = DataArray(
                data=F_z_t0,
                coords=[
                    (
                        "ion_charges",
                        np.linspace(
                            0, self.num_of_ion_charges - 1, self.num_of_ion_charges
                        ),
                    ),
                    x1_coord,  # type: ignore
                ],
                dims=["ion_charges", x1_coord.dims[0]],
            )
        else:
            input_check("F_z_t0", F_z_t0, DataArray, greater_than_or_equal_zero=True)

            try:
                assert F_z_t0.ndim < 3
            except AssertionError:
                raise ValueError("F_z_t0 must be at most 2-dimensional.")

            F_z_t0 = F_z_t0 / np.sum(F_z_t0, axis=0)
            F_z_t0 = F_z_t0.as_type(dtype=np.complex128)  # type: ignore

            F_z_t0 = DataArray(
                data=F_z_t0.values,  # type: ignore
                coords=[
                    (
                        "ion_charges",
                        np.linspace(
                            0, self.num_of_ion_charges - 1, self.num_of_ion_charges
                        ),
                    ),
                    x1_coord,  # type: ignore
                ],
                dims=["ion_charges", x1_coord.dims[0]],
            )

        eig_vals = self.eig_vals
        eig_vecs_inv = np.zeros(self.eig_vecs.shape, dtype=np.complex128)
        for ix1 in range(x1_coord.size):
            eig_vecs_inv[:, :, ix1] = np.linalg.pinv(
                np.transpose(self.eig_vecs[:, :, ix1])
            )

        boundary_conds = F_z_t0 - self.F_z_tinf

        eig_coeffs = np.zeros(eig_vals.shape, dtype=np.complex128)
        for ix1 in range(x1_coord.size):
            eig_coeffs[:, ix1] = np.dot(boundary_conds[:, ix1], eig_vecs_inv[:, :, ix1])

        self.eig_coeffs = eig_coeffs

        # If argument to numpy functions is of type DataArray then output is of
        # type DataArray
        F_z_t0 = np.abs(np.real(F_z_t0))  # type: ignore

        self.F_z_t0 = F_z_t0  # type: ignore

        return eig_coeffs, F_z_t0