duartegroup / autodE

automated reaction profile generation
https://duartegroup.github.io/autodE/
MIT License
165 stars 51 forks source link

SVD did not converge: #143 (cont, supposedly fixed by #151) #261

Open eneas77 opened 1 year ago

eneas77 commented 1 year ago

Hi,

Resuming the reaction below discussed in #143 ,

im

it crashes with the following:

  File "/home/user/rxn.py", line 11, in <module>
    rxn.calculate_reaction_profile(free_energy=True)
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/utils.py", line 350, in wrapped_function
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/reactions/reaction.py", line 153, in calculate_reaction_profile
    calculate(self)
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/utils.py", line 154, in wrapped_function
    result = func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/reactions/reaction.py", line 142, in calculate
    reaction.optimise_reacs_prods()
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/utils.py", line 530, in wrapped_function
    result = func(reaction)
             ^^^^^^^^^^^^^^
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/utils.py", line 154, in wrapped_function
    result = func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/reactions/reaction.py", line 609, in optimise_reacs_prods
    mol.optimise(h_method)
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/utils.py", line 288, in wrapped_function
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/species/species.py", line 1211, in optimise
    calc.run()
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/calculations/calculation.py", line 116, in run
    self._executor.run()
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/calculations/executors.py", line 371, in run
    self.optimiser.run(
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/opt/optimisers/base.py", line 134, in run
    self._step()  # Update self._coords
    ^^^^^^^^^^^^
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/opt/optimisers/crfo.py", line 86, in _step
    c = self._take_step_within_trust_radius(delta_s[:n])
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/opt/optimisers/rfo.py", line 111, in _take_step_within_trust_radius
    new_coords = self._coords + factor * delta_s
                 ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/opt/coordinates/base.py", line 257, in __add__
    new_coords.iadd(other)
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/autode-1.3.5-py3.11-linux-x86_64.egg/autode/opt/coordinates/dic.py", line 225, in iadd
    self.B_T_inv = np.linalg.pinv(self.B)
                   ^^^^^^^^^^^^^^^^^^^^^^
  File "<__array_function__ internals>", line 200, in pinv
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/numpy/linalg/linalg.py", line 1983, in pinv
    u, s, vt = svd(a, full_matrices=False, hermitian=hermitian)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<__array_function__ internals>", line 200, in svd
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/numpy/linalg/linalg.py", line 1642, in svd
    u, s, vh = gufunc(a, signature=signature, extobj=extobj)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/apps/anaconda3/envs/autode_135/lib/python3.11/site-packages/numpy/linalg/linalg.py", line 98, in _raise_linalgerror_svd_nonconvergence
    raise LinAlgError("SVD did not converge")
numpy.linalg.LinAlgError: SVD did not converge

This is the .py script

import autode as ade
ade.Config.n_cores = 2
ade.Config.hcode = 'NWChem'
ade.Config.lcode = 'XTB'
ade.Config.max_core = 4000
r1 = ade.Reactant(smiles='ON=O')
r2 = ade.Reactant(smiles='ON=O')
p1 = ade.Product(smiles='[O-][N+](=O)N=O')
p2 = ade.Product(smiles='O')
rxn = ade.Reaction(r1, r2, p1, p2, name='rxn', solvent_name='toluene', temp=358.15)
rxn.calculate_reaction_profile(free_energy=True)
quit()

Any hints about what is happening? Did you try to run this example when you closed the enhancement on #151 ?

Thank you,

E77

eneas77 commented 1 year ago

Hi,

Any updates about this?

Thanks,

E77

t-young31 commented 1 year ago

Hope you don't mind but I edited the issue to make the error/code easier to read

Thanks for raising –this looks like an optimiser bug to me, probably present since v1.3.0 – I'll take a look. I'm hoping @shoubhikraj might have fixed it already in #262

t-young31 commented 1 year ago

I cant reproduce this error but there's definitely something bad going on – it shouldn't take 68 iterations to converge N2O3 & fail to run the internals->cartesians transform 😞

@shoubhikraj would you mind trying ade.Molecule(smiles='[O-][N+](=O)N=O').optimise(method=ade.methods.NWChem()) with the trim optimiser when you have the chance? thanks!

shoubhikraj commented 1 year ago

@t-young31 @eneas77

I do not have access to NWChem right now, but I can reproduce the error even with xTB and the new optimiser:

>>> import autode as ade
>>> mol = ade.Molecule(smiles='[O-][N+](=O)N=O')
>>> opt = ade.opt.optimisers.HybridTRMOptimiser(maxiter=100,gtol=1.e-3,etol=1.e-4)
>>> opt.run(mol, method=ade.methods.XTB())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "G:\autodE\autode\opt\optimisers\base.py", line 135, in run
    self._step()  # Update self._coords
  File "G:\autodE\autode\opt\optimisers\trm.py", line 174, in _step
    self._coords = self._coords + step  # finally, take the step!
  File "G:\autodE\autode\opt\coordinates\base.py", line 264, in __add__
    new_coords.iadd(other)
  File "G:\autodE\autode\opt\coordinates\dic.py", line 243, in iadd
    raise RuntimeError(
RuntimeError: Iterative back-transform did not converge
>>> mol.coordinates
Coordinates([[-1.38900795 -0.83276619  0.04883061]
 [-0.58297449  0.02862588 -0.01147048]
 [-0.67159798  1.20019831 -0.15331935]
 [ 0.90290826 -0.58392015  0.17367619]
 [ 1.74067215  0.18786215 -0.05771697]] Å)

The optimiser throws the error much earlier (~16 iterations) when the dic-> cartesian transform fails. I suspect the problem is coming from the nearly 180 degree dihedral angle. When I restart the optimisation (which rebuilds the internal coordinates) it works (I assume because the dihedrals are now excluded from the primitive set):

>>> opt = ade.opt.optimisers.HybridTRMOptimiser(maxiter=100,gtol=1.e-3,etol=1.e-4)
>>> opt.run(mol, method=ade.methods.XTB())
>>> mol.coordinates
Coordinates([[-1.44320967e+00 -8.13930256e-01  8.45857398e-02]
 [-5.93660808e-01 -5.68579976e-04 -1.19083114e-02]
 [-5.96507906e-01  1.17034244e+00 -1.76402679e-01]
 [ 9.38350317e-01 -6.14585625e-01  1.07541973e-01]
 [ 1.69502807e+00  2.58742025e-01 -3.81672248e-03]] Å)

If you look at the final optimised structure, the two O-N-N-O dihedral angles are 179.773 and -0.264 degrees: image

One way to solve this could be to modify the optimisers so that whenever the back-tranform fails to converge, it will rebuild internal coordinates or perhaps switch to Cartesians.

eneas77 commented 1 year ago

Hi,

Did you try to run this example when you closed the enhancement on #151 ? I suppose the answer, as there is no one, is you didn't run it.

Perhaps you should include that basic QC: every case ending in bug/enhancement should be tested once the fork job is done. :-)

Just my two shilings on this matter.

Thanks a lot.

E77