def __init__(self, wfn, blocks=False, precondition='denom', tda=False, triplet=False): blocks = False if not wfn.same_a_b_orbs(): raise ValidationError("TDSCF is RHF only") self.wfn = wfn self.jk = wfn.jk() self.C = wfn.Ca() self.Co = wfn.Ca_subset("SO", "OCC") self.Cv = wfn.Ca_subset("SO", "VIR") self.noccpi = wfn.nalphapi() self.nmopi = wfn.nmopi() self.nirrep = wfn.nirrep() self.nvirpi = core.Dimension([ mo - occ for mo, occ in zip(self.noccpi.to_tuple(), self.nmopi.to_tuple()) ]) self.nocc = wfn.nalphapi().sum() self.nmo = wfn.nmopi().sum() self.nvir = self.nmo - self.nocc self.nov = self.nocc * self.nvir self.Fab = core.Matrix.triplet(self.Cv, self.wfn.Fa(), self.Cv, True, False, False) self.Fij = core.Matrix.triplet(self.Co, self.wfn.Fb(), self.Co, True, False, False) self.e_ia = np.zeros((self.nocc, self.nvir)) for i in range(self.nocc): for a in range(self.nvir): self.e_ia[i, a] = self.Fab.np[a, a] - self.Fij.np[i, i] self.blocks = blocks self.triplet = triplet
def _dimension_from_list( self, dims: Union[Tuple[int], List[int], np.ndarray, core.Dimension], name="New Dimension", ) -> core.Dimension: """ Builds a Dimension object from a Python list or tuple. If a :class:`~psi4.core.Dimension` object is passed, a copy will be returned. Parameters ---------- dims Iterable of integers defining irrep dimensions. name Name for new instance. """ if isinstance(dims, (tuple, list, np.ndarray)): irreps = len(dims) elif isinstance(dims, core.Dimension): irreps = dims.n() else: raise ValidationError("Dimension from list: Type '%s' not understood" % type(dims)) ret = core.Dimension(irreps, name) for i in range(irreps): ret[i] = dims[i] return ret
def _dimension_from_list(self, dims, name="New Dimension"): """ Builds a core.Dimension object from a python list or tuple. If a dimension object is passed a copy will be returned. """ if isinstance(dims, (tuple, list, np.ndarray)): irreps = len(dims) elif isinstance(dims, core.Dimension): irreps = dims.n() else: raise ValidationError("Dimension from list: Type '%s' not understood" % type(dims)) ret = core.Dimension(irreps, name) for i in range(irreps): ret[i] = dims[i] return ret
def _ROHF_orbital_gradient(self, save_fock: bool, max_diis_vectors: int) -> float: # Only the inact-act, inact-vir, and act-vir rotations are non-redundant dim_zero = core.Dimension(self.nirrep(), "Zero Dim") noccpi = self.doccpi() + self.soccpi() row_slice = core.Slice(dim_zero, noccpi) col_slice = core.Slice(self.doccpi(), self.nmopi()) MOgradient = self.moFeff().get_block(row_slice, col_slice) # Zero the active-active block for h in range(MOgradient.nirrep()): socc = self.soccpi()[h] docc = self.doccpi()[h] MOgradient.nph[h][docc:docc + socc, 0:socc] = 0 # Grab inact-act and act-vir orbs # Ct is (nmo x nmo), not the (nso x nmo) you would expect row_slice = core.Slice(dim_zero, self.nmopi()) col_slice = core.Slice(dim_zero, noccpi) Cia = self.Ct().get_block(row_slice, col_slice) col_slice = core.Slice(self.doccpi(), self.nmopi()) Cav = self.Ct().get_block(row_slice, col_slice) # Back transform MOgradient gradient = core.triplet(Cia, MOgradient, Cav, False, False, True) if save_fock: if not self.initialized_diis_manager_: self.diis_manager_ = core.DIISManager(max_diis_vectors, "HF DIIS vector", RemovalPolicy.LargestError, StoragePolicy.OnDisk) self.diis_manager_.set_error_vector_size(gradient) self.diis_manager_.set_vector_size(self.soFeff()) self.initialized_diis_manager_ = True self.diis_manager_.add_entry(gradient, self.soFeff()) if self.options().get_bool("DIIS_RMS_ERROR"): return gradient.rms() else: return gradient.absmax()
def array_to_matrix(self, arr, name="New Matrix", dim1=None, dim2=None): """ Converts a numpy array or list of numpy arrays into a Psi4 Matrix (irreped if list). Parameters ---------- arr : array or list of arrays Numpy array or list of arrays to use as the data for a new core.Matrix name : str Name to give the new core.Matrix dim1 : list, tuple, or core.Dimension (optional) If a single dense numpy array is given, a dimension can be supplied to apply irreps to this array. Note that this discards all extra information given in the matrix besides the diagonal blocks determined by the passed dimension. dim2 : Same as dim1 only if using a Psi4.Dimension object. Returns ------- ret : core.Vector or core.Matrix Returns the given Psi4 object Notes ----- This is a generalized function to convert a NumPy array to a Psi4 object Examples -------- >>> data = np.random.rand(20) >>> vector = array_to_matrix(data) >>> irrep_data = [np.random.rand(2, 2), np.empty(shape=(0,3)), np.random.rand(4, 4)] >>> matrix = array_to_matrix(irrep_data) >>> print matrix.rowspi().to_tuple() >>> (2, 0, 4) """ # What type is it? MRO can help. arr_type = self.__mro__[0] # Irreped case if isinstance(arr, (list, tuple)): if (dim1 is not None) or (dim2 is not None): raise ValidationError( "Array_to_Matrix: If passed input is list of arrays dimension cannot be specified." ) irreps = len(arr) if arr_type == core.Matrix: sdim1 = core.Dimension(irreps) sdim2 = core.Dimension(irreps) for i in range(irreps): d1, d2 = _find_dim(arr[i], 2) sdim1[i] = d1 sdim2[i] = d2 ret = self(name, sdim1, sdim2) elif arr_type == core.Vector: sdim1 = core.Dimension(irreps) for i in range(irreps): d1 = _find_dim(arr[i], 1) sdim1[i] = d1[0] ret = self(name, sdim1) else: raise ValidationError( "Array_to_Matrix: type '%s' is not recognized." % str(arr_type)) for view, vals in zip(ret.nph, arr): if 0 in view.shape: continue view[:] = vals return ret # No irreps implied by list else: if arr_type == core.Matrix: # Build an irreped array back out if dim1 is not None: if dim2 is None: raise ValidationError( "Array_to_Matrix: If dim1 is supplied must supply dim2 also" ) dim1 = core.Dimension.from_list(dim1) dim2 = core.Dimension.from_list(dim2) if dim1.n() != dim2.n(): raise ValidationError( "Array_to_Matrix: Length of passed dim1 must equal length of dim2." ) ret = self(name, dim1, dim2) start1 = 0 start2 = 0 for num, interface in enumerate(ret.nph): d1 = dim1[num] d2 = dim2[num] if (d1 == 0) or (d2 == 0): continue view = np.asarray(interface) view[:] = arr[start1:start1 + d1, start2:start2 + d2] start1 += d1 start2 += d2 return ret # Simple case without irreps else: ret = self(name, arr.shape[0], arr.shape[1]) ret_view = np.asarray(numpy_holder(ret.array_interface(0))) ret_view[:] = arr return ret elif arr_type == core.Vector: # Build an irreped array back out if dim1 is not None: if dim2 is not None: raise ValidationError( "Array_to_Matrix: If dim2 should not be supplied for 1D vectors." ) dim1 = core.Dimension.from_list(dim1) ret = self(name, dim1) start1 = 0 for num, interface in enumerate(ret.nph): d1 = dim1[num] if (d1 == 0): continue view = np.asarray(interface) view[:] = arr[start1:start1 + d1] start1 += d1 return ret # Simple case without irreps else: ret = self(name, arr.shape[0]) ret.np[:] = arr return ret else: raise ValidationError( "Array_to_Matrix: type '%s' is not recognized." % str(arr_type))
def array_to_matrix( self: Union[core.Matrix, core.Vector], arr: Union[np.ndarray, List[np.ndarray]], name: str = "New Matrix", dim1: Optional[Union[List, Tuple, core.Dimension]] = None, dim2: Optional[core.Dimension] = None, ) -> Union[core.Matrix, core.Vector]: """ Converts a `NumPy array <https://numpy.org/doc/stable/reference/arrays.ndarray.html>`_ or list of NumPy arrays into a |PSIfour| :class:`~psi4.core.Matrix` or :class:`~psi4.core.Vector` (irreped if list). Parameters ---------- self Matrix or Vector class. arr NumPy array or list of arrays to use as the data for a new :class:`~psi4.core.Matrix` or :class:`~psi4.core.Vector`. name Name to give the new :class:`~psi4.core.Matrix`. dim1 If a single dense NumPy array is given, a dimension can be supplied to apply irreps to this array. Note that this discards all extra information given in the matrix besides the diagonal blocks determined by the passed dimension. dim2 Same as `dim1` only if using a :class:`~psi4.core.Dimension` object. Returns ------- Matrix or Vector Returns the given (`self`) Psi4 object. Notes ----- This is a generalized function to convert a NumPy array to a Psi4 object Examples -------- >>> data = np.random.rand(20,1) >>> vector = psi4.core.Matrix.from_array(data) >>> irrep_data = [np.random.rand(2, 2), np.empty(shape=(0,3)), np.random.rand(4, 4)] >>> matrix = psi4.core.Matrix.from_array(irrep_data) >>> print(matrix.rowdim().to_tuple()) (2, 0, 4) """ # What type is it? MRO can help. arr_type = self.__mro__[0] # Irreped case if isinstance(arr, (list, tuple)): if (dim1 is not None) or (dim2 is not None): raise ValidationError( "Array_to_Matrix: If passed input is list of arrays dimension cannot be specified." ) irreps = len(arr) if arr_type == core.Matrix: sdim1 = core.Dimension(irreps) sdim2 = core.Dimension(irreps) for i in range(irreps): d1, d2 = _find_dim(arr[i], 2) sdim1[i] = d1 sdim2[i] = d2 ret = self(name, sdim1, sdim2) elif arr_type == core.Vector: sdim1 = core.Dimension(irreps) for i in range(irreps): d1 = _find_dim(arr[i], 1) sdim1[i] = d1[0] ret = self(name, sdim1) else: raise ValidationError( "Array_to_Matrix: type '%s' is not recognized." % str(arr_type)) for view, vals in zip(ret.nph, arr): if 0 in view.shape: continue view[:] = vals return ret # No irreps implied by list else: if arr_type == core.Matrix: # Build an irreped array back out if dim1 is not None: if dim2 is None: raise ValidationError( "Array_to_Matrix: If dim1 is supplied must supply dim2 also" ) dim1 = core.Dimension.from_list(dim1) dim2 = core.Dimension.from_list(dim2) if dim1.n() != dim2.n(): raise ValidationError( "Array_to_Matrix: Length of passed dim1 must equal length of dim2." ) ret = self(name, dim1, dim2) start1 = 0 start2 = 0 for num, interface in enumerate(ret.nph): d1 = dim1[num] d2 = dim2[num] if (d1 == 0) or (d2 == 0): continue view = np.asarray(interface) view[:] = arr[start1:start1 + d1, start2:start2 + d2] start1 += d1 start2 += d2 return ret # Simple case without irreps else: ret = self(name, arr.shape[0], arr.shape[1]) ret.np[:] = arr return ret elif arr_type == core.Vector: # Build an irreped array back out if dim1 is not None: if dim2 is not None: raise ValidationError( "Array_to_Matrix: If dim2 should not be supplied for 1D vectors." ) dim1 = core.Dimension.from_list(dim1) ret = self(name, dim1) start1 = 0 for num, interface in enumerate(ret.nph): d1 = dim1[num] if (d1 == 0): continue view = np.asarray(interface) view[:] = arr[start1:start1 + d1] start1 += d1 return ret # Simple case without irreps else: ret = self(name, arr.shape[0]) ret.np[:] = arr return ret else: raise ValidationError( "Array_to_Matrix: type '%s' is not recognized." % str(arr_type))