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