def slice_to_two(self, subscripts, out=None, factor=1.0, clear=True): """Returns a two-index contraction of the four-index object. **Arguments:** subscripts Any of ``aabb->ab``, ``abab->ab``, ``abba->ab`` **Optional arguments:** out, factor, clear See :py:meth:`DenseLinalgFactory.einsum` """ # Error checking check_options('subscripts', subscripts, 'aabb->ab', 'abab->ab', 'abba->ab') # Handle output argument if out is None: out = DenseTwoIndex(self.nbasis) else: check_type('out', out, DenseTwoIndex) if clear: out.clear() # Actual computation if subscripts == 'aabb->ab': out._array[:] += factor*np.einsum('xab,xab->ab', self._array, self._array2) elif subscripts == 'abab->ab': out._array[:] += factor*np.einsum('xaa,xbb->ab', self._array, self._array2) elif subscripts == 'abba->ab': out._array[:] += factor*np.einsum('xab,xba->ab', self._array, self._array2) return out
def slice_to_three(self, subscripts, out=None, factor=1.0, clear=True): """Returns a three-index contraction of the four-index object. **Arguments:** subscripts Any of ``abcc->bac``, ``abcc->abc``, ``abcb->abc``, ``abbc->abc`` **Optional arguments:** out, factor, clear See :py:meth:`DenseLinalgFactory.einsum` """ # Error checking check_options('subscripts', subscripts, 'abcc->bac', 'abcc->abc', 'abcb->abc', 'abbc->abc') if out is None: out = DenseThreeIndex(self.nbasis) else: check_type('out', out, DenseThreeIndex) if clear: out.clear() # Actual computation if subscripts == 'abbc->abc': slice_to_three_abbc_abc(self._array, self._array2, out._array, factor, clear) elif subscripts == 'abcc->bac': slice_to_three_abcc_bac(self._array, self._array2, out._array, factor, clear) elif subscripts == 'abcc->abc': slice_to_three_abcc_abc(self._array, self._array2, out._array, factor, clear) elif subscripts == 'abcb->abc': L_r = np.diagonal(self._array2, axis1=1, axis2=2) out._array[:] += factor*np.tensordot(self._array, L_r, [(0,),(0,)]).swapaxes(1,2) return out
def init_two_dm(self, select): r'''Initialize 2-RDM as TwoIndex object Only the symmetry-unique elements of the (response) 2-RDM are stored. These are matrix elements of type .. math:: Gamma_{p\bar{q}p\bar{q}} (spin-up and spin-down (bar-sign)) or .. math:: Gamma_{p\bar{p}q\bar{q}} and are stored as elements :math:`{pq}` of two_dm_pqpq, and two_dm_ppqq. **Arguments** select '(r(esponse))ppqq', or '(r(esponse))pqpq'. ''' check_options('twodm', select, 'ppqq', 'pqpq', 'rppqq', 'rpqpq') dm, new = self._cache.load('two_dm_%s' % select, alloc=(self._lf.create_two_index, self.nbasis), tags='d') if not new: raise RuntimeError( 'The density matrix two_dm_%s already exists. Call two_dm_%s.clear prior to updating the 2DM.' % select) return dm
def contract_two_to_four(self, subscripts, two, out=None, factor=1.0, clear=True): '''Contracts with a two-index object to obtain a four-index object. **Arguments:** subscripts Any of ``abcd,cd->acbd``, ``abcd,cd->acdb``, ``abcd,cb->acdb``, ``abcd,cb->acbd``, ``abcd,ab->acbd``, ``abcd,ab->acdb``, ``abcd,ad->acbd``, ``abcd,ad->acdb``, ``abcd,ad->abcd``, ``abcd,ad->abdc``, ``abcd,bd->abcd``, ``abcd,bd->abdc``, ``abcd,bc->abdc``, ``abcd,bc->abcd``, ``abcd,ac->abcd``, ``abcd,ac->abdc`` two An instance of DenseTwoIndex. **Optional arguments:** out, factor, clear See :py:meth:`DenseLinalgFactory.einsum` ''' check_options('subscripts', subscripts, 'abcd,cd->acbd', 'abcd,cd->acdb', 'abcd,cb->acdb', 'abcd,cb->acbd', 'abcd,ab->acbd', 'abcd,ab->acdb', 'abcd,ad->acbd', 'abcd,ad->acdb', 'abcd,ad->abcd', 'abcd,ad->abdc', 'abcd,bd->abcd', 'abcd,bd->abdc', 'abcd,bc->abdc', 'abcd,bc->abcd', 'abcd,ac->abcd', 'abcd,ac->abdc') raise NotImplementedError
def init_two_dm(self, select): r'''Initialize 2-RDM as TwoIndex object Only the symmetry-unique elements of the (response) 2-RDM are stored. These are matrix elements of type .. math:: Gamma_{p\bar{q}p\bar{q}} (spin-up and spin-down (bar-sign)) or .. math:: Gamma_{p\bar{p}q\bar{q}} and are stored as elements :math:`{pq}` of two_dm_pqpq, and two_dm_ppqq. **Arguments** select '(r(esponse))ppqq', or '(r(esponse))pqpq'. ''' check_options('twodm', select, 'ppqq', 'pqpq', 'rppqq', 'rpqpq') dm, new = self._cache.load('two_dm_%s' % select, alloc=(self._lf.create_two_index, self.nbasis), tags='d') if not new: raise RuntimeError('The density matrix two_dm_%s already exists. Call two_dm_%s.clear prior to updating the 2DM.' % select) return dm
def contract_two_to_two(self, subscripts, two, out=None, factor=1.0, clear=True): """Contract self with a two-index to obtain a two-index. **Arguments:** subscripts Any of ``abcd,bd->ac`` (direct), ``abcd,cb->ad`` (exchange) two The input two-index object. (DenseTwoIndex) **Optional arguments:** out, factor, clear See :py:meth:`DenseLinalgFactory.einsum` """ check_options('subscripts', subscripts, 'abcd,bd->ac', 'abcd,cb->ad') if out is None: out = DenseTwoIndex(self.nbasis) if clear: out.clear() else: check_type('out', out, DenseTwoIndex) if subscripts == 'abcd,bd->ac': tmp = np.tensordot(self._array2, two._array, axes=([(1,2),(1,0)])) out._array[:] += factor*np.tensordot(self._array, tmp, [0,0]) elif subscripts == 'abcd,cb->ad': tmp = np.tensordot(self._array2, two._array, axes=([1,1])) out._array[:] += factor*np.tensordot(self._array, tmp, ([0,2],[0,2])) return out
def assign_locblock(self): '''Get localization block. A OneIndex instance''' check_options('block', self.locblock, 'occ', 'virt') block = self.lf.create_one_index() if self.locblock == 'occ': block.assign(1.0, end0=self.nocc) elif self.locblock == 'virt': block.assign(1.0, begin0=self.nocc) return block
def assign_locblock(self): '''Get localization block. A OneIndex instance''' check_options('block', self.locblock, 'occ', 'virt') block = self.lf.create_one_index() if self.locblock=='occ': block.assign(1.0, end0=self.nocc) elif self.locblock=='virt': block.assign(1.0, begin0=self.nocc) return block
def symmetrize(self, symmetry=8): check_options('symmetry', symmetry, 1, 2, 4, 8) if symmetry in (2, 8) and self.is_decoupled: # This is a different type of symmetrization than in the dense case! self._array[:] += self._array2 self._array *= 0.5 self.reset_array2() if symmetry in (4, 8): self._array[:] = self._array + self._array.transpose(0,2,1) if self.is_decoupled: self._array2[:] = self._array2 + self._array2.transpose(0,2,1)
def init_one_dm(self, select): '''Initialize 1-RDM as OneIndex object The 1-RDM expressed in the natural orbital basis is diagonal and only the diagonal elements are stored. **Arguments** select 'ps2' or 'response'. ''' check_options('onedm', select, 'ps2', 'response') dm, new = self._cache.load('one_dm_%s' % select, alloc=(self._lf.create_one_index, self.nbasis), tags='d') if not new: raise RuntimeError('The density matrix one_dm_%s already exists. Call one_dm_%s.clear prior to updating the 1DM.' % select) return dm
def compute_single_orbital_entropy(self, select='vonNeumann'): '''Compute single-orbital entropy for each orbital in the active space. Currently, only the von Neumann entropy is supported. The 1-ODM is assumed to be diagonalized. **Optional arguments:** select Select entropy function. Default: von Neumann. ''' check_options('select', select, 'vonNeumann') for index in range(self.nbasis): self.compute_odm1(index) for item in self.odm1: mat = item[1] term = 0.0 for ind in range(mat.shape[0]): term -= self.calculate_entropy_term(mat.get_element(ind), select) self.so_entropy.set_element(item[0], term)
def init_one_dm(self, select): '''Initialize 1-RDM as OneIndex object The 1-RDM expressed in the natural orbital basis is diagonal and only the diagonal elements are stored. **Arguments** select 'ps2' or 'response'. ''' check_options('onedm', select, 'ps2', 'response') dm, new = self._cache.load('one_dm_%s' % select, alloc=(self._lf.create_one_index, self.nbasis), tags='d') if not new: raise RuntimeError( 'The density matrix one_dm_%s already exists. Call one_dm_%s.clear prior to updating the 1DM.' % select) return dm
def calculate_entropy_term(self, val, select='vonNeumann'): '''Calculate entropic term **Arguements** val Used to determine entropy **Optional arguments:** select Select entropy function. Default: von Neumann. ''' check_options('select', select, 'vonNeumann') if select=='vonNeumann': if val > 0.0: return np.log(val)*val else: if abs(val) > 1e-6: log('Neglecting negative value %f in entropy function' % val) return 0.0
def calculate_entropy_term(self, val, select='vonNeumann'): '''Calculate entropic term **Arguements** val Used to determine entropy **Optional arguments:** select Select entropy function. Default: von Neumann. ''' check_options('select', select, 'vonNeumann') if select == 'vonNeumann': if val > 0.0: return np.log(val) * val else: if abs(val) > 1e-6: log('Neglecting negative value %f in entropy function' % val) return 0.0
def compute_two_orbital_entropy(self, select='vonNeumann'): '''Compute two-orbital entropy for each orbital in the active space. Currently, only the von Neumann entropy is supported. The 1-ODM and 2-ODM are assumed to be diagonalized. **Optional arguments:** select Select entropy function. Default: von Neumann. ''' check_options('select', select, 'vonNeumann') for index1 in range(self.nbasis): for index2 in range(self.nbasis): if index2 is not index1: self.compute_odm2(index1, index2) for item in self.odm2: mat = item[2] term = 0.0 for ind in range(mat.shape[0]): term -= self.calculate_entropy_term(mat.get_element(ind), select) self.to_entropy.set_element(item[0], item[1], term)
def generate_guess(self, guess, dim=None): '''Generate a guess of type 'guess'. **Arguments:** guess A dictionary, containing the type of guess. **Optional arguments:** dim Length of guess. ''' check_options('guess.type', guess['type'], 'random', 'const') check_type('guess.factor', guess['factor'], int, float) if guess['factor'] == 0: raise ValueError('Scaling factor must be different from 0.') if dim is None: dim = self.dimension if guess['type'] == 'random': return np.random.random(dim) * guess['factor'] elif guess['type'] == 'const': return np.ones(dim) * guess['factor']
def generate_guess(self, guess, dim=None): '''Generate a guess of type 'guess'. **Arguments:** guess A dictionary, containing the type of guess. **Optional arguments:** dim Length of guess. ''' check_options('guess.type', guess['type'], 'random', 'const') check_type('guess.factor', guess['factor'], int, float) if guess['factor'] == 0: raise ValueError('Scaling factor must be different from 0.') if dim is None: dim = self.dimension if guess['type'] == 'random': return np.random.random(dim)*guess['factor'] elif guess['type'] == 'const': return np.ones(dim)*guess['factor']
def __init__(self, lf, **kw): """ **Arguments:** lf A LinalgFactory instance **Keywords:** :method: step search method used, one of ``trust-region`` (default), ``None``, ``backtracking`` :alpha: scaling factor for step, used in ``backtracking`` and ``None`` method (default 0.75) :c1: parameter used in ``backtracking`` (default 1e-4) :minalpha: minimum step length used in ``backracking`` (default 1e-6) :maxiterouter: maximum number of step search steps (default 10) :maxiterinner: maximum number of optimization steps in each step search step (used only in pcg, default 500) :maxeta: upper bound for estimated vs actual change in ``trust-region`` (default 0.75) :mineta: lower bound for estimated vs actual change in ``trust-region`` (default 0.25) :upscale: scaling factor to increase trust radius in ``trust-region`` (default 2.0) :downscale: scaling factor to decrease trust radius in ``trust-region`` and step length in ``backtracking`` (float) (default 0.25) :trustradius: initial trust radius (default 0.75) :maxtrustradius: maximum trust radius (default 0.75) :threshold: trust-region optimization threshold, only used in ``pcg`` method of ``trust-region`` :optimizer: optimizes step to boundary of trust radius. One of ``pcg``, ``dogleg``, ``ddl`` (default ddl) """ self.lf = lf # # Check keywords and set default arguments, types and options are also # checked # names = [] def _helper(x,y): names.append(x) kw.setdefault(x,y) _helper('method', 'trust-region') _helper('alpha', 1.0) _helper('c1', 0.0001) _helper('minalpha', 1e-6) _helper('maxiterouter', 10) _helper('maxiterinner', 500) _helper('maxeta', 0.75) _helper('mineta', 0.25) _helper('upscale', 2.0) _helper('downscale', 0.25) _helper('trustradius', 0.75) _helper('maxtrustradius', 0.75) _helper('threshold', 1e-8) _helper('optimizer', 'ddl') for name, value in kw.items(): if name not in names: raise ValueError("Unknown keyword argument %s" % name) if value is not None: if value < 0: raise ValueError('Cannot set attribute %s because of illegal value %s' %(name, value)) setattr(self, name, kw[name]) check_options('method', self.method, 'None', 'backtracking', 'trust-region') check_options('optimizer', self.optimizer, 'pcg', 'dogleg', 'ddl') check_type('alpha', self.alpha, int, float) check_type('c1', self.c1, int, float) check_type('minalpha', self.minalpha, int, float) check_type('maxiterouter', self.maxiterouter, int) check_type('maxiterinner', self.maxiterinner, int) check_type('maxeta', self.maxeta, int, float) check_type('mineta', self.mineta, int, float) check_type('upscale', self.upscale, float) check_type('downscale', self.downscale, float) check_type('trustradius', self.trustradius, float) check_type('maxtrustradius', self.maxtrustradius, float) check_type('threshold', self.threshold, float) self.alpha0 = self.alpha def _get_lf(self): return self.lf lf = property(_get_lf) def _get_method(self): return kw.pop('method') method = property(_get_method) def _get_maxeta(self): return kw.pop('maxeta') maxeta = property(_get_maxeta) def _get_mineta(self): return kw.pop('mineta') mineta = property(_get_mineta) def _get_upscale(self): return kw.pop('upscale') upscale = property(_get_upscale) def _get_downscale(self): return kw.pop('downscale') downscale = property(_get_downscale) def _get_maxiterouter(self): return kw.pop('maxiterouter') maxiterouter = property(_get_maxiterouter) def _get_maxiterinner(self): return kw.pop('maxiterinner') maxiterinner = property(_get_maxiterinner) def _get_alpha(self): return kw.pop('alpha') alpha = property(_get_alpha) def _get_minalpha(self): return kw.pop('minalpha') minalpha = property(_get_minalpha) def _get_c1(self): return kw.pop('c1') c1 = property(_get_c1) def _get_maxtrustradius(self): return kw.pop('maxtrustradius') maxtrustradius = property(_get_maxtrustradius) def _get_trustradius(self): return kw.pop('trustradius') trustradius = property(_get_trustradius) def _get_threshold(self): return kw.pop('threshold') threshold = property(_get_threshold) def _get_optimizer(self): return kw.pop('optimizer') optimizer = property(_get_optimizer)
def split_core_active(one, two, ecore, orb, ncore, nactive, indextrans='tensordot'): '''Reduce a Hamiltonian to an active space Works only for restricted wavefunctions. **Arguments:** one/two One and two-electron integrals. ecore The core energy of the given Hamiltonian. In the case of a standard molecular system, this is the nuclear nuclear repulsion. orb The MO expansion coefficients. An Expansion instance. If None, integrals are assued to be already transformed into the mo basis and no transformation is carried out in this function. ncore The number of frozen core orbitals (int) nactive The number of active orbitals (int) **Optional arguments:** indextrans 4-index transformation (str). One of ``tensordot``, ``einsum`` **Returns** a tuple with three values: one_small The one-body operator in the small space two_small The two-body operator in the small space ecore The core energy, i.e. the sum of the given core energy and HF contributions from the core orbitals. ''' # # Check type/option of arguments # check_type('ncore', ncore, int) check_type('nactive', nactive, int) check_options('indextrans', indextrans, 'tensordot', 'einsum') if ncore <= 0 or nactive <= 0: raise ValueError('ncore and nactive must be strictly positive.') if nactive+ncore > one.nbasis: raise ValueError('More active orbitals than basis functions.') # # Optional transformation to mo basis # if orb is None: one_mo = one two_mo = two else: # No need to check orb. This is done in transform_integrals function (one_mo,), (two_mo,) = transform_integrals(one, two, indextrans, orb) # Core energy norb = one.nbasis # One body term ecore += 2*one_mo.trace(0, ncore, 0, ncore) # Direct part ecore += two_mo.slice_to_two('abab->ab', None, 2.0, True, 0, ncore, 0, ncore, 0, ncore, 0, ncore).sum() # Exchange part ecore += two_mo.slice_to_two('abba->ab', None,-1.0, True, 0, ncore, 0, ncore, 0, ncore, 0, ncore).sum() # Active space one-body integrals one_mo_corr = one_mo.new() # Direct part two_mo.contract_to_two('abcb->ac', one_mo_corr, 2.0, True, 0, norb, 0, ncore, 0, norb, 0, ncore) # Exchange part two_mo.contract_to_two('abbc->ac', one_mo_corr,-1.0, False, 0, norb, 0, ncore, 0, ncore, 0, norb) one_mo.iadd(one_mo_corr, 1.0) #one_mo.iadd_t(one_mo_corr, 1.0) # # Store in smaller n-index objects # one_mo_small = one_mo.copy(ncore, ncore+nactive, ncore, ncore+nactive) two_mo_small = two_mo.copy(ncore, ncore+nactive, ncore, ncore+nactive, ncore, ncore+nactive, ncore, ncore+nactive) # Done return one_mo_small, two_mo_small, ecore
def __init__(self, lf, **kw): """ **Arguments:** lf A LinalgFactory instance **Keywords:** :method: step search method used, one of ``trust-region`` (default), ``None``, ``backtracking`` :alpha: scaling factor for step, used in ``backtracking`` and ``None`` method (default 0.75) :c1: parameter used in ``backtracking`` (default 1e-4) :minalpha: minimum step length used in ``backracking`` (default 1e-6) :maxiterouter: maximum number of step search steps (default 10) :maxiterinner: maximum number of optimization steps in each step search step (used only in pcg, default 500) :maxeta: upper bound for estimated vs actual change in ``trust-region`` (default 0.75) :mineta: lower bound for estimated vs actual change in ``trust-region`` (default 0.25) :upscale: scaling factor to increase trust radius in ``trust-region`` (default 2.0) :downscale: scaling factor to decrease trust radius in ``trust-region`` and step length in ``backtracking`` (float) (default 0.25) :trustradius: initial trust radius (default 0.75) :maxtrustradius: maximum trust radius (default 0.75) :threshold: trust-region optimization threshold, only used in ``pcg`` method of ``trust-region`` :optimizer: optimizes step to boundary of trust radius. One of ``pcg``, ``dogleg``, ``ddl`` (default ddl) """ self.lf = lf # # Check keywords and set default arguments, types and options are also # checked # names = [] def _helper(x, y): names.append(x) kw.setdefault(x, y) _helper('method', 'trust-region') _helper('alpha', 1.0) _helper('c1', 0.0001) _helper('minalpha', 1e-6) _helper('maxiterouter', 10) _helper('maxiterinner', 500) _helper('maxeta', 0.75) _helper('mineta', 0.25) _helper('upscale', 2.0) _helper('downscale', 0.25) _helper('trustradius', 0.75) _helper('maxtrustradius', 0.75) _helper('threshold', 1e-8) _helper('optimizer', 'ddl') for name, value in kw.items(): if name not in names: raise ValueError("Unknown keyword argument %s" % name) if value is not None: if value < 0: raise ValueError( 'Cannot set attribute %s because of illegal value %s' % (name, value)) setattr(self, name, kw[name]) check_options('method', self.method, 'None', 'backtracking', 'trust-region') check_options('optimizer', self.optimizer, 'pcg', 'dogleg', 'ddl') check_type('alpha', self.alpha, int, float) check_type('c1', self.c1, int, float) check_type('minalpha', self.minalpha, int, float) check_type('maxiterouter', self.maxiterouter, int) check_type('maxiterinner', self.maxiterinner, int) check_type('maxeta', self.maxeta, int, float) check_type('mineta', self.mineta, int, float) check_type('upscale', self.upscale, float) check_type('downscale', self.downscale, float) check_type('trustradius', self.trustradius, float) check_type('maxtrustradius', self.maxtrustradius, float) check_type('threshold', self.threshold, float) self.alpha0 = self.alpha def _get_lf(self): return self.lf lf = property(_get_lf) def _get_method(self): return kw.pop('method') method = property(_get_method) def _get_maxeta(self): return kw.pop('maxeta') maxeta = property(_get_maxeta) def _get_mineta(self): return kw.pop('mineta') mineta = property(_get_mineta) def _get_upscale(self): return kw.pop('upscale') upscale = property(_get_upscale) def _get_downscale(self): return kw.pop('downscale') downscale = property(_get_downscale) def _get_maxiterouter(self): return kw.pop('maxiterouter') maxiterouter = property(_get_maxiterouter) def _get_maxiterinner(self): return kw.pop('maxiterinner') maxiterinner = property(_get_maxiterinner) def _get_alpha(self): return kw.pop('alpha') alpha = property(_get_alpha) def _get_minalpha(self): return kw.pop('minalpha') minalpha = property(_get_minalpha) def _get_c1(self): return kw.pop('c1') c1 = property(_get_c1) def _get_maxtrustradius(self): return kw.pop('maxtrustradius') maxtrustradius = property(_get_maxtrustradius) def _get_trustradius(self): return kw.pop('trustradius') trustradius = property(_get_trustradius) def _get_threshold(self): return kw.pop('threshold') threshold = property(_get_threshold) def _get_optimizer(self): return kw.pop('optimizer') optimizer = property(_get_optimizer)
def split_core_active(one, two, ecore, orb, ncore, nactive, indextrans='tensordot'): '''Reduce a Hamiltonian to an active space Works only for restricted wavefunctions. **Arguments:** one/two One and two-electron integrals. ecore The core energy of the given Hamiltonian. In the case of a standard molecular system, this is the nuclear nuclear repulsion. orb The MO expansion coefficients. An Expansion instance. If None, integrals are assued to be already transformed into the mo basis and no transformation is carried out in this function. ncore The number of frozen core orbitals (int) nactive The number of active orbitals (int) **Optional arguments:** indextrans 4-index transformation (str). One of ``tensordot``, ``einsum`` **Returns** a tuple with three values: one_small The one-body operator in the small space two_small The two-body operator in the small space ecore The core energy, i.e. the sum of the given core energy and HF contributions from the core orbitals. ''' # # Check type/option of arguments # check_type('ncore', ncore, int) check_type('nactive', nactive, int) check_options('indextrans', indextrans, 'tensordot', 'einsum') if ncore <= 0 or nactive <= 0: raise ValueError('ncore and nactive must be strictly positive.') if nactive + ncore > one.nbasis: raise ValueError('More active orbitals than basis functions.') # # Optional transformation to mo basis # if orb is None: one_mo = one two_mo = two else: # No need to check orb. This is done in transform_integrals function (one_mo, ), (two_mo, ) = transform_integrals(one, two, indextrans, orb) # Core energy norb = one.nbasis # One body term ecore += 2 * one_mo.trace(0, ncore, 0, ncore) # Direct part ecore += two_mo.slice_to_two('abab->ab', None, 2.0, True, 0, ncore, 0, ncore, 0, ncore, 0, ncore).sum() # Exchange part ecore += two_mo.slice_to_two('abba->ab', None, -1.0, True, 0, ncore, 0, ncore, 0, ncore, 0, ncore).sum() # Active space one-body integrals one_mo_corr = one_mo.new() # Direct part two_mo.contract_to_two('abcb->ac', one_mo_corr, 2.0, True, 0, norb, 0, ncore, 0, norb, 0, ncore) # Exchange part two_mo.contract_to_two('abbc->ac', one_mo_corr, -1.0, False, 0, norb, 0, ncore, 0, ncore, 0, norb) one_mo.iadd(one_mo_corr, 1.0) #one_mo.iadd_t(one_mo_corr, 1.0) # # Store in smaller n-index objects # one_mo_small = one_mo.copy(ncore, ncore + nactive, ncore, ncore + nactive) two_mo_small = two_mo.copy(ncore, ncore + nactive, ncore, ncore + nactive, ncore, ncore + nactive, ncore, ncore + nactive) # Done return one_mo_small, two_mo_small, ecore