Cannot deepcopy the Atoms object post calculation
Currently, it is not possible to deepcopy() the Atoms object after an xTB calculation with the ASE interface.
from copy import deepcopy
from xtb.ase.calculator import XTB
from ase.build import molecule
atoms = molecule("H2")
atoms.calc = XTB(method="GFN2-xTB")
atoms.get_potential_energy()
deepcopy(atoms)
Returns:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_3220/591948702.py in <module>
5 atoms.calc = XTB(method="GFN2-xTB")
6 atoms.get_potential_energy()
----> 7 deepcopy(atoms)
~/anaconda3/envs/xtb/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
170 y = x
171 else:
--> 172 y = _reconstruct(x, memo, *rv)
173
174 # If is its own copy, don't memoize.
~/anaconda3/envs/xtb/lib/python3.8/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
268 if state is not None:
269 if deep:
--> 270 state = deepcopy(state, memo)
271 if hasattr(y, '__setstate__'):
272 y.__setstate__(state)
~/anaconda3/envs/xtb/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
144 copier = _deepcopy_dispatch.get(cls)
145 if copier is not None:
--> 146 y = copier(x, memo)
147 else:
148 if issubclass(cls, type):
~/anaconda3/envs/xtb/lib/python3.8/copy.py in _deepcopy_dict(x, memo, deepcopy)
228 memo[id(x)] = y
229 for key, value in x.items():
--> 230 y[deepcopy(key, memo)] = deepcopy(value, memo)
231 return y
232 d[dict] = _deepcopy_dict
~/anaconda3/envs/xtb/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
170 y = x
171 else:
--> 172 y = _reconstruct(x, memo, *rv)
173
174 # If is its own copy, don't memoize.
~/anaconda3/envs/xtb/lib/python3.8/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
268 if state is not None:
269 if deep:
--> 270 state = deepcopy(state, memo)
271 if hasattr(y, '__setstate__'):
272 y.__setstate__(state)
~/anaconda3/envs/xtb/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
144 copier = _deepcopy_dispatch.get(cls)
145 if copier is not None:
--> 146 y = copier(x, memo)
147 else:
148 if issubclass(cls, type):
~/anaconda3/envs/xtb/lib/python3.8/copy.py in _deepcopy_dict(x, memo, deepcopy)
228 memo[id(x)] = y
229 for key, value in x.items():
--> 230 y[deepcopy(key, memo)] = deepcopy(value, memo)
231 return y
232 d[dict] = _deepcopy_dict
~/anaconda3/envs/xtb/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
170 y = x
171 else:
--> 172 y = _reconstruct(x, memo, *rv)
173
174 # If is its own copy, don't memoize.
~/anaconda3/envs/xtb/lib/python3.8/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
268 if state is not None:
269 if deep:
--> 270 state = deepcopy(state, memo)
271 if hasattr(y, '__setstate__'):
272 y.__setstate__(state)
~/anaconda3/envs/xtb/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
144 copier = _deepcopy_dispatch.get(cls)
145 if copier is not None:
--> 146 y = copier(x, memo)
147 else:
148 if issubclass(cls, type):
~/anaconda3/envs/xtb/lib/python3.8/copy.py in _deepcopy_dict(x, memo, deepcopy)
228 memo[id(x)] = y
229 for key, value in x.items():
--> 230 y[deepcopy(key, memo)] = deepcopy(value, memo)
231 return y
232 d[dict] = _deepcopy_dict
~/anaconda3/envs/xtb/lib/python3.8/copy.py in deepcopy(x, memo, _nil)
159 reductor = getattr(x, "__reduce_ex__", None)
160 if reductor is not None:
--> 161 rv = reductor(4)
162 else:
163 reductor = getattr(x, "__reduce__", None)
TypeError: cannot pickle '_cffi_backend.__CDataGCP' object
Indeed, the API in xtb does not implement a copy function which could be used to create a deepcopy of any API object at the moment. For the ASE Calculator case this wouldn't be an issue since the API objects are (re)created on demand.
Further, I'm not sure what the actual requirements are for implementing a deepcopy mechanism in Python, especially since the objects we want to copy are automatically generated by CFFI from the xtb.hinformation and only represent opaque handles (void*).
Got it, thanks for the info and prompt reply!