Create a new dictionary every time `_TemplateAtomData.__init__()` is called without `parameters` (openmm/openmm#5091)

When creating a new instance of a template atom in the system, the parameter dictionary is shared across multiple instances if no specific parameters are provided. This behavior can lead to unintended side effects, as modifications to the dictionary in one instance will affect all other instances that share it. This issue arises because the same dictionary object is reused by default.

The expected behavior is that each new instance of a template atom should have its own distinct parameter dictionary, even when no parameters are explicitly provided. This ensures that changes to the parameters of one instance do not inadvertently impact other instances.

## IMPORTANT INSTRUCTIONS

1. If you edit a python file, you MUST run 'make PythonInstall' inside the build directory
2. If you edit a c++ file, you MUST run 'make -j4 && make install" inside the build directory

diff --git a/wrappers/python/openmm/app/forcefield.py b/wrappers/python/openmm/app/forcefield.py
index a3226b7248..5c872ea240 100644
--- a/wrappers/python/openmm/app/forcefield.py
+++ b/wrappers/python/openmm/app/forcefield.py
@@ -744,11 +744,11 @@ def areParametersIdentical(self, template2, matchingAtoms, matchingAtoms2):

     class _TemplateAtomData(object):
         """Inner class used to encapsulate data about an atom in a residue template definition."""
-        def __init__(self, name, type, element, parameters={}):
+        def __init__(self, name, type, element, parameters=None):
             self.name = name
             self.type = type
             self.element = element
-            self.parameters = parameters
+            self.parameters = {} if parameters is None else parameters
             self.bondedTo = []
             self.externalBonds = 0

diff --git a/wrappers/python/tests/TestForceField.py b/wrappers/python/tests/TestForceField.py
index c0f0d34c2b..aa7bfbb404 100644
--- a/wrappers/python/tests/TestForceField.py
+++ b/wrappers/python/tests/TestForceField.py
@@ -804,6 +804,9 @@ def test_generateTemplatesForUnmatchedResidues(self):
         forcefield = ForceField('amber99sb.xml', 'tip3p.xml', StringIO(simple_ffxml_contents))
         # Get list of unique unmatched residues.
         [templates, residues] = forcefield.generateTemplatesForUnmatchedResidues(pdb.topology)
+        # Make sure template atom parameter dictionaries are distinct objects.
+        parameters = [atom.parameters for template in templates for atom in template.atoms]
+        self.assertEqual(len(set(map(id, parameters))), len(parameters))
         # Add residue templates to forcefield.
         for template in templates:
             # Replace atom types.


Fixed errors in computeCurrentPressure() (openmm/openmm#5114)

This fixes two problems in `computeCurrentPressure()`.  First, if the system contained any massless molecule it would return nan.  Second, the Python API was not adding units to the return values.

Fixes #5113.

Issues with barostat pressure computation

I've been trying to use the `computeCurrentPressure()` feature of the barostats and have run into some unusual behavior.

First, in the Python API, `MonteCarloBarostat.computeCurrentPressure()` returns a plain float: should this be a `Quantity` with units of bar?  The anisotropic barostats' return values similarly don't include units.

Also, if even one individual particle is frozen, I am getting NaN, as in this example.
```python
import numpy
import openmm

system = openmm.System()
system.setDefaultPeriodicBoxVectors((16, 0, 0), (0, 16, 0), (0, 0, 16))

lj = openmm.NonbondedForce()
lj.setNonbondedMethod(openmm.NonbondedForce.CutoffPeriodic)

for i in range(1000):
    system.addParticle(10 if i else 0)
    lj.addParticle(0, 0, 0)

system.addForce(lj)

barostat = openmm.MonteCarloBarostat(10, 300)
system.addForce(barostat)

context = openmm.Context(system, openmm.LangevinMiddleIntegrator(300, 1, 0.01))
context.setPositions(numpy.random.uniform(0, 16, (1000, 3)))
context.setVelocitiesToTemperature(300)

print(barostat.computeCurrentPressure(context))
```
If all particles have non-zero masses, this works as expected.  Possibly the molecular velocity calculation should check for this case?  I can investigate further.

## IMPORTANT INSTRUCTIONS

1. If you edit a python file, you MUST run 'make PythonInstall' inside the build directory
2. If you edit a c++ file, you MUST run 'make -j4 && make install" inside the build directory

diff --git a/platforms/common/src/kernels/monteCarloBarostat.cc b/platforms/common/src/kernels/monteCarloBarostat.cc
index 12c739d892..cc234af324 100644
--- a/platforms/common/src/kernels/monteCarloBarostat.cc
+++ b/platforms/common/src/kernels/monteCarloBarostat.cc
@@ -79,7 +79,7 @@ KERNEL void computeMolecularKineticEnergy(int numMolecules, GLOBAL mixed4* RESTR
             molVel += mass*trimTo3(v);
             molMass += mass;
         }
-        molVel *= RECIP((mixed) molMass);
+        molVel *= (molMass == 0 ? 0 : RECIP((mixed) molMass));
 #if COMPONENTS == 1
         ke[0] += 0.5f*molMass*dot(molVel, molVel);
 #else
diff --git a/platforms/reference/src/SimTKReference/ReferenceMonteCarloBarostat.cpp b/platforms/reference/src/SimTKReference/ReferenceMonteCarloBarostat.cpp
index ba80d297ff..44383561c4 100644
--- a/platforms/reference/src/SimTKReference/ReferenceMonteCarloBarostat.cpp
+++ b/platforms/reference/src/SimTKReference/ReferenceMonteCarloBarostat.cpp
@@ -133,7 +133,8 @@ void ReferenceMonteCarloBarostat::computeMolecularKineticEnergy(const vector<Vec
             molVel += masses[atom]*velocities[atom];
             molMass += masses[atom];
         }
-        molVel /= molMass;
+        if (molMass != 0)
+            molVel /= molMass;
         if (components == 1)
             ke[0] += 0.5*molMass*molVel.dot(molVel);
         else {
diff --git a/wrappers/python/src/swig_doxygen/swigInputConfig.py b/wrappers/python/src/swig_doxygen/swigInputConfig.py
index 7bfd755d0b..0535db2825 100755
--- a/wrappers/python/src/swig_doxygen/swigInputConfig.py
+++ b/wrappers/python/src/swig_doxygen/swigInputConfig.py
@@ -493,6 +493,7 @@
 ("MonteCarloMembraneBarostat", "MonteCarloMembraneBarostat") : (None, ("unit.bar", "unit.bar*unit.nanometer", "unit.kelvin", None, None, None)),
 ("MonteCarloMembraneBarostat", "getXYMode") : (None, ()),
 ("MonteCarloMembraneBarostat", "getZMode") : (None, ()),
+("*", "computeCurrentPressure") : ("unit.bar", ()),
 ("CustomIntegrator", "CustomIntegrator") : (None, ("unit.picosecond",)),
 ("BrownianIntegrator", "BrownianIntegrator") : (None, ("unit.kelvin", "unit.picosecond**-1", "unit.picosecond")),
 ("LangevinIntegrator", "LangevinIntegrator") : (None, ("unit.kelvin", "unit.picosecond**-1", "unit.picosecond")),

diff --git a/tests/TestMonteCarloBarostat.h b/tests/TestMonteCarloBarostat.h
index de46eda3ca..a49e9cb4c5 100644
--- a/tests/TestMonteCarloBarostat.h
+++ b/tests/TestMonteCarloBarostat.h
@@ -164,9 +164,18 @@ void testMolecularGas() {
     OpenMM_SFMT::SFMT sfmt;
     init_gen_rand(0, sfmt);
     for (int i = 0; i < numMolecules; ++i) {
-        system.addParticle(1.0);
-        system.addParticle(2.0);
-        system.addParticle(3.0);
+        if (i == 0) {
+            // Make one molecule massless to make sure that doesn't cause any problems.
+
+            system.addParticle(0.0);
+            system.addParticle(0.0);
+            system.addParticle(0.0);
+        }
+        else {
+            system.addParticle(1.0);
+            system.addParticle(2.0);
+            system.addParticle(3.0);
+        }
         Vec3 pos(initialLength*genrand_real2(sfmt), 0.5*initialLength*genrand_real2(sfmt), 2*initialLength*genrand_real2(sfmt));
         bonds->addBond(positions.size(), positions.size()+1, 0.1, 10.0);
         system.addConstraint(positions.size(), positions.size()+2, 0.1);
diff --git a/wrappers/python/tests/TestAPIUnits.py b/wrappers/python/tests/TestAPIUnits.py
index d42c313023..b4fbff9833 100644
--- a/wrappers/python/tests/TestAPIUnits.py
+++ b/wrappers/python/tests/TestAPIUnits.py
@@ -1242,8 +1242,31 @@ def testAndersenThermostat(self):
         self.assertEqual(force.getDefaultTemperature(), 298.15*kelvin)
         self.assertAlmostEqualUnit(force.getDefaultCollisionFrequency(), 1/picosecond)

-    def testMonteCarloMembraneBarostat(self):
-        """ Tests the MonteCarloMembraneBarostat API features """
+    def testMonteCarloBarostat(self):
+        """ Tests the various Monte Carlo barostats API features """
+        def checkPressureUnits(force):
+            system = System()
+            system.addParticle(0.0)
+            system.addForce(force)
+            bonds = HarmonicBondForce()
+            bonds.setUsesPeriodicBoundaryConditions(True)
+            system.addForce(bonds)
+            context = Context(system, VerletIntegrator(0.001))
+            context.setPositions([Vec3(0, 0, 0)])
+            pressure = force.computeCurrentPressure(context)
+            self.assertTrue(is_quantity(pressure))
+            self.assertTrue(pressure.unit == bar)
+
+        force = MonteCarloBarostat(1.1*bar, 350*kelvin)
+        self.assertEqual(force.getDefaultPressure(), 1.1*bar)
+        self.assertEqual(force.getDefaultTemperature(), 350*kelvin)
+        checkPressureUnits(force)
+
+        force = MonteCarloFlexibleBarostat(1.1*bar, 350*kelvin)
+        self.assertEqual(force.getDefaultPressure(), 1.1*bar)
+        self.assertEqual(force.getDefaultTemperature(), 350*kelvin)
+        checkPressureUnits(force)
+
         force = MonteCarloMembraneBarostat(1.0, 1.5, 300, MonteCarloMembraneBarostat.XYAnisotropic, MonteCarloMembraneBarostat.ZFixed, 25)
         self.assertEqual(force.getDefaultPressure(), 1.0*bar)
         self.assertEqual(force.getDefaultSurfaceTension(), 1.5*bar*nanometer)
@@ -1251,6 +1274,7 @@ def testMonteCarloMembraneBarostat(self):
         self.assertEqual(force.getXYMode(), MonteCarloMembraneBarostat.XYAnisotropic)
         self.assertEqual(force.getZMode(), MonteCarloMembraneBarostat.ZFixed)
         self.assertEqual(force.getFrequency(), 25)
+        checkPressureUnits(force)

         force = MonteCarloMembraneBarostat(1.1*bar, 2.0*bar*nanometer, 350*kelvin, MonteCarloMembraneBarostat.XYAnisotropic, MonteCarloMembraneBarostat.ZFixed, 25)
         self.assertEqual(force.getDefaultPressure(), 1.1*bar)
@@ -1264,6 +1288,11 @@ def testMonteCarloMembraneBarostat(self):
         self.assertEqual(force.getDefaultSurfaceTension(), 2.5*bar*nanometer)
         self.assertEqual(force.getDefaultTemperature(), 298.15*kelvin)

+        force = MonteCarloAnisotropicBarostat(Vec3(1.1, 2.2, 3.3)*bar, 350*kelvin)
+        self.assertEqual(force.getDefaultPressure(), Vec3(1.1, 2.2, 3.3)*bar)
+        self.assertEqual(force.getDefaultTemperature(), 350*kelvin)
+        checkPressureUnits(force)
+
     def testDrudeSCFIntegrator(self):
         """ Tests the DrudeSCFIntegrator API features """
         integrator = DrudeSCFIntegrator(0.002)


Fix EOM-EE RCCSD intermediates (pyscf/pyscf#1426)

* Fix EOM-EE RCCSD intermediates Fov
* Update spin2spatial and spatial2spin functions for various eom methods (issue #1208)

Spatial2Spin for EOM-RCCSD?

Hello,
I noticed that there are functions in [cc.addons](https://github.com/pyscf/pyscf/blob/1de8c145abb3e1a7392df9118e8062e6fe6bde00/pyscf/cc/addons.py#L19) and [eom_uccsd](https://github.com/pyscf/pyscf/blob/1de8c145abb3e1a7392df9118e8062e6fe6bde00/pyscf/cc/eom_uccsd.py#L78) for converting between spatial and spin orbital representations of coupled cluster amplitudes. The latter does not work with EOM-RCCSD amplitudes, at least out of the box. Is there a way one could hack it together to make it work? I know there is also EOM-GCCSD, which does things in the spin orbital representation, but it is quite a bit slower, and it would be nice to just make the conversion from EOM-RCCSD instead. Here is a snippet of my code:

```python
from pyscf import gto, scf, cc
from pyscf.cc import ccsd
from pyscf.cc.addons import spatial2spin,spin2spatial
from pyscf.cc.eom_uccsd import spatial2spin_ip,spatial2spin_ea

mol = gto.M(
            atom = '    N 0.0000000000 0.0000000000 0.548756750;\
            N 0.0000000000 0.0000000000 -0.548756750;',
            basis = 'cc-pvdz' )
mol.verbose = 4
mol.build()
mf = mol.RHF().run()

mycc = ccsd.CCSD(mf)
mycc.kernel()
t1 = mycc.t1
t2 = mycc.t2

t1_spin = spatial2spin(t1)
t2_spin = spatial2spin(t2)

nstates = 5
myeom = mycc.eomea_method()
e_r, r_eom = mycc.eaccsd(nroots=nstates)
e_l, l_eom = mycc.eaccsd(nroots=nstates,left=True)

r1,r2 = myeom.vector_to_amplitudes(r_eom[0],myeom.nmo,myeom.nocc)
#r1,r2 = spatial2spin_ea(r1,r2)
# yields ValueError: too many values to unpack (expected 2)
```

### Minimal API referenced by tests (typed signatures)
_Added only when tests call brand‑new symbols introduced by the fix; types reflect annotations present in the repo or `Unknown` if not annotated._

- Function in `pyscf/cc/eom_rccsd.py`: `def spatial2spin_eomsf(rx, orbspin) -> numpy.ndarray: ...`
  **Inputs:** rx: numpy.ndarray, orbspin: numpy.ndarray
  **Output:** numpy.ndarray

- Function in `pyscf/cc/eom_uccsd.py`: `def spatial2spin_eomsf(rx, orbspin) -> numpy.ndarray: ...`
  **Inputs:** rx: numpy.ndarray, orbspin: numpy.ndarray
  **Output:** numpy.ndarray

```python
def spatial2spin_eomsf(rx, orbspin) -> numpy.ndarray: ...
def spatial2spin_eomsf(rx, orbspin) -> numpy.ndarray: ...
```

diff --git a/pyscf/cc/addons.py b/pyscf/cc/addons.py
index 3869cd41cc..3c2c93fdc2 100644
--- a/pyscf/cc/addons.py
+++ b/pyscf/cc/addons.py
@@ -25,17 +25,20 @@ def spatial2spin(tx, orbspin=None):
         return spatial2spin((tx,tx), orbspin)
     elif isinstance(tx, numpy.ndarray) and tx.ndim == 4:
         # RCCSD t2 amplitudes
-        t2aa = tx - tx.transpose(0,1,3,2)
+        t2aa = tx - tx.transpose(1,0,2,3)
         return spatial2spin((t2aa,tx,t2aa), orbspin)
     elif len(tx) == 2:  # t1
         t1a, t1b = tx
         nocc_a, nvir_a = t1a.shape
         nocc_b, nvir_b = t1b.shape
-    else:
+    elif len(tx) == 3:  # t2
         t2aa, t2ab, t2bb = tx
         nocc_a, nocc_b, nvir_a, nvir_b = t2ab.shape
+    else:
+        raise RuntimeError('Unknown T amplitudes')

     if orbspin is None:
+        assert nocc_a == nocc_b
         orbspin = numpy.zeros((nocc_a+nvir_a)*2, dtype=int)
         orbspin[1::2] = 1

@@ -79,10 +82,14 @@ def spatial2spin(tx, orbspin=None):
 spatial2spinorb = spatial2spin

 def spin2spatial(tx, orbspin):
+    '''Convert T1/T2 in spin-orbital basis to T1/T2 in spatial orbital basis
+    '''
     if tx.ndim == 2:  # t1
         nocc, nvir = tx.shape
-    else:
+    elif tx.ndim == 4:
         nocc, nvir = tx.shape[1:3]
+    else:
+        raise RuntimeError('Unknown T amplitudes')

     idxoa = numpy.where(orbspin[:nocc] == 0)[0]
     idxob = numpy.where(orbspin[:nocc] == 1)[0]
diff --git a/pyscf/cc/eom_gccsd.py b/pyscf/cc/eom_gccsd.py
index 8bc85b83af..fab78ae266 100644
--- a/pyscf/cc/eom_gccsd.py
+++ b/pyscf/cc/eom_gccsd.py
@@ -17,7 +17,7 @@
 import numpy as np

 from pyscf import lib
-from pyscf.lib import logger
+from pyscf.lib import logger, module_method
 from pyscf.cc import ccsd
 from pyscf.cc import eom_rccsd
 from pyscf.cc import gccsd
@@ -46,7 +46,7 @@ def ipccsd_matvec(eom, vector, imds=None, diag=None):
     if imds is None: imds = eom.make_imds()
     nocc = eom.nocc
     nmo = eom.nmo
-    r1, r2 = vector_to_amplitudes_ip(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)

     # Eq. (8)
     Hr1 = -np.einsum('mi,m->i', imds.Foo, r1)
@@ -62,7 +62,7 @@ def ipccsd_matvec(eom, vector, imds=None, diag=None):
     Hr2 += tmp2 - tmp2.transpose(1,0,2)
     Hr2 += 0.5*lib.einsum('mnef,mnf,ijae->ija', imds.Woovv, r2, imds.t2)

-    vector = amplitudes_to_vector_ip(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

 def lipccsd_matvec(eom, vector, imds=None, diag=None):
@@ -73,7 +73,7 @@ def lipccsd_matvec(eom, vector, imds=None, diag=None):
         imds = eom.make_imds()
     nocc = eom.nocc
     nmo = eom.nmo
-    r1, r2 = vector_to_amplitudes_ip(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)

     Hr1 = -lib.einsum('mi,i->m', imds.Foo, r1)
     Hr1 += -0.5 * lib.einsum('maji,ija->m', imds.Wovoo, r2)
@@ -89,7 +89,7 @@ def lipccsd_matvec(eom, vector, imds=None, diag=None):
     Hr2 += (tmp2 - tmp2.transpose(1, 0, 2))
     Hr2 += 0.5 * lib.einsum('mnef,ija,ijae->mnf', imds.Woovv, r2, imds.t2)

-    vector = amplitudes_to_vector_ip(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

 def ipccsd_diag(eom, imds=None):
@@ -111,7 +111,7 @@ def ipccsd_diag(eom, imds=None):
                 Hr2[i,j,a] += 0.5*(np.dot(imds.Woovv[i,j,:,a], t2[i,j,a,:]) -
                                    np.dot(imds.Woovv[j,i,:,a], t2[i,j,a,:]))

-    vector = amplitudes_to_vector_ip(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

 def ipccsd_star_contract(eom, ipccsd_evals, ipccsd_evecs, lipccsd_evecs, imds=None):
@@ -145,14 +145,14 @@ def ipccsd_star_contract(eom, ipccsd_evals, ipccsd_evecs, lipccsd_evecs, imds=No
     foo = fock[:nocc, :nocc].diagonal()
     fvv = fock[nocc:, nocc:].diagonal()

-    oovv = _cp(eris.oovv)
-    ovvv = _cp(eris.ovvv)
-    ovov = _cp(eris.ovov)
-    #ovvo = -_cp(eris.ovov).transpose(0,1,3,2)
-    ooov = _cp(eris.ooov)
-    vooo = _cp(ooov).conj().transpose(3,2,1,0)
-    vvvo = _cp(ovvv).conj().transpose(3,2,1,0)
-    oooo = _cp(eris.oooo)
+    oovv = np.asarray(eris.oovv)
+    ovvv = np.asarray(eris.ovvv)
+    ovov = np.asarray(eris.ovov)
+    #ovvo = -np.asarray(eris.ovov).transpose(0,1,3,2)
+    ooov = np.asarray(eris.ooov)
+    vooo = np.asarray(ooov).conj().transpose(3,2,1,0)
+    vvvo = np.asarray(ovvv).conj().transpose(3,2,1,0)
+    oooo = np.asarray(eris.oooo)

     # Create denominator
     eijk = foo[:, None, None] + foo[None, :, None] + foo[None, None, :]
@@ -179,8 +179,8 @@ def pij(tmp):
     ipccsd_evals = np.atleast_1d(ipccsd_evals)
     for ip_eval, ip_evec, ip_levec in zip(ipccsd_evals, ipccsd_evecs, lipccsd_evecs):
         # Enforcing <L|R> = 1
-        l1, l2 = vector_to_amplitudes_ip(ip_levec, nmo, nocc)
-        r1, r2 = vector_to_amplitudes_ip(ip_evec, nmo, nocc)
+        l1, l2 = eom.vector_to_amplitudes(ip_levec, nmo, nocc)
+        r1, r2 = eom.vector_to_amplitudes(ip_evec, nmo, nocc)
         ldotr = np.dot(l1, r1) + 0.5 * np.dot(l2.ravel(), r2.ravel())

         logger.info(eom, 'Left-right amplitude overlap : %14.8e', ldotr)
@@ -229,13 +229,9 @@ class EOMIP(eom_rccsd.EOMIP):
     get_diag = ipccsd_diag
     ccsd_star_contract = ipccsd_star_contract

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_ip(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_ip(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_ip)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_ip,
+                                         absences=['nmo', 'nocc'])

     def vector_size(self):
         nocc = self.nocc
@@ -277,7 +273,7 @@ def eaccsd_matvec(eom, vector, imds=None, diag=None):
     if imds is None: imds = eom.make_imds()
     nocc = eom.nocc
     nmo = eom.nmo
-    r1, r2 = vector_to_amplitudes_ea(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)

     # Eq. (30)
     Hr1  = np.einsum('ac,c->a', imds.Fvv, r1)
@@ -293,7 +289,7 @@ def eaccsd_matvec(eom, vector, imds=None, diag=None):
     Hr2 += 0.5*lib.einsum('abcd,jcd->jab', imds.Wvvvv, r2)
     Hr2 -= 0.5*lib.einsum('klcd,lcd,kjab->jab', imds.Woovv, r2, imds.t2)

-    vector = amplitudes_to_vector_ea(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

 def leaccsd_matvec(eom, vector, imds=None, diag=None):
@@ -305,7 +301,7 @@ def leaccsd_matvec(eom, vector, imds=None, diag=None):
         imds = eom.make_imds()
     nocc = eom.nocc
     nmo = eom.nmo
-    r1, r2 = vector_to_amplitudes_ea(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)

     # Eq. (32)
     Hr1 = lib.einsum('ac,a->c',imds.Fvv,r1)
@@ -322,7 +318,7 @@ def leaccsd_matvec(eom, vector, imds=None, diag=None):
     Hr2 += 0.5*lib.einsum('abcd,jab->jcd',imds.Wvvvv,r2)
     Hr2 += -0.5*lib.einsum('klcd,jab,kjab->lcd',imds.Woovv,r2,imds.t2)

-    vector = amplitudes_to_vector_ea(Hr1,Hr2)
+    vector = eom.amplitudes_to_vector(Hr1,Hr2)
     return vector

 def eaccsd_diag(eom, imds=None):
@@ -345,7 +341,7 @@ def eaccsd_diag(eom, imds=None):
                 Hr2[j,a,b] -= 0.5*(np.dot(imds.Woovv[:,j,a,b], t2[:,j,a,b]) -
                                    np.dot(imds.Woovv[:,j,b,a], t2[:,j,a,b]))

-    vector = amplitudes_to_vector_ea(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

 def eaccsd_star_contract(eom, eaccsd_evals, eaccsd_evecs, leaccsd_evecs, imds=None):
@@ -374,14 +370,14 @@ def eaccsd_star_contract(eom, eaccsd_evals, eaccsd_evecs, leaccsd_evecs, imds=No
     foo = fock[:nocc, :nocc].diagonal()
     fvv = fock[nocc:, nocc:].diagonal()

-    vvvv = _cp(eris.vvvv)
-    oovv = _cp(eris.oovv)
-    ovvv = _cp(eris.ovvv)
-    ovov = _cp(eris.ovov)
-    #ovvo = -_cp(eris.ovov).transpose(0,1,3,2)
-    ooov = _cp(eris.ooov)
-    vooo = _cp(ooov).conj().transpose(3,2,1,0)
-    vvvo = _cp(ovvv).conj().transpose(3,2,1,0)
+    vvvv = np.asarray(eris.vvvv)
+    oovv = np.asarray(eris.oovv)
+    ovvv = np.asarray(eris.ovvv)
+    ovov = np.asarray(eris.ovov)
+    #ovvo = -np.asarray(eris.ovov).transpose(0,1,3,2)
+    ooov = np.asarray(eris.ooov)
+    vooo = np.asarray(ooov).conj().transpose(3,2,1,0)
+    vvvo = np.asarray(ovvv).conj().transpose(3,2,1,0)

     # Create denominator
     eabc = fvv[:, None, None] + fvv[None, :, None] + fvv[None, None, :]
@@ -408,8 +404,8 @@ def pab(tmp):
     eaccsd_evals = np.atleast_1d(eaccsd_evals)
     for ea_eval, ea_evec, ea_levec in zip(eaccsd_evals, eaccsd_evecs, leaccsd_evecs):
         # Enforcing <L|R> = 1
-        l1, l2 = vector_to_amplitudes_ea(ea_levec, nmo, nocc)
-        r1, r2 = vector_to_amplitudes_ea(ea_evec, nmo, nocc)
+        l1, l2 = eom.vector_to_amplitudes(ea_levec, nmo, nocc)
+        r1, r2 = eom.vector_to_amplitudes(ea_evec, nmo, nocc)
         ldotr = np.dot(l1, r1) + 0.5 * np.dot(l2.ravel(), r2.ravel())

         logger.info(eom, 'Left-right amplitude overlap : %14.8e', ldotr)
@@ -460,13 +456,9 @@ class EOMEA(eom_rccsd.EOMEA):
     get_diag = eaccsd_diag
     ccsd_star_contract = eaccsd_star_contract

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_ea(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_ea(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_ea)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_ea,
+                                         absences=['nmo', 'nocc'])

     def vector_size(self):
         nocc = self.nocc
@@ -500,7 +492,7 @@ def eeccsd_matvec(eom, vector, imds=None, diag=None):
     if imds is None: imds = eom.make_imds()
     nocc = eom.nocc
     nmo = eom.nmo
-    r1, r2 = vector_to_amplitudes_ee(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)

     # Eq. (9)
     Hr1  = lib.einsum('ae,ie->ia', imds.Fvv, r1)
@@ -529,7 +521,7 @@ def eeccsd_matvec(eom, vector, imds=None, diag=None):
     Hr2 += 0.5*lib.einsum('mnij,mnab->ijab', imds.Woooo, r2)
     Hr2 += 0.5*lib.einsum('abef,ijef->ijab', imds.Wvvvv, r2)

-    vector = amplitudes_to_vector_ee(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

 def eeccsd_diag(eom, imds=None):
@@ -564,7 +556,7 @@ def eeccsd_diag(eom, imds=None):
         for j in range(i):
             Hr2[i,j,:,:] += 0.5*(imds.Woooo[i,j,i,j]-imds.Woooo[j,i,i,j])

-    vector = amplitudes_to_vector_ee(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

@@ -596,13 +588,9 @@ def gen_matvec(self, imds=None, **kwargs):
         matvec = lambda xs: [self.matvec(x, imds) for x in xs]
         return matvec, diag

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_ee(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_ee(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_ee)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_ee,
+                                         absences=['nmo', 'nocc'])

     def vector_size(self):
         '''size of the vector based on spin-orbital basis'''
@@ -747,41 +735,3 @@ def make_ee(self):
         self.made_ee_imds = True
         logger.timer(self, 'EOM-CCSD EE intermediates', *cput0)
         return self
-
-def _cp(a):
-    return np.array(a, copy=False, order='C')
-
-if __name__ == '__main__':
-    from pyscf import scf
-    from pyscf import gto
-    from pyscf.cc import gccsd
-    mol = gto.Mole()
-    mol.atom = [
-        [8 , (0. , 0.     , 0.)],
-        [1 , (0. , -0.757 , 0.587)],
-        [1 , (0. , 0.757  , 0.587)]]
-    mol.basis = 'cc-pvdz'
-    mol.spin = 0
-    mol.build()
-    mf = scf.UHF(mol).run()
-    mf = scf.addons.convert_to_ghf(mf)
-
-    mycc = gccsd.GCCSD(mf)
-    ecc, t1, t2 = mycc.kernel()
-    print(ecc - -0.2133432712431435)
-    e,v = mycc.ipccsd(nroots=8)
-    print(e[0] - 0.4335604332073799)
-    print(e[2] - 0.5187659896045407)
-    print(e[4] - 0.6782876002229172)
-
-    #mycc.verbose = 5
-    e,v = mycc.eaccsd(nroots=8)
-    print(e[0] - 0.16737886338859731)
-    print(e[2] - 0.24027613852009164)
-    print(e[4] - 0.51006797826488071)
-
-    e,v = mycc.eeccsd(nroots=4)
-    print(e[0] - 0.2757159395886167)
-    print(e[1] - 0.2757159395886167)
-    print(e[2] - 0.2757159395886167)
-    print(e[3] - 0.3005716731825082)
diff --git a/pyscf/cc/eom_rccsd.py b/pyscf/cc/eom_rccsd.py
index 7a2467dd1a..b0cb3f2c1f 100644
--- a/pyscf/cc/eom_rccsd.py
+++ b/pyscf/cc/eom_rccsd.py
@@ -23,7 +23,7 @@

 from pyscf import lib
 from pyscf import ao2mo
-from pyscf.lib import logger
+from pyscf.lib import logger, module_method
 from pyscf.cc import ccsd
 from pyscf.cc import rintermediates as imd
 from pyscf import __config__
@@ -274,12 +274,22 @@ def amplitudes_to_vector_ip(r1, r2):
     vector = np.hstack((r1, r2.ravel()))
     return vector

+def spatial2spin_ip(rx, orbspin=None):
+    from pyscf.cc import eom_uccsd
+    if rx.ndim == 1:
+        r1 = (rx, np.zeros_like(rx))
+        return eom_uccsd.spatial2spin_ip(r1, orbspin)
+    else:
+        rx0 = np.zeros_like(rx)
+        r2 = (rx.transpose(1,0,2)-rx, rx0, -rx, rx0)
+        return eom_uccsd.spatial2spin_ip(r2, orbspin)
+
 def ipccsd_matvec(eom, vector, imds=None, diag=None):
     # Ref: Nooijen and Snijders, J. Chem. Phys. 102, 1681 (1995) Eqs.(8)-(9)
     if imds is None: imds = eom.make_imds()
     nocc = eom.nocc
     nmo = eom.nmo
-    r1, r2 = vector_to_amplitudes_ip(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)

     # 1h-1h block
     Hr1 = -np.einsum('ki,k->i', imds.Loo, r1)
@@ -300,7 +310,7 @@ def ipccsd_matvec(eom, vector, imds=None, diag=None):
         Hr2 += -lib.einsum('ki,kjb->ijb', foo, r2)
         Hr2 += -lib.einsum('lj,ilb->ijb', foo, r2)
     elif eom.partition == 'full':
-        diag_matrix2 = vector_to_amplitudes_ip(diag, nmo, nocc)[1]
+        diag_matrix2 = eom.vector_to_amplitudes(diag, nmo, nocc)[1]
         Hr2 += diag_matrix2 * r2
     else:
         Hr2 += lib.einsum('bd,ijd->ijb', imds.Lvv, r2)
@@ -315,7 +325,7 @@ def ipccsd_matvec(eom, vector, imds=None, diag=None):
         tmp += -np.einsum('kldc,kld->c', imds.Woovv, r2)
         Hr2 += -np.einsum('c,ijcb->ijb', tmp, imds.t2)

-    vector = amplitudes_to_vector_ip(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

 def lipccsd_matvec(eom, vector, imds=None, diag=None):
@@ -327,7 +337,7 @@ def lipccsd_matvec(eom, vector, imds=None, diag=None):
     if imds is None: imds = eom.make_imds()
     nocc = eom.nocc
     nmo = eom.nmo
-    r1, r2 = vector_to_amplitudes_ip(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)

     # 1h-1h block
     Hr1 = -np.einsum('ki,i->k', imds.Loo, r1)
@@ -347,7 +357,7 @@ def lipccsd_matvec(eom, vector, imds=None, diag=None):
         Hr2 += -lib.einsum('ki,ild->kld', foo, r2)
         Hr2 += -lib.einsum('lj,kjd->kld', foo, r2)
     elif eom.partition == 'full':
-        diag_matrix2 = vector_to_amplitudes_ip(diag, nmo, nocc)[1]
+        diag_matrix2 = eom.vector_to_amplitudes(diag, nmo, nocc)[1]
         Hr2 += diag_matrix2 * r2
     else:
         Hr2 += lib.einsum('bd,klb->kld', imds.Lvv, r2)
@@ -360,7 +370,7 @@ def lipccsd_matvec(eom, vector, imds=None, diag=None):
         tmp = np.einsum('ijcb,ijb->c', imds.t2, r2)
         Hr2 += -np.einsum('lkdc,c->kld', 2.*imds.Woovv-imds.Woovv.transpose(1,0,2,3), tmp)

-    vector = amplitudes_to_vector_ip(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

 def ipccsd_diag(eom, imds=None):
@@ -393,7 +403,7 @@ def ipccsd_diag(eom, imds=None):
                     Hr2[i,j,b] += -2*np.dot(imds.Woovv[j,i,b,:], t2[i,j,:,b])
                     Hr2[i,j,b] += np.dot(imds.Woovv[i,j,b,:], t2[i,j,:,b])

-    vector = amplitudes_to_vector_ip(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

 def ipccsd_star_contract(eom, ipccsd_evals, ipccsd_evecs, lipccsd_evecs, imds=None):
@@ -555,13 +565,10 @@ def gen_matvec(self, imds=None, left=False, **kwargs):
             matvec = lambda xs: [self.matvec(x, imds, diag) for x in xs]
         return matvec, diag

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_ip(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_ip(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_ip)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_ip,
+                                         absences=['nmo', 'nocc'])
+    spatial2spin = staticmethod(spatial2spin_ip)

     def vector_size(self):
         nocc = self.nocc
@@ -619,13 +626,23 @@ def amplitudes_to_vector_ea(r1, r2):
     vector = np.hstack((r1, r2.ravel()))
     return vector

+def spatial2spin_ea(rx, orbspin=None):
+    from pyscf.cc import eom_uccsd
+    if rx.ndim == 1:
+        r1 = (rx, np.zeros_like(rx))
+        return eom_uccsd.spatial2spin_ea(r1, orbspin)
+    else:
+        rx0 = np.zeros_like(rx)
+        r2 = (rx-rx.transpose(0,2,1), rx0, rx, rx0)
+        return eom_uccsd.spatial2spin_ea(r2, orbspin)
+
 def eaccsd_matvec(eom, vector, imds=None, diag=None):
     # Ref: Nooijen and Bartlett, J. Chem. Phys. 102, 3629 (1995) Eqs.(30)-(31)
     if imds is None: imds = eom.make_imds()
     nocc = eom.nocc
     nmo = eom.nmo
     nvir = nmo - nocc
-    r1, r2 = vector_to_amplitudes_ea(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)

     # Eq. (37)
     # 1p-1p block
@@ -646,7 +663,7 @@ def eaccsd_matvec(eom, vector, imds=None, diag=None):
         Hr2 +=  lib.einsum('bd,jad->jab', fvv, r2)
         Hr2 += -lib.einsum('lj,lab->jab', foo, r2)
     elif eom.partition == 'full':
-        diag_matrix2 = vector_to_amplitudes_ea(diag, nmo, nocc)[1]
+        diag_matrix2 = eom.vector_to_amplitudes(diag, nmo, nocc)[1]
         Hr2 += diag_matrix2 * r2
     else:
         Hr2 +=  lib.einsum('ac,jcb->jab', imds.Lvv, r2)
@@ -660,7 +677,7 @@ def eaccsd_matvec(eom, vector, imds=None, diag=None):
         tmp = np.einsum('klcd,lcd->k', 2.*imds.Woovv-imds.Woovv.transpose(0,1,3,2), r2)
         Hr2 += -np.einsum('k,kjab->jab', tmp, imds.t2)

-    vector = amplitudes_to_vector_ea(Hr1,Hr2)
+    vector = eom.amplitudes_to_vector(Hr1,Hr2)
     return vector

 def leaccsd_matvec(eom, vector, imds=None, diag=None):
@@ -672,7 +689,7 @@ def leaccsd_matvec(eom, vector, imds=None, diag=None):
     nocc = eom.nocc
     nmo = eom.nmo
     nvir = nmo - nocc
-    r1, r2 = vector_to_amplitudes_ea(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)

     # Eq. (30)
     # 1p-1p block
@@ -693,7 +710,7 @@ def leaccsd_matvec(eom, vector, imds=None, diag=None):
         Hr2 += lib.einsum('lcb,bd->lcd', r2, fvv)
         Hr2 += -lib.einsum('jcd,lj->lcd', r2, foo)
     elif eom.partition == 'full':
-        diag_matrix2 = vector_to_amplitudes_ea(diag, nmo, nocc)[1]
+        diag_matrix2 = eom.vector_to_amplitudes(diag, nmo, nocc)[1]
         Hr2 += diag_matrix2 * r2
     else:
         Hr2 += lib.einsum('lad,ac->lcd', r2, imds.Lvv)
@@ -707,7 +724,7 @@ def leaccsd_matvec(eom, vector, imds=None, diag=None):
         tmp = np.einsum('ijcb,ibc->j', imds.t2, r2)
         Hr2 += -np.einsum('kjfe,j->kef', 2.*imds.Woovv-imds.Woovv.transpose(0,1,3,2),tmp)

-    vector = amplitudes_to_vector_ea(Hr1,Hr2)
+    vector = eom.amplitudes_to_vector(Hr1,Hr2)
     return vector

 def eaccsd_diag(eom, imds=None):
@@ -743,7 +760,7 @@ def eaccsd_diag(eom, imds=None):
                     Hr2[j,a,b] += -2*np.dot(imds.Woovv[:,j,a,b], t2[:,j,a,b])
                     Hr2[j,a,b] += np.dot(imds.Woovv[:,j,b,a], t2[:,j,a,b])

-    vector = amplitudes_to_vector_ea(Hr1,Hr2)
+    vector = eom.amplitudes_to_vector(Hr1,Hr2)
     return vector

 def eaccsd_star_contract(eom, eaccsd_evals, eaccsd_evecs, leaccsd_evecs, imds=None):
@@ -914,13 +931,10 @@ def gen_matvec(self, imds=None, left=False, **kwargs):
             matvec = lambda xs: [self.matvec(x, imds, diag) for x in xs]
         return matvec, diag

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_ea(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_ea(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_ea)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_ea,
+                                         absences=['nmo', 'nocc'])
+    spatial2spin = staticmethod(spatial2spin_ea)

     def vector_size(self):
         nocc = self.nocc
@@ -1068,6 +1082,18 @@ def eomsf_ccsd(eom, nroots=1, koopmans=False, guess=None,
 vector_to_amplitudes_ee = vector_to_amplitudes_singlet = ccsd.vector_to_amplitudes
 amplitudes_to_vector_ee = amplitudes_to_vector_singlet = ccsd.amplitudes_to_vector

+def spatial2spin_singlet(rx, orbspin=None):
+    from pyscf.cc import eom_uccsd
+    if rx.ndim == 2:
+        r1a = rx * .5**.5
+        r1 = (r1a, r1a)
+        return eom_uccsd.spatial2spin_eomee(r1, orbspin)
+    else:
+        r2ab = rx * .5**.5
+        r2aa = r2ab - r2ab.transpose(1,0,2,3)
+        r2 = (r2aa, r2ab, r2aa)
+        return eom_uccsd.spatial2spin_eomee(r2, orbspin)
+
 def amplitudes_to_vector_eomsf(t1, t2, out=None):
     nocc, nvir = t1.shape
     t2baaa, t2aaba = t2
@@ -1102,6 +1128,16 @@ def vector_to_amplitudes_eomsf(vector, nmo, nocc):
     t2aaba = t2aaba.reshape(nocc,nocc,nvir,nvir)
     return t1, (t2baaa, t2aaba)

+def spatial2spin_eomsf(rx, orbspin=None):
+    from pyscf.cc import eom_uccsd
+    if isinstance(rx, np.ndarray) and rx.ndim == 2:
+        r1 = (rx, np.zeros_like(rx))
+        return eom_uccsd.spatial2spin_eomsf(r1, orbspin)
+    else:
+        rx0 = np.zeros_like(rx[0])
+        r2 = (rx0, rx[1], rx[0], rx0)
+        return eom_uccsd.spatial2spin_eomsf(r2, orbspin)
+
 def amplitudes_to_vector_triplet(t1, t2, out=None):
     t2aa, t2ab = t2
     dtype = np.result_type(t1, t2aa, t2ab)
@@ -1125,13 +1161,26 @@ def vector_to_amplitudes_triplet(vector, nmo, nocc):
     t2ab = t2ab.reshape(nocc,nvir,nocc,nvir).transpose(0,2,1,3).copy()
     return t1, (t2aa, t2ab)

+def spatial2spin_triplet(rx, orbspin=None):
+    from pyscf.cc import eom_uccsd
+    if isinstance(rx, np.ndarray) and rx.ndim == 2:
+        r1a = rx * .5**.5
+        r1 = (r1a, r1a)
+        return eom_uccsd.spatial2spin_eomee(r1, orbspin)
+    else:
+        r2ab = rx * .5**.5
+        r2aa, r2ab = rx
+        r2aa = r2ab - r2ab.transpose(1,0,2,3)
+        r2 = (r2aa, r2ab, -r2aa)
+        return eom_uccsd.spatial2spin_eomee(r2, orbspin)
+
 def eeccsd_matvec_singlet(eom, vector, imds=None):
     if imds is None: imds = eom.make_imds()
     nocc = eom.nocc
     nmo = eom.nmo
     nvir = nmo - nocc

-    r1, r2 = vector_to_amplitudes_singlet(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)
     t1, t2, eris = imds.t1, imds.t2, imds.eris
     nocc, nvir = t1.shape

@@ -1219,7 +1268,7 @@ def eeccsd_matvec_singlet(eom, vector, imds=None):
     tau = tmp = eris_ovov = None

     Hr2 = Hr2 + Hr2.transpose(1,0,3,2)
-    vector = amplitudes_to_vector_ee(Hr1, Hr2)
+    vector = eom.amplitudes_to_vector(Hr1, Hr2)
     return vector

 def eeccsd_matvec_triplet(eom, vector, imds=None):
@@ -1228,7 +1277,7 @@ def eeccsd_matvec_triplet(eom, vector, imds=None):
     nmo = eom.nmo
     nvir = nmo - nocc

-    r1, r2 = vector_to_amplitudes_triplet(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)
     r2aa, r2ab = r2
     t1, t2, eris = imds.t1, imds.t2, imds.eris
     nocc, nvir = t1.shape
@@ -1287,10 +1336,11 @@ def eeccsd_matvec_triplet(eom, vector, imds=None):
     Hr2ab += lib.einsum('MBEJ,iMEa->iJaB', woVVo, r2aa)
     Hr2ab += lib.einsum('MbeJ,iMeA->iJbA', woVVo, r2ab)

-    woVVo = woVVo + np.asarray(imds.woVvO)
+    woVvO = np.asarray(imds.woVvO)
+    wovvo = woVVo + woVvO
     theta = r2aa + r2ab
-    tmp = lib.einsum('mbej,imae->ijab', woVVo, theta)
-    woVVo = None
+    tmp = lib.einsum('mbej,imae->ijab', wovvo, theta)
+    woVVo = woVvO = wovvo = None

     woOoV = np.asarray(imds.woOoV)
     Hr1 -= lib.einsum('mnie,mnae->ia', woOoV, theta)
@@ -1344,7 +1394,7 @@ def eeccsd_matvec_triplet(eom, vector, imds=None):
     Hr2aa = Hr2aa - Hr2aa.transpose(0,1,3,2)
     Hr2aa = Hr2aa - Hr2aa.transpose(1,0,2,3)
     Hr2ab = Hr2ab - Hr2ab.transpose(1,0,3,2)
-    vector = amplitudes_to_vector_triplet(Hr1, (Hr2aa,Hr2ab))
+    vector = eom.amplitudes_to_vector(Hr1, (Hr2aa,Hr2ab))
     return vector

 def eeccsd_matvec_sf(eom, vector, imds=None):
@@ -1355,7 +1405,7 @@ def eeccsd_matvec_sf(eom, vector, imds=None):
     nvir = nmo - nocc

     t1, t2, eris = imds.t1, imds.t2, imds.eris
-    r1, r2 = vector_to_amplitudes_eomsf(vector, nmo, nocc)
+    r1, r2 = eom.vector_to_amplitudes(vector, nmo, nocc)
     r2baaa, r2aaba = r2
     nocc, nvir = t1.shape

@@ -1493,7 +1543,7 @@ def eeccsd_matvec_sf(eom, vector, imds=None):

     Hr2baaa = Hr2baaa - Hr2baaa.transpose(0,1,3,2)
     Hr2aaba = Hr2aaba - Hr2aaba.transpose(1,0,2,3)
-    vector = amplitudes_to_vector_eomsf(Hr1, (Hr2baaa,Hr2aaba))
+    vector = eom.amplitudes_to_vector(Hr1, (Hr2baaa,Hr2aaba))
     return vector

 def eeccsd_diag(eom, imds=None):
@@ -1655,13 +1705,10 @@ def gen_matvec(self, imds=None, diag=None, **kwargs):
         matvec = lambda xs: [self.matvec(x, imds) for x in xs]
         return matvec, diag

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_singlet(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_singlet(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_singlet)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_singlet,
+                                         absences=['nmo', 'nocc'])
+    spatial2spin = staticmethod(spatial2spin_singlet)

     def vector_size(self):
         nocc = self.nocc
@@ -1681,13 +1728,10 @@ def gen_matvec(self, imds=None, diag=None, **kwargs):
         matvec = lambda xs: [self.matvec(x, imds) for x in xs]
         return matvec, diag

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_triplet(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_triplet(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_triplet)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_triplet,
+                                         absences=['nmo', 'nocc'])
+    spatial2spin = staticmethod(spatial2spin_triplet)

     def vector_size(self):
         nocc = self.nocc
@@ -1707,13 +1751,10 @@ def gen_matvec(self, imds=None, diag=None, **kwargs):
         matvec = lambda xs: [self.matvec(x, imds) for x in xs]
         return matvec, diag

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_eomsf(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_eomsf(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_eomsf)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_eomsf,
+                                         absences=['nmo', 'nocc'])
+    spatial2spin = staticmethod(spatial2spin_eomsf)

     def vector_size(self):
         nocc = self.nocc
@@ -1934,6 +1975,7 @@ def make_ee(self):
             self.woVvO[p0:p1] = woVvO
             self.woVVo[p0:p1] = woVVo

+        self.Fov += fov
         self.Foo += foo + 0.5*np.einsum('me,ie->mi', self.Fov+fov, t1)
         self.Fvv += fvv - 0.5*np.einsum('me,ma->ae', self.Fov+fov, t1)

@@ -2041,157 +2083,3 @@ def _make_tau(t2, t1, r1, fac=1, out=None):
     tau *= fac * .5
     tau += t2
     return tau
-
-def _cp(a):
-    return np.array(a, copy=False, order='C')
-
-
-if __name__ == '__main__':
-    from pyscf import scf
-    from pyscf import gto
-    from pyscf.cc import rccsd
-
-    mol = gto.Mole()
-    mol.atom = [
-        [8 , (0. , 0.     , 0.)],
-        [1 , (0. , -0.757 , 0.587)],
-        [1 , (0. , 0.757  , 0.587)]]
-    mol.basis = 'cc-pvdz'
-    mol.verbose = 0
-    mol.spin = 0
-    mol.build()
-    mf = scf.RHF(mol).run(conv_tol=1e-14)
-
-    mycc = rccsd.RCCSD(mf)
-    ecc, t1, t2 = mycc.kernel()
-    print(ecc - -0.21334326214236796)
-
-    myeom = EOMIP(mycc)
-    print("IP energies... (right eigenvector)")
-    e,v = ipccsd(myeom, nroots=3)
-    print(e[0] - 0.43356041409195489)
-    print(e[1] - 0.51876598058509493)
-    print(e[2] - 0.6782879569941862 )
-
-    print("IP energies... (left eigenvector)")
-    le,lv = ipccsd(myeom, nroots=3,left=True)
-    print(le[0] - 0.43356040428879794)
-    print(le[1] - 0.51876597800180335)
-    print(le[2] - 0.67828755013874864)
-
-    e = myeom.ipccsd_star_contract(e, v, lv)
-    print(e[0] - 0.43793202073189047)
-    print(e[1] - 0.52287073446559729)
-    print(e[2] - 0.67994597948852287)
-
-    myeom = EOMEA(mycc)
-    print("EA energies... (right eigenvector)")
-    e,v = eaccsd(myeom, nroots=3)
-    print(e[0] - 0.16737886282063008)
-    print(e[1] - 0.24027622989542635)
-    print(e[2] - 0.51006796667905585)
-
-    print("EA energies... (left eigenvector)")
-    le,lv = eaccsd(myeom, nroots=3, left=True)
-    print(le[0] - 0.16737896537079733)
-    print(le[1] - 0.24027634198123343)
-    print(le[2] - 0.51006809015066612)
-
-    e = myeom.eaccsd_star_contract(e,v,lv)
-    print(e[0] - 0.16656250953550664)
-    print(e[1] - 0.23944144521387614)
-    print(e[2] - 0.41399436888830721)
-
-    myeom = EOMEESpinFlip(mycc)
-    np.random.seed(1)
-    v = np.random.random(myeom.vector_size())
-    r1, r2 = vector_to_amplitudes_eomsf(v, myeom.nmo, myeom.nocc)
-    print(lib.finger(r1)    - 0.017703197938757409)
-    print(lib.finger(r2[0]) --21.605764517401415)
-    print(lib.finger(r2[1]) - 6.5857056438834842)
-    print(abs(amplitudes_to_vector_eomsf(r1, r2) - v).max())
-
-    myeom = EOMEE(mycc)
-    e,v = myeom.eeccsd(nroots=1)
-    print(e - 0.2757159395886167)
-
-    e,v = myeom.eeccsd(nroots=4)
-    print(e[0] - 0.2757159395886167)
-    print(e[1] - 0.2757159395886167)
-    print(e[2] - 0.2757159395886167)
-    print(e[3] - 0.3005716731825082)
-
-    e,v = myeom.eeccsd(nroots=4, koopmans=True)
-    print(e[0] - 0.2757159395886167)
-    print(e[1] - 0.2757159395886167)
-    print(e[2] - 0.2757159395886167)
-    print(e[3] - 0.3005716731825082)
-
-    e,v = myeom.eeccsd(nroots=4, guess=v[:4])
-    print(e[0] - 0.2757159395886167)
-    print(e[1] - 0.2757159395886167)
-    print(e[2] - 0.2757159395886167)
-    print(e[3] - 0.3005716731825082)
-
-
-    mycc = ccsd.CCSD(mf)
-    ecc, t1, t2 = mycc.kernel()
-    print(ecc - -0.21334326214236796)
-
-    myeom = EOMIP(mycc)
-    print("IP energies... (right eigenvector)")
-    e,v = ipccsd(myeom, nroots=3)
-    print(e[0] - 0.43356041409195489)
-    print(e[1] - 0.51876598058509493)
-    print(e[2] - 0.6782879569941862 )
-
-    print("IP energies... (left eigenvector)")
-    le,lv = ipccsd(myeom, nroots=3,left=True)
-    print(le[0] - 0.43356040428879794)
-    print(le[1] - 0.51876597800180335)
-    print(le[2] - 0.67828755013874864)
-
-    e = myeom.ipccsd_star_contract(e, v, lv)
-    print(e[0] - 0.43793202073189047)
-    print(e[1] - 0.52287073446559729)
-    print(e[2] - 0.67994597948852287)
-
-    myeom = EOMEA(mycc)
-    print("EA energies... (right eigenvector)")
-    e,v = eaccsd(myeom, nroots=3)
-    print(e[0] - 0.16737886282063008)
-    print(e[1] - 0.24027622989542635)
-    print(e[2] - 0.51006796667905585)
-
-    print("EA energies... (left eigenvector)")
-    le,lv = eaccsd(myeom, nroots=3, left=True)
-    print(le[0] - 0.16737896537079733)
-    print(le[1] - 0.24027634198123343)
-    print(le[2] - 0.51006809015066612)
-
-    e = myeom.eaccsd_star_contract(e,v,lv)
-    print(e[0] - 0.16656250953550664)
-    print(e[1] - 0.23944144521387614)
-    print(e[2] - 0.41399436888830721)
-
-    myeom = EOMEE(mycc)
-    e,v = myeom.eeccsd(nroots=1)
-    print(e - 0.2757159395886167)
-
-    e,v = myeom.eeccsd(nroots=4)
-    print(e[0] - 0.2757159395886167)
-    print(e[1] - 0.2757159395886167)
-    print(e[2] - 0.2757159395886167)
-    print(e[3] - 0.3005716731825082)
-
-    e,v = myeom.eeccsd(nroots=4, koopmans=True)
-    print(e[0] - 0.2757159395886167)
-    print(e[1] - 0.2757159395886167)
-    print(e[2] - 0.2757159395886167)
-    print(e[3] - 0.3005716731825082)
-
-    e,v = myeom.eeccsd(nroots=4, guess=v[:4])
-    print(e[0] - 0.2757159395886167)
-    print(e[1] - 0.2757159395886167)
-    print(e[2] - 0.2757159395886167)
-    print(e[3] - 0.3005716731825082)
diff --git a/pyscf/cc/eom_uccsd.py b/pyscf/cc/eom_uccsd.py
index d2870749a2..46ccde6491 100644
--- a/pyscf/cc/eom_uccsd.py
+++ b/pyscf/cc/eom_uccsd.py
@@ -25,10 +25,11 @@
 import numpy as np

 from pyscf import lib
-from pyscf.lib import logger
+from pyscf.lib import logger, module_method
 from pyscf import ao2mo
 from pyscf.cc import ccsd
 from pyscf.cc import uccsd
+from pyscf.cc import addons
 from pyscf.cc import eom_rccsd
 from pyscf.cc import uintermediates

@@ -75,16 +76,30 @@ def amplitudes_to_vector_ip(r1, r2):
                       r2aaa[idxa].ravel(), r2baa.ravel(),
                       r2abb.ravel(), r2bbb[idxb].ravel()))

-def spatial2spin_ip(r1, r2, orbspin=None):
-    '''Convert R1/R2 of spatial orbital representation to R1/R2 of
-    spin-orbital representation
-    '''
-    r1a, r1b = r1
-    r2aaa, r2baa, r2abb, r2bbb = r2
+def spatial2spin_ip(rx, orbspin=None):
+    '''Convert EOMIP spatial-orbital R1/R2 to spin-orbital R1/R2'''
+    if len(rx) == 2:  # r1
+        r1a, r1b = rx
+        nocc_a = r1a.size
+        nocc_b = r1b.size
+        nocc = nocc_a + nocc_b
+
+        r1 = np.zeros(nocc, dtype=r1a.dtype)
+        if orbspin is None:
+            assert nocc_a == nocc_b
+            r1[0::2] = r1a
+            r1[1::2] = r1b
+        else:
+            r1[orbspin[:nocc] == 0] = r1a
+            r1[orbspin[:nocc] == 1] = r1b
+        return r1
+
+    r2aaa, r2baa, r2abb, r2bbb = rx
     nocc_a, nvir_a = r2aaa.shape[1:]
     nocc_b, nvir_b = r2bbb.shape[1:]

     if orbspin is None:
+        assert nocc_a == nocc_b
         orbspin = np.zeros((nocc_a+nvir_a)*2, dtype=int)
         orbspin[1::2] = 1

@@ -95,10 +110,6 @@ def spatial2spin_ip(r1, r2, orbspin=None):
     idxva = np.where(orbspin[nocc:] == 0)[0]
     idxvb = np.where(orbspin[nocc:] == 1)[0]

-    r1 = np.zeros((nocc), dtype=r1a.dtype)
-    r1[idxoa] = r1a
-    r1[idxob] = r1b
-
     r2 = np.zeros((nocc**2, nvir), dtype=r2aaa.dtype)
     idxoaa = idxoa[:,None] * nocc + idxoa
     idxoab = idxoa[:,None] * nocc + idxob
@@ -120,10 +131,17 @@ def spatial2spin_ip(r1, r2, orbspin=None):
     r2bab = -r2abb
     lib.takebak_2d(r2, r2aba, idxoab.T.ravel(), idxva.ravel())
     lib.takebak_2d(r2, r2bab, idxoba.T.ravel(), idxvb.ravel())
-    return r1, r2.reshape(nocc, nocc, nvir)
+    return r2.reshape(nocc, nocc, nvir)

-def spin2spatial_ip(r1, r2, orbspin):
-    nocc, nvir = r2.shape[1:]
+def spin2spatial_ip(rx, orbspin):
+    '''Convert EOMIP spin-orbital R1/R2 to spatial-orbital R1/R2'''
+    if rx.ndim == 1:
+        nocc = rx.size
+        r1a = rx[orbspin[:nocc] == 0]
+        r1b = rx[orbspin[:nocc] == 1]
+        return r1a, r1b
+
+    nocc, nvir = rx.shape[1:]

     idxoa = np.where(orbspin[:nocc] == 0)[0]
     idxob = np.where(orbspin[:nocc] == 1)[0]
@@ -134,9 +152,6 @@ def spin2spatial_ip(r1, r2, orbspin):
     nvir_a = len(idxva)
     nvir_b = len(idxvb)

-    r1a = r1[idxoa]
-    r1b = r1[idxob]
-
     idxoaa = idxoa[:,None] * nocc + idxoa
     idxoab = idxoa[:,None] * nocc + idxob
     idxoba = idxob[:,None] * nocc + idxoa
@@ -146,7 +161,7 @@ def spin2spatial_ip(r1, r2, orbspin):
     #idxvba = idxvb[:,None] * nvir + idxva
     #idxvbb = idxvb[:,None] * nvir + idxvb

-    r2 = r2.reshape(nocc**2, nvir)
+    r2 = rx.reshape(nocc**2, nvir)
     r2aaa = lib.take_2d(r2, idxoaa.ravel(), idxva.ravel())
     r2baa = lib.take_2d(r2, idxoba.ravel(), idxva.ravel())
     r2abb = lib.take_2d(r2, idxoab.ravel(), idxvb.ravel())
@@ -156,7 +171,7 @@ def spin2spatial_ip(r1, r2, orbspin):
     r2baa = r2baa.reshape(nocc_b, nocc_a, nvir_a)
     r2abb = r2abb.reshape(nocc_a, nocc_b, nvir_b)
     r2bbb = r2bbb.reshape(nocc_b, nocc_b, nvir_b)
-    return [r1a, r1b], [r2aaa, r2baa, r2abb, r2bbb]
+    return r2aaa, r2baa, r2abb, r2bbb

 def ipccsd_matvec(eom, vector, imds=None, diag=None):
     '''For spin orbitals
@@ -168,7 +183,7 @@ def ipccsd_matvec(eom, vector, imds=None, diag=None):
     t2aa, t2ab, t2bb = t2
     nocca, noccb, nvira, nvirb = t2ab.shape
     nmoa, nmob = nocca+nvira, noccb+nvirb
-    r1, r2 = vector_to_amplitudes_ip(vector, (nmoa,nmob), (nocca,noccb))
+    r1, r2 = eom.vector_to_amplitudes(vector, (nmoa,nmob), (nocca,noccb))
     r1a, r1b = r1
     r2aaa, r2baa, r2abb, r2bbb = r2

@@ -329,13 +344,11 @@ def get_init_guess(self, nroots=1, koopmans=True, diag=None):
             guess.append(g)
         return guess

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_ip(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_ip(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_ip)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_ip,
+                                         absences=['nmo', 'nocc'])
+    spatial2spin = staticmethod(spatial2spin_ip)
+    spin2spatial = staticmethod(spin2spatial_ip)

     def vector_size(self):
         '''size of the vector based on spin-orbital basis'''
@@ -393,16 +406,30 @@ def amplitudes_to_vector_ea(r1, r2):
                       r2aba.ravel(), r2bab.ravel(),
                       r2bbb[:,idxb[0],idxb[1]].ravel()))

-def spatial2spin_ea(r1, r2, orbspin=None):
-    '''Convert R1/R2 of spatial orbital representation to R1/R2 of
-    spin-orbital representation
-    '''
-    r1a, r1b = r1
-    r2aaa, r2aba, r2bab, r2bbb = r2
+def spatial2spin_ea(rx, orbspin=None):
+    '''Convert EOMEA spatial-orbital R1/R2 to spin-orbital R1/R2'''
+    if len(rx) == 2:  # r1
+        r1a, r1b = rx
+        nvir_a = r1a.size
+        nvir_b = r1b.size
+        nvir = nvir_a + nvir_b
+
+        r1 = np.zeros(nvir, dtype=r1a.dtype)
+        if orbspin is None:
+            assert nvir_a == nvir_b
+            r1[0::2] = r1a
+            r1[1::2] = r1b
+        else:
+            r1[orbspin[-nvir:] == 0] = r1a
+            r1[orbspin[-nvir:] == 1] = r1b
+        return r1
+
+    r2aaa, r2aba, r2bab, r2bbb = rx
     nocc_a, nvir_a = r2aaa.shape[:2]
     nocc_b, nvir_b = r2bbb.shape[:2]

     if orbspin is None:
+        assert nvir_a == nvir_b
         orbspin = np.zeros((nocc_a+nvir_a)*2, dtype=int)
         orbspin[1::2] = 1

@@ -413,10 +440,6 @@ def spatial2spin_ea(r1, r2, orbspin=None):
     idxva = np.where(orbspin[nocc:] == 0)[0]
     idxvb = np.where(orbspin[nocc:] == 1)[0]

-    r1 = np.zeros((nvir), dtype=r1a.dtype)
-    r1[idxva] = r1a
-    r1[idxvb] = r1b
-
     r2 = np.zeros((nocc, nvir**2), dtype=r2aaa.dtype)
     #idxoaa = idxoa[:,None] * nocc + idxoa
     #idxoab = idxoa[:,None] * nocc + idxob
@@ -441,10 +464,17 @@ def spatial2spin_ea(r1, r2, orbspin=None):
     lib.takebak_2d(r2, r2bba, idxob.ravel(), idxvba.T.ravel())
     lib.takebak_2d(r2, r2aab, idxoa.ravel(), idxvab.T.ravel())
     r2 = r2.reshape(nocc, nvir, nvir)
-    return r1, r2
+    return r2

-def spin2spatial_ea(r1, r2, orbspin):
-    nocc, nvir = r2.shape[:2]
+def spin2spatial_ea(rx, orbspin):
+    '''Convert EOMEA spin-orbital R1/R2 to spatial-orbital R1/R2'''
+    if rx.ndim == 1:
+        nvir = rx.size
+        r1a = rx[orbspin[-nvir:] == 0]
+        r1b = rx[orbspin[-nvir:] == 1]
+        return r1a, r1b
+
+    nocc, nvir = rx.shape[:2]

     idxoa = np.where(orbspin[:nocc] == 0)[0]
     idxob = np.where(orbspin[:nocc] == 1)[0]
@@ -455,19 +485,12 @@ def spin2spatial_ea(r1, r2, orbspin):
     nvir_a = len(idxva)
     nvir_b = len(idxvb)

-    r1a = r1[idxva]
-    r1b = r1[idxvb]
-
-    #idxoaa = idxoa[:,None] * nocc + idxoa
-    #idxoab = idxoa[:,None] * nocc + idxob
-    #idxoba = idxob[:,None] * nocc + idxoa
-    #idxobb = idxob[:,None] * nocc + idxob
     idxvaa = idxva[:,None] * nvir + idxva
     idxvab = idxva[:,None] * nvir + idxvb
     idxvba = idxvb[:,None] * nvir + idxva
     idxvbb = idxvb[:,None] * nvir + idxvb

-    r2 = r2.reshape(nocc, nvir**2)
+    r2 = rx.reshape(nocc, nvir**2)
     r2aaa = lib.take_2d(r2, idxoa.ravel(), idxvaa.ravel())
     r2aba = lib.take_2d(r2, idxoa.ravel(), idxvba.ravel())
     r2bab = lib.take_2d(r2, idxob.ravel(), idxvab.ravel())
@@ -477,7 +500,7 @@ def spin2spatial_ea(r1, r2, orbspin):
     r2aba = r2aba.reshape(nocc_a, nvir_b, nvir_a)
     r2bab = r2bab.reshape(nocc_b, nvir_a, nvir_b)
     r2bbb = r2bbb.reshape(nocc_b, nvir_b, nvir_b)
-    return [r1a, r1b], [r2aaa, r2aba, r2bab, r2bbb]
+    return r2aaa, r2aba, r2bab, r2bbb

 def eaccsd_matvec(eom, vector, imds=None, diag=None):
     '''For spin orbitals.
@@ -490,7 +513,7 @@ def eaccsd_matvec(eom, vector, imds=None, diag=None):
     t2aa, t2ab, t2bb = t2
     nocca, noccb, nvira, nvirb = t2ab.shape
     nmoa, nmob = nocca+nvira, noccb+nvirb
-    r1, r2 = vector_to_amplitudes_ea(vector, (nmoa,nmob), (nocca,noccb))
+    r1, r2 = eom.vector_to_amplitudes(vector, (nmoa,nmob), (nocca,noccb))
     r1a, r1b = r1
     r2aaa, r2aba, r2bab, r2bbb = r2

@@ -848,13 +871,11 @@ def get_init_guess(self, nroots=1, koopmans=True, diag=None):
             guess.append(g)
         return guess

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_ea(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_ea(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_ea)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_ea,
+                                         absences=['nmo', 'nocc'])
+    spatial2spin = staticmethod(spatial2spin_ea)
+    spin2spatial = staticmethod(spin2spatial_ea)

     def vector_size(self):
         '''size of the vector based on spin-orbital basis'''
@@ -982,8 +1003,8 @@ def eomsf_ccsd(eom, nroots=1, koopmans=False, guess=None,
     '''
     return eomee_ccsd(eom, nroots, koopmans, guess, eris, imds, diag)

-amplitudes_to_vector_ee = uccsd.amplitudes_to_vector
-vector_to_amplitudes_ee = uccsd.vector_to_amplitudes
+amplitudes_to_vector_ee = amplitudes_to_vector_eomee = uccsd.amplitudes_to_vector
+vector_to_amplitudes_ee = vector_to_amplitudes_eomee = uccsd.vector_to_amplitudes

 def amplitudes_to_vector_eomsf(t1, t2, out=None):
     t1ab, t1ba = t1
@@ -1049,8 +1070,11 @@ def vector_to_amplitudes_eomsf(vector, nmo, nocc):
     t2bbab = t2bbab.reshape(noccb,noccb,nvira,nvirb)
     return (t1ab,t1ba), (t2baaa, t2aaba, t2abbb, t2bbab)

-def spatial2spin_eomsf(rx, orbspin):
-    '''Convert EOM spatial R1,R2 to spin-orbital R1,R2'''
+spatial2spin_eomee = addons.spatial2spin
+spin2spatial_eomee = addons.spin2spatial
+
+def spatial2spin_eomsf(rx, orbspin=None):
+    '''Convert spin-flip EOMEE spatial-orbital R1/R2 to spin-orbital R1/R2'''
     if len(rx) == 2:  # r1
         r1ab, r1ba = rx
         nocca, nvirb = r1ab.shape
@@ -1062,6 +1086,11 @@ def spatial2spin_eomsf(rx, orbspin):

     nocc = nocca + noccb
     nvir = nvira + nvirb
+    if orbspin is None:
+        assert nocca == noccb
+        orbspin = np.zeros(nocc+nvir, dtype=int)
+        orbspin[1::2] = 1
+
     idxoa = np.where(orbspin[:nocc] == 0)[0]
     idxob = np.where(orbspin[:nocc] == 1)[0]
     idxva = np.where(orbspin[nocc:] == 0)[0]
@@ -1098,7 +1127,7 @@ def spatial2spin_eomsf(rx, orbspin):
         return r2.reshape(nocc,nocc,nvir,nvir)

 def spin2spatial_eomsf(rx, orbspin):
-    '''Convert EOM spin-orbital R1,R2 to spatial R1,R2'''
+    '''Convert EOMEE spin-orbital R1/R2 to spin-flip EOMEE spatial-orbital R1/R2'''
     if rx.ndim == 2:  # r1
         nocc, nvir = rx.shape
     else:
@@ -1148,7 +1177,7 @@ def eomee_ccsd_matvec(eom, vector, imds=None):
     t2aa, t2ab, t2bb = t2
     nocca, noccb, nvira, nvirb = t2ab.shape
     nmoa, nmob = nocca+nvira, noccb+nvirb
-    r1, r2 = vector_to_amplitudes_ee(vector, (nmoa,nmob), (nocca,noccb))
+    r1, r2 = eom.vector_to_amplitudes(vector, (nmoa,nmob), (nocca,noccb))
     r1a, r1b = r1
     r2aa, r2ab, r2bb = r2

@@ -1369,7 +1398,7 @@ def eomsf_ccsd_matvec(eom, vector, imds=None):
     t2aa, t2ab, t2bb = t2
     nocca, noccb, nvira, nvirb = t2ab.shape
     nmoa, nmob = nocca+nvira, noccb+nvirb
-    r1, r2 = vector_to_amplitudes_eomsf(vector, (nmoa,nmob), (nocca,noccb))
+    r1, r2 = eom.vector_to_amplitudes(vector, (nmoa,nmob), (nocca,noccb))
     r1ab, r1ba = r1
     r2baaa, r2aaba, r2abbb, r2bbab = r2

@@ -1853,13 +1882,11 @@ def gen_matvec(self, imds=None, diag=None, **kwargs):
         matvec = lambda xs: [self.matvec(x, imds) for x in xs]
         return matvec, diag

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_ee(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_ee(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_ee)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_ee,
+                                         absences=['nmo', 'nocc'])
+    spatial2spin = staticmethod(spatial2spin_eomee)
+    spin2spatial = staticmethod(spin2spatial_eomee)

     def vector_size(self):
         '''size of the vector based on spin-orbital basis'''
@@ -1901,13 +1928,11 @@ def gen_matvec(self, imds=None, diag=None, **kwargs):
         matvec = lambda xs: [self.matvec(x, imds) for x in xs]
         return matvec, diag

-    def vector_to_amplitudes(self, vector, nmo=None, nocc=None):
-        if nmo is None: nmo = self.nmo
-        if nocc is None: nocc = self.nocc
-        return vector_to_amplitudes_eomsf(vector, nmo, nocc)
-
-    def amplitudes_to_vector(self, r1, r2):
-        return amplitudes_to_vector_eomsf(r1, r2)
+    amplitudes_to_vector = staticmethod(amplitudes_to_vector_eomsf)
+    vector_to_amplitudes = module_method(vector_to_amplitudes_eomsf,
+                                         absences=['nmo', 'nocc'])
+    spatial2spin = staticmethod(spatial2spin_eomsf)
+    spin2spatial = staticmethod(spin2spatial_eomsf)

     def vector_size(self):
         '''size of the vector based on spin-orbital basis'''
@@ -2604,229 +2629,3 @@ def make_ee(self):

         self.made_ee_imds = True
         log.timer('EOM-UCCSD EE intermediates', *cput0)
-
-def rand_mf(mol, seed=1):
-    from pyscf import scf
-    from pyscf import gto
-    from pyscf import lo
-    mol = gto.Mole()
-    mol.atom = [
-        [8 , (0. , 0.     , 0.)],
-        [1 , (0. , -0.757 , 0.587)],
-        [1 , (0. , 0.757  , 0.587)]]
-    mol.basis = 'sto-3g'
-    mol.verbose = 0
-    mol.spin = 0
-    mol.build()
-
-    np.random.seed(seed)
-
-    mf = scf.UHF(mol).run(conv_tol=1e-14)
-    nmo = mol.nao_nr()
-    mf.mo_occ = np.zeros((2,nmo))
-    mf.mo_occ[0,:4] = 1
-    mf.mo_occ[1,:2] = 1
-    mf.mo_energy = np.arange(nmo) + np.random.random((2,nmo)) * .3
-    mf.mo_energy[mf.mo_occ == 0] += 2
-
-    mo = np.random.random((2,nmo,nmo))
-    s = mf.get_ovlp()
-    mf.mo_coeff = np.empty_like(mo)
-    mf.mo_coeff[0] = lo.orth.vec_lowdin(mo[0], s)
-    mf.mo_coeff[1] = lo.orth.vec_lowdin(mo[1], s)
-    return mf
-
-def rand_cc_t1_t2(mf, seed=1):
-    from pyscf import ao2mo
-    from pyscf.cc import uccsd
-    mycc = uccsd.UCCSD(mf)
-
-    nocca, noccb = mycc.nocc
-    nmoa, nmob = mycc.nmo
-    nvira, nvirb = nmoa - nocca, nmob - noccb
-    def my_ao2mo(mo):
-        eris = ao2mo.kernel(mycc._scf._eri, mo, compact=False)
-        eris = ao2mo.restore(1, eris, mf.mol.nao_nr())
-
-        eris = eris + np.cos(eris)*1j
-        eris = eris + eris.transpose(1, 0, 3, 2)
-        eris = eris + eris.conj().transpose(2, 3, 0, 1)
-        return eris
-    eris = uccsd._make_eris_incore(mycc)#, ao2mofn=my_ao2mo)
-
-    np.random.seed(seed)
-    t1a = (np.random.random((nocca,nvira)) +
-           np.random.random((nocca,nvira))*1j - .5 - .5j)
-    t1b = (np.random.random((noccb,nvirb)) +
-           np.random.random((noccb,nvirb))*1j - .5 - .5j)
-    t2aa = (np.random.random((nocca,nocca,nvira,nvira)) +
-            np.random.random((nocca,nocca,nvira,nvira))*1j - .5 - .5j)
-    t2aa = t2aa - t2aa.transpose(1, 0, 2, 3)
-    t2aa = t2aa - t2aa.transpose(0, 1, 3, 2)
-
-    t2ab = (np.random.random((nocca,noccb,nvira,nvirb)) +
-            np.random.random((nocca,noccb,nvira,nvirb))*1j - .5 - .5j)
-
-    t2bb = (np.random.random((noccb,noccb,nvirb,nvirb)) +
-            np.random.random((noccb,noccb,nvirb,nvirb))*1j - .5 - .5j)
-    t2bb = t2bb - t2bb.transpose(1, 0, 2, 3)
-    t2bb = t2bb - t2bb.transpose(0, 1, 3, 2)
-
-    t1 = (t1a, t1b)
-    t2 = (t2aa, t2ab, t2bb)
-    return mycc, eris, t1, t2
-
-def enforce_symm_2p_spin(r1, r2, orbspin, excitation):
-    assert (excitation in ['ip', 'ea'])
-    if excitation == 'ip':
-        nocc, nvir = r2.shape[1:]
-    elif excitation == 'ea':
-        nocc, nvir = r2.shape[:2]
-    else:
-        raise NotImplementedError
-
-    idxoa = np.where(orbspin[:nocc] == 0)[0]
-    idxob = np.where(orbspin[:nocc] == 1)[0]
-    idxva = np.where(orbspin[nocc:] == 0)[0]
-    idxvb = np.where(orbspin[nocc:] == 1)[0]
-
-    idxoaa = idxoa[:,None] * nocc + idxoa
-    idxobb = idxob[:,None] * nocc + idxob
-    idxvaa = idxva[:,None] * nvir + idxva
-    idxvbb = idxvb[:,None] * nvir + idxvb
-
-    if excitation == 'ip':
-        r2 = r2 - r2.transpose(1, 0, 2)
-
-        r2 = r2.reshape(nocc**2, nvir)
-        r2[idxobb.ravel()[:, None], idxva.ravel()] = 0.0
-        r2[idxoaa.ravel()[:, None], idxvb.ravel()] = 0.0
-        r2 = r2.reshape(nocc, nocc, nvir)
-
-    if excitation == 'ea':
-        r2 = r2 - r2.transpose(0, 2, 1)
-
-        r2 = r2.reshape(nocc, nvir**2)
-        r2[idxoa.ravel(), idxvbb.ravel()[:, None]] = 0.0
-        r2[idxob.ravel(), idxvaa.ravel()[:, None]] = 0.0
-        r2 = r2.reshape(nocc, nvir, nvir)
-
-    return r1, r2
-
-def enforce_symm_2p_spin_ip(r1, r2, orbspin):
-    return enforce_symm_2p_spin(r1, r2, orbspin, 'ip')
-
-def enforce_symm_2p_spin_ea(r1, r2, orbspin):
-    return enforce_symm_2p_spin(r1, r2, orbspin, 'ea')
-
-if __name__ == '__main__':
-    from pyscf import gto
-    #from pyscf import scf
-    #from pyscf.cc import rccsd
-
-    mol = gto.Mole()
-    mol.atom = [
-        [8 , (0. , 0.     , 0.)],
-        [1 , (0. , -0.757 , 0.587)],
-        [1 , (0. , 0.757  , 0.587)]]
-    mol.basis = 'sto-3g'
-    mol.verbose = 0
-    mol.spin = 0
-    mol.build()
-
-    mf = rand_mf(mol)
-    mycc, eris, t1, t2 = rand_cc_t1_t2(mf)
-    mycc.t1 = t1
-    mycc.t2 = t2
-
-    nocca, noccb = mycc.nocc
-    nmoa, nmob = mycc.nmo
-    nvira, nvirb = nmoa - nocca, nmob - noccb
-    nocc = nocca + noccb
-    nvir = nvira + nvirb
-    nmo = nocc + nvir
-
-    def my_ao2mo(mo):
-        nao, nmo = mo.shape
-        orbspin = mo.orbspin
-
-#        eris = ao2mo.kernel(mygcc._scf._eri, mo_a + mo_b)
-#        sym_forbid = (orbspin[:,None] != orbspin)[np.tril_indices(nmo)]
-#        eris[sym_forbid,:] = 0
-#        eris[:,sym_forbid] = 0
-#        eris = ao2mo.restore(1, eris, nao)
-#        return eris
-        eris =(np.random.random((nmo,nmo,nmo,nmo)) +
-               np.random.random((nmo,nmo,nmo,nmo)) * 1j)
-
-        eris = eris + np.cos(eris)*1j
-        eris = eris + eris.transpose(1, 0, 3, 2)
-        eris = eris + eris.conj().transpose(2, 3, 0, 1)
-        eris[orbspin[:,None] != orbspin] = 0
-        eris[:,:,orbspin[:,None] != orbspin] = 0
-        return eris
-
-    import pyscf.cc.addons
-    from pyscf.cc import gccsd
-    mygcc = pyscf.cc.addons.convert_to_gccsd(mycc)
-    mygcc._ucc = mycc
-    mygcc._ucc_eris = eris
-    eris = gccsd._make_eris_incore(mygcc)#, ao2mofn=my_ao2mo)
-    orbspin = eris.orbspin
-
-    ## EOM-IP
-    myeom = EOMIP(mycc)
-    imds = myeom.make_imds()
-
-    np.random.seed(1)
-    r1 = np.random.rand(nocc)*1j + np.random.rand(nocc) - 0.5 - 0.5*1j
-    r2 = np.random.rand(nocc**2 * nvir)*1j + np.random.rand(nocc**2 * nvir) - 0.5 - 0.5*1j
-    r2 = r2.reshape(nocc, nocc, nvir)
-    r1, r2 = enforce_symm_2p_spin_ip(r1, r2, orbspin)
-    r1, r2 = spin2spatial_ip(r1, r2, orbspin)
-
-    vector = myeom.amplitudes_to_vector(r1, r2)
-    r1x, r2x = myeom.vector_to_amplitudes(vector)
-    print(abs(r1[0]-r1x[0]).max() < 1e-13 and
-          abs(r1[1]-r1x[1]).max() < 1e-13 and
-          abs(r2[0]-r2x[0]).max() < 1e-13 and
-          abs(r2[1]-r2x[1]).max() < 1e-13 and
-          abs(r2[2]-r2x[2]).max() < 1e-13 and
-          abs(r2[3]-r2x[3]).max() < 1e-13)
-    Hvector = myeom.matvec(vector, imds=imds)
-    print('ip', lib.finger(Hvector) - (21.67127462317093-19.068987454261908j))
-    print('diag', lib.finger(myeom.get_diag()) - (-9.6676217223549763+9.325219825942975j))
-
-    # EOM-EA
-    myeom = EOMEA(mycc)
-    imds = myeom.make_imds()
-
-    np.random.seed(1)
-    r1 = np.random.rand(nvir)*1j + np.random.rand(nvir) - 0.5 - 0.5*1j
-    r2 = np.random.rand(nocc * nvir**2)*1j + np.random.rand(nocc * nvir**2) - 0.5 - 0.5*1j
-    r2 = r2.reshape(nocc, nvir, nvir)
-    r1, r2 = enforce_symm_2p_spin_ea(r1, r2, orbspin)
-    r1, r2 = spin2spatial_ea(r1, r2, orbspin)
-
-    vector = myeom.amplitudes_to_vector(r1, r2)
-    r1x, r2x = myeom.vector_to_amplitudes(vector)
-    print(abs(r1[0]-r1x[0]).max() < 1e-13 and
-          abs(r1[1]-r1x[1]).max() < 1e-13 and
-          abs(r2[0]-r2x[0]).max() < 1e-13 and
-          abs(r2[1]-r2x[1]).max() < 1e-13 and
-          abs(r2[2]-r2x[2]).max() < 1e-13 and
-          abs(r2[3]-r2x[3]).max() < 1e-13)
-    Hvector = myeom.matvec(vector, imds=imds)
-    print('ea', lib.finger(Hvector) - (6.5543877287461187-13.175055314063574j))
-    print('diag', lib.finger(myeom.get_diag()) - (-57.353207240857785+1.4052857730841204j))
-
-    mycc = uccsd.UCCSD(mol.UHF().run())
-    ecc, t1, t2 = mycc.kernel()
-    print(ecc - -0.04946750711013597)
-    e,v = mycc.ipccsd(nroots=6)
-    print(e[0] - 0.3092874511803249)
-    print(e[1] - 0.3092874511803249)
-    print(e[2] - 0.4011171373779585)
-    print(e[3] - 0.4011171373779585)
-    print(e[4] - 0.6107409208314764)
-    print(e[5] - 0.6107409208314764)
diff --git a/pyscf/cc/gintermediates.py b/pyscf/cc/gintermediates.py
index a40e022f51..55cf7ec972 100644
--- a/pyscf/cc/gintermediates.py
+++ b/pyscf/cc/gintermediates.py
@@ -166,9 +166,6 @@ def Wvvvo(t1, t2, eris, _Wvvvv=None):
 # T3[2] related contributions to T1/T2
 ########################################

-def _cp(a):
-    return np.array(a, copy=False, order='C')
-
 def get_t3p2_imds_slow(cc, t1, t2, eris=None, t3p2_ip_out=None, t3p2_ea_out=None):
     """Calculates T1, T2 amplitudes corrected by second-order T3 contribution
     and intermediates used in IP/EA-CCSD(T)a
@@ -214,12 +211,12 @@ def get_t3p2_imds_slow(cc, t1, t2, eris=None, t3p2_ip_out=None, t3p2_ea_out=None
     mo_e_o = eris.mo_energy[:nocc]
     mo_e_v = eris.mo_energy[nocc:]

-    oovv = _cp(eris.oovv)
-    ovvv = _cp(eris.ovvv)
-    ooov = _cp(eris.ooov)
-    oovv = _cp(eris.oovv)
-    vooo = _cp(ooov).conj().transpose(3, 2, 1, 0)
-    vvvo = _cp(ovvv).conj().transpose(3, 2, 1, 0)
+    oovv = np.asarray(eris.oovv)
+    ovvv = np.asarray(eris.ovvv)
+    ooov = np.asarray(eris.ooov)
+    oovv = np.asarray(eris.oovv)
+    vooo = np.asarray(ooov).conj().transpose(3, 2, 1, 0)
+    vvvo = np.asarray(ovvv).conj().transpose(3, 2, 1, 0)

     ccsd_energy = cc.energy(t1, t2, eris)
     dtype = np.result_type(t1, t2)
diff --git a/pyscf/cc/rintermediates.py b/pyscf/cc/rintermediates.py
index 718ffb0cf1..ebdb4d7460 100644
--- a/pyscf/cc/rintermediates.py
+++ b/pyscf/cc/rintermediates.py
@@ -236,9 +236,6 @@ def _get_vvvv(eris):
     else:
         return eris.vvvv

-def _cp(a):
-    return np.array(a, copy=False, order='C')
-
 def get_t3p2_imds_slow(cc, t1, t2, eris=None, t3p2_ip_out=None, t3p2_ea_out=None):
     """Calculates T1, T2 amplitudes corrected by second-order T3 contribution
     and intermediates used in IP/EA-CCSD(T)a
@@ -261,8 +258,8 @@ def get_t3p2_imds_slow(cc, t1, t2, eris=None, t3p2_ip_out=None, t3p2_ea_out=None
     mo_e_o = eris.mo_energy[:nocc]
     mo_e_v = eris.mo_energy[nocc:]

-    ovov = _cp(eris.ovov)
-    ovvv = _cp(eris.get_ovvv())
+    ovov = np.asarray(eris.ovov)
+    ovvv = np.asarray(eris.get_ovvv())
     eris_vvov = eris.get_ovvv().conj().transpose(1,3,0,2)  # Physicist notation
     eris_vooo = eris.ovoo[:].conj().transpose(1,0,3,2)  # Chemist notation

diff --git a/pyscf/cc/test/test_dfccsd.py b/pyscf/cc/test/test_dfccsd.py
index fac0b39431..f1aa92486d 100644
--- a/pyscf/cc/test/test_dfccsd.py
+++ b/pyscf/cc/test/test_dfccsd.py
@@ -201,8 +201,8 @@ def test_df_eomee_ccsd_matvec_singlet(self):
         imds = myeom.make_imds(eris1)
         vec1 = myeom.matvec(vec, imds)
         r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1), -11001.96269563921, 7)
-        self.assertAlmostEqual(lib.fp(r2), 10145.408880409095, 7)
+        self.assertAlmostEqual(lib.fp(r1), -29298.85295742222, 7)
+        self.assertAlmostEqual(lib.fp(r2), 10145.543907318603, 7)

     def test_df_eomee_ccsd_matvec_triplet(self):
         numpy.random.seed(10)
@@ -216,9 +216,9 @@ def test_df_eomee_ccsd_matvec_triplet(self):
         imds = myeom.make_imds(eris1)
         vec1 = myeom.matvec(vec, imds)
         r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1   ), 214.90035498814302, 9)
-        self.assertAlmostEqual(lib.fp(r2[0]), 37033.183886562998, 7)
-        self.assertAlmostEqual(lib.fp(r2[1]), 4164.1657912277242, 7)
+        self.assertAlmostEqual(lib.fp(r1   ), -6923.975705203359, 8)
+        self.assertAlmostEqual(lib.fp(r2[0]), 37033.47500554715 , 7)
+        self.assertAlmostEqual(lib.fp(r2[1]), 4164.221159944544, 7)

     def test_df_eomsf_ccsd_matvec(self):
         numpy.random.seed(10)
@@ -229,15 +229,15 @@ def test_df_eomsf_ccsd_matvec(self):
         imds = myeom.make_imds(eris1)
         vec1 = myeom.matvec(vec, imds)
         r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1   ), 1929.9270950777639, 8)
-        self.assertAlmostEqual(lib.fp(r2[0]), 15571.714806853948, 7)
-        self.assertAlmostEqual(lib.fp(r2[1]),-12949.619613624538, 7)
+        self.assertAlmostEqual(lib.fp(r1   ), 133.93692998558186, 8)
+        self.assertAlmostEqual(lib.fp(r2[0]), 15572.228624905263, 7)
+        self.assertAlmostEqual(lib.fp(r2[1]),-12949.86945323115 , 7)

     def test_df_eomee_diag(self):
         vec1S, vec1T, vec2 = eom_rccsd.EOMEE(mycc1).get_diag()
-        self.assertAlmostEqual(lib.fp(vec1S), 213.16715890265095, 9)
-        self.assertAlmostEqual(lib.fp(vec1T),-857.23800705535234, 9)
-        self.assertAlmostEqual(lib.fp(vec2) , 14.360296355284504, 9)
+        self.assertAlmostEqual(lib.fp(vec1S), 213.17116636400607, 9)
+        self.assertAlmostEqual(lib.fp(vec1T),-857.2458742624522 , 9)
+        self.assertAlmostEqual(lib.fp(vec2) , 14.357453812621733, 9)

     def test_ao2mo(self):
         numpy.random.seed(2)
diff --git a/pyscf/cc/test/test_eom_rccsd.py b/pyscf/cc/test/test_eom_rccsd.py
index c417e4f28d..b1210ac7b3 100644
--- a/pyscf/cc/test/test_eom_rccsd.py
+++ b/pyscf/cc/test/test_eom_rccsd.py
@@ -277,11 +277,21 @@ def test_eomee_ccsd_matvec_singlet(self):
         r2 = r2 + r2.transpose(1,0,3,2)
         myeom = eom_rccsd.EOMEESinglet(mycc1)
         vec = myeom.amplitudes_to_vector(r1,r2)
-        imds = myeom.make_imds(eris1)
-        vec1 = myeom.matvec(vec, imds)
-        r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1), -112883.3791497977, 7)
-        self.assertAlmostEqual(lib.fp(r2), -268199.3475813322, 7)
+        vec1 = myeom.matvec(vec)
+        v1, v2 = myeom.vector_to_amplitudes(vec1)
+        self.assertAlmostEqual(lib.fp(v1), -145152.78511963107, 7)
+        self.assertAlmostEqual(lib.fp(v2), -268196.0471308574, 7)
+
+        gcc1 = cc.addons.convert_to_gccsd(mycc1)
+        gee1 = gcc1.EOMEE()
+        orbspin = gcc1._scf.mo_coeff.orbspin
+        gr1 = myeom.spatial2spin(r1, orbspin)
+        gr2 = myeom.spatial2spin(r2, orbspin)
+        gvec = gee1.amplitudes_to_vector(gr1, gr2)
+        vecref = gee1.matvec(gvec)
+        gr1, gr2 = gee1.vector_to_amplitudes(vecref)
+        self.assertAlmostEqual(abs(gr1-myeom.spatial2spin(v1, orbspin)).max(), 0, 8)
+        self.assertAlmostEqual(abs(gr2-myeom.spatial2spin(v2, orbspin)).max(), 0, 8)

     def test_eomee_ccsd_matvec_triplet(self):
         numpy.random.seed(10)
@@ -294,10 +304,24 @@ def test_eomee_ccsd_matvec_triplet(self):
         vec = myeom.amplitudes_to_vector(r1, r2)
         imds = myeom.make_imds(eris1)
         vec1 = myeom.matvec(vec, imds)
-        r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1   ), 3550.5250670914056, 8)
-        self.assertAlmostEqual(lib.fp(r2[0]), -237433.03756895234,7)
-        self.assertAlmostEqual(lib.fp(r2[1]), 127680.0182437716 , 7)
+        v1, v2 = myeom.vector_to_amplitudes(vec1)
+        self.assertAlmostEqual(lib.fp(v1   ), -5616.12199728998, 8)
+        self.assertAlmostEqual(lib.fp(v2[0]), -237430.14342594685,7)
+        self.assertAlmostEqual(lib.fp(v2[1]), 127682.76151592708, 7)
+
+        gcc1 = cc.addons.convert_to_uccsd(mycc1)
+        gee1 = gcc1.EOMEESpinKeep()
+        gr1 = (r1*.5**.5, -r1*.5**.5)
+        raa = r2[0]*.5**.5
+        rx = r2[1]*.5**.5
+        gr2 = (raa, rx, -raa)
+        gvec = gee1.amplitudes_to_vector(gr1, gr2)
+        vecref = gee1.matvec(gvec)
+        gr1, gr2 = gee1.vector_to_amplitudes(vecref)
+        self.assertAlmostEqual(abs(gr1[0]*2**.5- v1).max(), 0, 9)
+        self.assertAlmostEqual(abs(gr2[0]*2**.5- v2[0]).max(), 0, 9)
+        self.assertAlmostEqual(abs(gr2[1]*2**.5- v2[1]).max(), 0, 9)
+        self.assertAlmostEqual(abs(-gr2[2]*2**.5- v2[0]).max(), 0, 9)

     def test_eomsf_ccsd_matvec(self):
         numpy.random.seed(10)
@@ -307,24 +331,56 @@ def test_eomsf_ccsd_matvec(self):
         vec = myeom.amplitudes_to_vector(r1,r2)
         imds = myeom.make_imds(eris1)
         vec1 = myeom.matvec(vec, imds)
-        r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1   ), -19368.729268465482, 8)
-        self.assertAlmostEqual(lib.fp(r2[0]), 84325.863680611626 , 7)
-        self.assertAlmostEqual(lib.fp(r2[1]), 6715.9574457836134 , 8)
+        v1, v2 = myeom.vector_to_amplitudes(vec1)
+
+        self.assertAlmostEqual(lib.fp(v1   ), -6213.095578988824, 7)
+        self.assertAlmostEqual(lib.fp(v2[0]), 84329.40539995288 , 7)
+        self.assertAlmostEqual(lib.fp(v2[1]), 6719.930458652292 , 7)
+
+        numpy.random.seed(10)
+        vec = numpy.random.random(myeom.vector_size()) - .9
+        r1, r2 = myeom.vector_to_amplitudes(vec)
+        vec1 = myeom.matvec(vec, imds)
+        v1, v2 = myeom.vector_to_amplitudes(vec1)
+
+        gcc1 = cc.addons.convert_to_gccsd(mycc1)
+        gee1 = gcc1.EOMEE()
+        orbspin = gcc1._scf.mo_coeff.orbspin
+        gr1 = myeom.spatial2spin(r1, orbspin)
+        gr2 = myeom.spatial2spin(r2, orbspin)
+        gvec = gee1.amplitudes_to_vector(gr1, gr2)
+        vecref = gee1.matvec(gvec)
+        gr1, gr2 = gee1.vector_to_amplitudes(vecref)
+        self.assertAlmostEqual(abs(gr1-myeom.spatial2spin(v1, orbspin)).max(), 0, 9)
+        self.assertAlmostEqual(abs(gr2-myeom.spatial2spin(v2, orbspin)).max(), 0, 9)

     def test_eomee_diag(self):
         vec1S, vec1T, vec2 = eom_rccsd.EOMEE(mycc1).get_diag()
-        self.assertAlmostEqual(lib.fp(vec1S),-4714.9854130015719, 8)
-        self.assertAlmostEqual(lib.fp(vec1T), 2221.3155272953709, 8)
-        self.assertAlmostEqual(lib.fp(vec2) ,-5486.1611871545592, 8)
+        self.assertAlmostEqual(lib.fp(vec1S), -4714.969920334639, 8)
+        self.assertAlmostEqual(lib.fp(vec1T),  2221.322839866705, 8)
+        self.assertAlmostEqual(lib.fp(vec2) , -5486.124838268124, 8)

     def test_ip_matvec(self):
         numpy.random.seed(12)
         r1 = numpy.random.random((no)) - .9
         r2 = numpy.random.random((no,no,nv)) - .9
-        myeom = eom_rccsd.EOMIP(mycc1)
+        myeom = mycc1.EOMIP()
         vec = myeom.amplitudes_to_vector(r1,r2)
         r1,r2 = myeom.vector_to_amplitudes(vec)
+
+        gcc1 = cc.addons.convert_to_gccsd(mycc1)
+        gee1 = gcc1.EOMIP()
+        orbspin = gcc1._scf.mo_coeff.orbspin
+        gr1 = myeom.spatial2spin(r1, orbspin)
+        gr2 = myeom.spatial2spin(r2, orbspin)
+        gvec = gee1.amplitudes_to_vector(gr1, gr2)
+        vecref = gee1.matvec(gvec)
+        gr1, gr2 = gee1.vector_to_amplitudes(vecref)
+        vec1 = myeom.matvec(vec)
+        v1, v2 = myeom.vector_to_amplitudes(vec1)
+        self.assertAlmostEqual(abs(gr1-myeom.spatial2spin(v1, orbspin)).max(), 0, 9)
+        self.assertAlmostEqual(abs(gr2-myeom.spatial2spin(v2, orbspin)).max(), 0, 9)
+
         myeom.partition = 'mp'
         self.assertAlmostEqual(lib.fp(r1), 0.37404344676857076, 11)
         self.assertAlmostEqual(lib.fp(r2), -1.1568913404570922, 11)
@@ -347,6 +403,20 @@ def test_ea_matvec(self):
         myeom = eom_rccsd.EOMEA(mycc1)
         vec = myeom.amplitudes_to_vector(r1,r2)
         r1,r2 = myeom.vector_to_amplitudes(vec)
+
+        gcc1 = cc.addons.convert_to_gccsd(mycc1)
+        gee1 = gcc1.EOMEA()
+        orbspin = gcc1._scf.mo_coeff.orbspin
+        gr1 = myeom.spatial2spin(r1, orbspin)
+        gr2 = myeom.spatial2spin(r2, orbspin)
+        gvec = gee1.amplitudes_to_vector(gr1, gr2)
+        vecref = gee1.matvec(gvec)
+        gr1, gr2 = gee1.vector_to_amplitudes(vecref)
+        vec1 = myeom.matvec(vec)
+        v1, v2 = myeom.vector_to_amplitudes(vec1)
+        self.assertAlmostEqual(abs(gr1-myeom.spatial2spin(v1, orbspin)).max(), 0, 9)
+        self.assertAlmostEqual(abs(gr2-myeom.spatial2spin(v2, orbspin)).max(), 0, 9)
+
         myeom.partition = 'mp'
         self.assertAlmostEqual(lib.fp(r1), 1.4488291275539353, 11)
         self.assertAlmostEqual(lib.fp(r2), 0.97080165032287469, 11)
@@ -506,8 +576,8 @@ def test_eomee_ccsd_matvec_singlet2(self):
         imds = myeom.make_imds(eris21)
         vec1 = myeom.matvec(vec, imds)
         r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1), -112883.3791497977, 7)
-        self.assertAlmostEqual(lib.fp(r2), -268199.3475813322, 7)
+        self.assertAlmostEqual(lib.fp(r1), -145152.7851196310, 7)
+        self.assertAlmostEqual(lib.fp(r2), -268196.0471308578, 7)

     def test_eomee_ccsd_matvec_triplet2(self):
         numpy.random.seed(10)
@@ -521,9 +591,9 @@ def test_eomee_ccsd_matvec_triplet2(self):
         imds = myeom.make_imds(eris21)
         vec1 = myeom.matvec(vec, imds)
         r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1   ), 3550.5250670914056, 8)
-        self.assertAlmostEqual(lib.fp(r2[0]), -237433.03756895234,7)
-        self.assertAlmostEqual(lib.fp(r2[1]), 127680.0182437716 , 7)
+        self.assertAlmostEqual(lib.fp(r1   ), -5616.12199728998, 8)
+        self.assertAlmostEqual(lib.fp(r2[0]), -237430.14342594685,7)
+        self.assertAlmostEqual(lib.fp(r2[1]), 127682.76151592708, 7)

     def test_eomsf_ccsd_matvec2(self):
         numpy.random.seed(10)
@@ -534,15 +604,15 @@ def test_eomsf_ccsd_matvec2(self):
         imds = myeom.make_imds(eris21)
         vec1 = myeom.matvec(vec, imds)
         r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1   ), -19368.729268465482, 7)
-        self.assertAlmostEqual(lib.fp(r2[0]), 84325.863680611626 , 7)
-        self.assertAlmostEqual(lib.fp(r2[1]), 6715.9574457836134 , 7)
+        self.assertAlmostEqual(lib.fp(r1   ), -6213.095578988824, 7)
+        self.assertAlmostEqual(lib.fp(r2[0]), 84329.40539995288 , 7)
+        self.assertAlmostEqual(lib.fp(r2[1]), 6719.930458652292 , 7)

     def test_eomee_diag2(self):
         vec1S, vec1T, vec2 = eom_rccsd.EOMEE(mycc21).get_diag()
-        self.assertAlmostEqual(lib.fp(vec1S),-4714.9854130015719, 8)
-        self.assertAlmostEqual(lib.fp(vec1T), 2221.3155272953709, 8)
-        self.assertAlmostEqual(lib.fp(vec2) ,-5486.1611871545592, 8)
+        self.assertAlmostEqual(lib.fp(vec1S), -4714.969920334639, 8)
+        self.assertAlmostEqual(lib.fp(vec1T),  2221.322839866705, 8)
+        self.assertAlmostEqual(lib.fp(vec2) , -5486.124838268124, 8)

     def test_ip_matvec2(self):
@@ -705,8 +775,8 @@ def test_eomee_ccsd_matvec_singlet3(self):
         imds = myeom.make_imds(eris31)
         vec1 = myeom.matvec(vec, imds)
         r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1), -112883.3791497977, 7)
-        self.assertAlmostEqual(lib.fp(r2), -268199.3475813322, 7)
+        self.assertAlmostEqual(lib.fp(r1), -145152.7851196310, 7)
+        self.assertAlmostEqual(lib.fp(r2), -268196.0471308578, 7)

     def test_eomee_ccsd_matvec_triplet3(self):
         numpy.random.seed(10)
@@ -720,9 +790,9 @@ def test_eomee_ccsd_matvec_triplet3(self):
         imds = myeom.make_imds(eris31)
         vec1 = myeom.matvec(vec, imds)
         r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1   ), 3550.5250670914056, 8)
-        self.assertAlmostEqual(lib.fp(r2[0]), -237433.03756895234,7)
-        self.assertAlmostEqual(lib.fp(r2[1]), 127680.0182437716 , 7)
+        self.assertAlmostEqual(lib.fp(r1   ), -5616.12199728998, 8)
+        self.assertAlmostEqual(lib.fp(r2[0]), -237430.14342594685,7)
+        self.assertAlmostEqual(lib.fp(r2[1]), 127682.76151592708, 7)

     def test_eomsf_ccsd_matvec3(self):
         numpy.random.seed(10)
@@ -733,15 +803,15 @@ def test_eomsf_ccsd_matvec3(self):
         imds = myeom.make_imds(eris31)
         vec1 = myeom.matvec(vec, imds)
         r1, r2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(lib.fp(r1   ), -19368.729268465482, 7)
-        self.assertAlmostEqual(lib.fp(r2[0]), 84325.863680611626 , 7)
-        self.assertAlmostEqual(lib.fp(r2[1]), 6715.9574457836134 , 7)
+        self.assertAlmostEqual(lib.fp(r1   ), -6213.095578988824, 7)
+        self.assertAlmostEqual(lib.fp(r2[0]), 84329.40539995288 , 7)
+        self.assertAlmostEqual(lib.fp(r2[1]), 6719.930458652292 , 7)

     def test_eomee_diag3(self):
         vec1S, vec1T, vec2 = eom_rccsd.EOMEE(mycc31).get_diag()
-        self.assertAlmostEqual(lib.fp(vec1S),-2881.6804563818432, 8)
-        self.assertAlmostEqual(lib.fp(vec1T), 2039.7385969969259, 8)
-        self.assertAlmostEqual(lib.fp(vec2) ,-4271.6230465236358, 8)
+        self.assertAlmostEqual(lib.fp(vec1S), -2881.664963714903, 8)
+        self.assertAlmostEqual(lib.fp(vec1T),  2039.745909568253, 8)
+        self.assertAlmostEqual(lib.fp(vec2) , -4271.586697637197, 8)

     def test_ip_matvec3(self):
diff --git a/pyscf/cc/test/test_eom_uccsd.py b/pyscf/cc/test/test_eom_uccsd.py
index 7ec38eadae..754eeb873e 100644
--- a/pyscf/cc/test/test_eom_uccsd.py
+++ b/pyscf/cc/test/test_eom_uccsd.py
@@ -16,6 +16,7 @@
 import copy
 import unittest
 import numpy
+import numpy as np
 from functools import reduce

 from pyscf import gto
@@ -29,8 +30,8 @@
 from pyscf.cc import eom_gccsd

 def setUpModule():
-    global mol, mf, mol1, mf0, mf1, gmf, ucc, ucc0, ucc1, eris1
-    global ecc, orbspin, nocca, noccb, nvira, nvirb, r1, r2
+    global mol, mf, mol1, mf0, mf1, gmf, ucc, ucc0, ucc1
+    global orbspin, nocca, noccb, nvira, nvirb, r1, r2
     mol = gto.Mole()
     mol.verbose = 0
     mol.atom = [
@@ -57,7 +58,6 @@ def setUpModule():
     orbspin = gmf.mo_coeff.orbspin

     ucc1 = cc.UCCSD(mf1)
-    eris1 = ucc1.ao2mo()

     numpy.random.seed(11)
     no = nocca + noccb
@@ -76,16 +76,17 @@ def setUpModule():
     ucc = cc.UCCSD(mf)
     ucc.max_space = 0
     ucc.conv_tol = 1e-8
-    ecc = ucc.kernel()[0]
+    ucc.kernel()[0]

     ucc0 = cc.UCCSD(mf0)
     ucc0.conv_tol = 1e-8
     ucc0.direct = True
     ucc0.kernel()

+
 def tearDownModule():
-    global mol, mf, mol1, mf0, mf1, gmf, ucc, ucc0, ucc1, eris1
-    del mol, mf, mol1, mf0, mf1, gmf, ucc, ucc0, ucc1, eris1
+    global mol, mf, mol1, mf0, mf1, gmf, ucc, ucc0, ucc1
+    del mol, mf, mol1, mf0, mf1, gmf, ucc, ucc0, ucc1

 class KnownValues(unittest.TestCase):
     def test_ipccsd(self):
@@ -130,7 +131,7 @@ def test_eaccsd_koopmans(self):

     def test_eomee(self):
-        self.assertAlmostEqual(ecc, -0.13539788719099638, 5)
+        self.assertAlmostEqual(ucc.e_corr, -0.13539788719099638, 5)
         eom = ucc.eomee_method()
         e,v = eom.kernel(nroots=1, koopmans=False)
         self.assertAlmostEqual(e, 0.28114509667240556, 5)
@@ -164,11 +165,13 @@ def test_eomsf_ccsd(self):

     def test_ucc_update_amps(self):
         gcc1 = gccsd.GCCSD(gmf)
+        orbspin = gcc1._scf.mo_coeff.orbspin
         r1g = gcc1.spatial2spin(ucc1.t1, orbspin)
         r2g = gcc1.spatial2spin(ucc1.t2, orbspin)
         r1g, r2g = gcc1.update_amps(r1g, r2g, gcc1.ao2mo())
         u1g = gcc1.spin2spatial(r1g, orbspin)
         u2g = gcc1.spin2spatial(r2g, orbspin)
+        eris1 = ucc1.ao2mo()
         t1, t2 = ucc1.update_amps(ucc1.t1, ucc1.t2, eris1)
         self.assertAlmostEqual(abs(u1g[0]-t1[0]).max(), 0, 7)
         self.assertAlmostEqual(abs(u1g[1]-t1[1]).max(), 0, 7)
@@ -199,29 +202,59 @@ def test_ucc_eomee_ccsd_matvec(self):
         gr1 = gcc1.spatial2spin(r1)
         gr2 = gcc1.spatial2spin(r2)
         gee1 = eom_gccsd.EOMEE(gcc1)
-        gvec = eom_gccsd.amplitudes_to_vector_ee(gr1, gr2)
-        vecref = eom_gccsd.eeccsd_matvec(gee1, gvec)
+        gvec = gee1.amplitudes_to_vector(gr1, gr2)
+        vecref = gee1.matvec(gvec)

-        vec = eom_uccsd.amplitudes_to_vector_ee(r1,r2)
         uee1 = eom_uccsd.EOMEESpinKeep(ucc1)
-        vec1 = eom_uccsd.eomee_ccsd_matvec(uee1, vec)
-
-        uv = eom_uccsd.amplitudes_to_vector_ee(r1, r2)
-        gv = eom_gccsd.amplitudes_to_vector_ee(gr1, gr2)
-        r1, r2 = uee1.vector_to_amplitudes(uee1.matvec(uv))
-        gr1, gr2 = gee1.vector_to_amplitudes(gee1.matvec(gv))
+        orbspin = gcc1._scf.mo_coeff.orbspin
+        r1 = uee1.spin2spatial(uee1.spatial2spin(r1, orbspin), orbspin)
+        r2 = uee1.spin2spatial(uee1.spatial2spin(r2, orbspin), orbspin)
+        vec = uee1.amplitudes_to_vector(r1,r2)
+        vec1 = uee1.matvec(vec)

         r1, r2 = uee1.vector_to_amplitudes(vec1)
         gr1, gr2 = gee1.vector_to_amplitudes(vecref)
-        self.assertAlmostEqual(float(abs(gr1-gcc1.spatial2spin(r1)).max()), 0, 9)
-        self.assertAlmostEqual(float(abs(gr2-gcc1.spatial2spin(r2)).max()), 0, 9)
+        self.assertAlmostEqual(float(abs(gr1-uee1.spatial2spin(r1, orbspin)).max()), 0, 9)
+        self.assertAlmostEqual(float(abs(gr2-uee1.spatial2spin(r2, orbspin)).max()), 0, 9)
+        self.assertAlmostEqual(lib.fp(vec1), 49.499911123484523, 9)
+
+        ucc2 = copy.copy(ucc1)
+        ucc2.direct = True
+        uee1 = eom_uccsd.EOMEESpinKeep(ucc2)
+        vec1 = uee1.matvec(vec)
         self.assertAlmostEqual(lib.fp(vec1), 49.499911123484523, 9)

-    def test_ucc_eomee_ccsd_diag(self):  # FIXME: compare to EOMEE-GCCSD diag
+    def test_ucc_eomee_ccsd_diag(self):
         vec1, vec2 = eom_uccsd.EOMEE(ucc1).get_diag()
         self.assertAlmostEqual(lib.fp(vec1), 62.767648620751018, 9)
         self.assertAlmostEqual(lib.fp(vec2), 156.2976365433517, 9)

+        gcc1 = cc.addons.convert_to_gccsd(ucc1)
+        gee1 = eom_gccsd.EOMEE(gcc1)
+        gvec = gee1.get_diag()
+        orbspin = gcc1._scf.mo_coeff.orbspin
+        gv1, gv2 = gee1.vector_to_amplitudes(gvec)
+
+        nmo = ucc1.nmo
+        nocc = ucc1.nocc
+        v1, v2 = eom_uccsd.vector_to_amplitudes_eomee(vec1, nmo, nocc)
+        r1 = eom_uccsd.spin2spatial_eomee(gv1, orbspin)
+        r2 = eom_uccsd.spin2spatial_eomee(gv2, orbspin)
+        self.assertAlmostEqual(abs(abs(v1[0])-abs(r1[0])).max(), 0, 9)
+        self.assertAlmostEqual(abs(abs(v1[1])-abs(r1[1])).max(), 0, 9)
+        self.assertAlmostEqual(abs(abs(v2[0])-abs(r2[0])).max(), 0, 9)
+        self.assertAlmostEqual(abs(abs(v2[1])-abs(r2[1])).max(), 0, 9)
+        self.assertAlmostEqual(abs(abs(v2[2])-abs(r2[2])).max(), 0, 9)
+
+        v1, v2 = eom_uccsd.vector_to_amplitudes_eomsf(vec2, nmo, nocc)
+        r1 = eom_uccsd.spin2spatial_eomsf(gv1, orbspin)
+        r2 = eom_uccsd.spin2spatial_eomsf(gv2, orbspin)
+        self.assertAlmostEqual(abs(abs(v1[0])-abs(r1[0])).max(), 0, 9)
+        self.assertAlmostEqual(abs(abs(v1[1])-abs(r1[1])).max(), 0, 9)
+        self.assertAlmostEqual(abs(abs(v2[0])-abs(r2[0])).max(), 0, 9)
+        self.assertAlmostEqual(abs(abs(v2[1])-abs(r2[1])).max(), 0, 9)
+        self.assertAlmostEqual(abs(abs(v2[2])-abs(r2[2])).max(), 0, 9)
+
     def test_ucc_eomee_init_guess(self):
         uee = eom_uccsd.EOMEESpinKeep(ucc1)
         diag = uee.get_diag()[0]
@@ -241,25 +274,88 @@ def test_ucc_eomsf_ccsd_matvec(self):
         numpy.random.seed(10)
         myeom = eom_uccsd.EOMEESpinFlip(ucc1)
         vec = numpy.random.random(myeom.vector_size()) - .9
-        vec1 = eom_uccsd.eomsf_ccsd_matvec(myeom, vec)
+        vec1 = myeom.matvec(vec)
+        self.assertAlmostEqual(lib.fp(vec1), -1655.5564756993756, 8)
+
+        gcc1 = cc.addons.convert_to_gccsd(ucc1)
+        gee1 = eom_gccsd.EOMEE(gcc1)
+        r1, r2 = myeom.vector_to_amplitudes(vec)
+        orbspin = gcc1._scf.mo_coeff.orbspin
+        r1 = myeom.spin2spatial(myeom.spatial2spin(r1, orbspin), orbspin)
+        r2 = myeom.spin2spatial(myeom.spatial2spin(r2, orbspin), orbspin)
+        gr1 = myeom.spatial2spin(r1, orbspin)
+        gr2 = myeom.spatial2spin(r2, orbspin)
+        gvec = gee1.amplitudes_to_vector(gr1, gr2)
+
+        vecref = gee1.matvec(gvec)
+        gr1, gr2 = gee1.vector_to_amplitudes(vecref)
+        v1, v2 = myeom.vector_to_amplitudes(vec1)
+        self.assertAlmostEqual(float(abs(gr1-myeom.spatial2spin(v1, orbspin)).max()), 0, 9)
+        self.assertAlmostEqual(float(abs(gr2-myeom.spatial2spin(v2, orbspin)).max()), 0, 9)
+
+        ucc2 = copy.copy(ucc1)
+        ucc2.direct = True
+        myeom = eom_uccsd.EOMEESpinFlip(ucc2)
+        vec1 = myeom.matvec(vec)
         self.assertAlmostEqual(lib.fp(vec1), -1655.5564756993756, 8)

+    def test_ucc_eomip_matvec(self):
+        numpy.random.seed(10)
+        myeom = eom_uccsd.EOMIP(ucc1)
+        vec = numpy.random.random(myeom.vector_size()) - .9
+        vec1 = myeom.matvec(vec)
+        self.assertAlmostEqual(lib.fp(vec1), -216.54704385639815, 8)
+
+        gcc1 = cc.addons.convert_to_gccsd(ucc1)
+        gee1 = eom_gccsd.EOMIP(gcc1)
         r1, r2 = myeom.vector_to_amplitudes(vec)
-        gr1 = eom_uccsd.spatial2spin_eomsf(r1, orbspin)
-        gr2 = eom_uccsd.spatial2spin_eomsf(r2, orbspin)
-        gvec = eom_gccsd.amplitudes_to_vector_ee(gr1, gr2)
+        orbspin = gcc1._scf.mo_coeff.orbspin
+        r1 = myeom.spin2spatial(myeom.spatial2spin(r1, orbspin), orbspin)
+        r2 = myeom.spin2spatial(myeom.spatial2spin(r2, orbspin), orbspin)
+        gr1 = myeom.spatial2spin(r1, orbspin)
+        gr2 = myeom.spatial2spin(r2, orbspin)
+        gvec = gee1.amplitudes_to_vector(gr1, gr2)
+
+        vecref = gee1.matvec(gvec)
+        gr1, gr2 = gee1.vector_to_amplitudes(vecref)
+        v1, v2 = myeom.vector_to_amplitudes(vec1)
+        self.assertAlmostEqual(float(abs(gr1-myeom.spatial2spin(v1, orbspin)).max()), 0, 9)
+        self.assertAlmostEqual(float(abs(gr2-myeom.spatial2spin(v2, orbspin)).max()), 0, 9)
+
+        ucc2 = copy.copy(ucc1)
+        ucc2.direct = True
+        myeom = eom_uccsd.EOMIP(ucc2)
+        vec1 = myeom.matvec(vec)
+        self.assertAlmostEqual(lib.fp(vec1), -216.54704385639815, 8)
+
+    def test_ucc_eomea_matvec(self):
+        numpy.random.seed(10)
+        myeom = eom_uccsd.EOMEA(ucc1)
+        vec = numpy.random.random(myeom.vector_size()) - .9
+        vec1 = myeom.matvec(vec)
+        self.assertAlmostEqual(lib.fp(vec1), -110.5193188685705, 8)

         gcc1 = cc.addons.convert_to_gccsd(ucc1)
-        gee1 = eom_gccsd.EOMEE(gcc1)
-        vecref = eom_gccsd.eeccsd_matvec(gee1, gvec)
+        gee1 = eom_gccsd.EOMEA(gcc1)
+        r1, r2 = myeom.vector_to_amplitudes(vec)
+        orbspin = gcc1._scf.mo_coeff.orbspin
+        r1 = myeom.spin2spatial(myeom.spatial2spin(r1, orbspin), orbspin)
+        r2 = myeom.spin2spatial(myeom.spatial2spin(r2, orbspin), orbspin)
+        gr1 = myeom.spatial2spin(r1, orbspin)
+        gr2 = myeom.spatial2spin(r2, orbspin)
+        gvec = gee1.amplitudes_to_vector(gr1, gr2)
+
+        vecref = gee1.matvec(gvec)
         gr1, gr2 = gee1.vector_to_amplitudes(vecref)
         v1, v2 = myeom.vector_to_amplitudes(vec1)
-        self.assertAlmostEqual(float(abs(gr1-eom_uccsd.spatial2spin_eomsf(v1, orbspin)).max()), 0, 9)
-        self.assertAlmostEqual(float(abs(gr2-eom_uccsd.spatial2spin_eomsf(v2, orbspin)).max()), 0, 9)
+        self.assertAlmostEqual(float(abs(gr1-myeom.spatial2spin(v1, orbspin)).max()), 0, 9)
+        self.assertAlmostEqual(float(abs(gr2-myeom.spatial2spin(v2, orbspin)).max()), 0, 9)

-#    def test_ucc_eomip_matvec(self):
-#
-#    def test_ucc_eomea_matvec(self):
+        ucc2 = copy.copy(ucc1)
+        ucc2.direct = True
+        myeom = eom_uccsd.EOMEA(ucc2)
+        vec1 = myeom.matvec(vec)
+        self.assertAlmostEqual(lib.fp(vec1), -110.5193188685705, 8)

 ########################################
 # With 4-fold symmetry in integrals
@@ -289,8 +385,8 @@ def test_spatial2spin_eomsf(self):
         size = eomsf.vector_size()
         v = numpy.random.random(size)
         r1, r2 = eomsf.vector_to_amplitudes(v)
-        v1 = eom_uccsd.spin2spatial_eomsf(eom_uccsd.spatial2spin_eomsf(r1, orbspin), orbspin)
-        v2 = eom_uccsd.spin2spatial_eomsf(eom_uccsd.spatial2spin_eomsf(r2, orbspin), orbspin)
+        v1 = eomsf.spin2spatial(eomsf.spatial2spin(r1, orbspin), orbspin)
+        v2 = eomsf.spin2spatial(eomsf.spatial2spin(r2, orbspin), orbspin)
         self.assertAlmostEqual(abs(r1[0]-v1[0]).max(), 0, 12)
         self.assertAlmostEqual(abs(r1[1]-v1[1]).max(), 0, 12)
         self.assertAlmostEqual(abs(r2[0]-v2[0]).max(), 0, 12)