Hi, I am trying to do parallel NEB calculation with DFTB calculator. The following python file works without errors when the EMT calculator is used instead of DFTB. However, when DFTB is used the following error is shown: ValueError: One or more NEB images share the same calculator. Each image must have its own calculator. You may wish to use the ase.neb.SingleCalculatorNEB class instead, although using separate calculators is recommended.
neb.py file:
from ase.io import read
from ase.constraints import FixAtoms
from ase.calculators.emt import EMT
from ase.calculators.dftb import Dftb
from ase.neb import NEB
from ase.optimize import BFGS
from ase.parallel import world
initial = read('start.traj')
final = read('end.traj')
#constraint = FixAtoms(mask=[i > 15 for i in range(0,66)])
images = [initial]
j = world.rank * 3 // world.size # my image number
for i in range(3):
image = initial.copy()
if i == j:
#image.calc = EMT() <--- the error is not reported when EMT is used here
image.calc=Dftb(label='h2o',
atoms=images[i], kpts=(1,4,1),
Hamiltonian_SCC='yes',
Hamiltonian_SCCTolerance=1E-7,
Hamiltonian_MaxSCCIterations=300,
Hamiltonian_ForceEvaluation="'dynamics'",
Hamiltonian_Filling = 'Fermi {Temperature [Kelvin] = 100.0}',
Hamiltonian_MaxAngularMomentum_='',
Hamiltonian_MaxAngularMomentum_C='"p"',
Hamiltonian_MaxAngularMomentum_O='"p"',
Driver_='',
Driver_ConjugateGradient_='',
Driver_ConjugateGradient_MaxForceComponent = '1E-4',
Driver_ConjugateGradient_MaxSteps = '0',
Driver_ConjugateGradient_ConvergentForcesOnly = 'No'
)
print(image)
#image.set_constraint(constraint)
images.append(image)
images.append(final)
neb = NEB(images, parallel=True)
neb.interpolate()
qn = BFGS(neb, trajectory='neb.traj')
qn.run(fmax=0.05)
I run the calculation with mpirun -n 3 gpaw python neb.py
I got similar error when using vasp calculator. I fixed it by attaching new calculator in each images. Hopes it is useful for you. Here is my code:
from ase.calculators.vasp import Vasp
from ase.neb import NEB
from ase.io import read
from ase.optimize import BFGS
# Load initial and final structures
atoms = Vasp(restart=True, directory='nh3-initial').get_atoms()
atoms2 = Vasp(restart=True, directory='nh3-final').get_atoms()
# Create 5 images including endpoints
images = [atoms] # initial state
images += [atoms.copy() for i in range(3)]
images += [atoms2] # final state
# Set up NEB interpolation
neb = NEB(images)
neb.interpolate()
# Set up VASP calculator for NEB calculation
calc = Vasp(directory='molecules/nh3-neb',
xc='PBE',
ibrion=1, encut=350,
nsw=90,
spring=-5.0)
for image in images[1:4]:
image.calc = Vasp(
xc='PBE',
ibrion=1, encut=350,
nsw=90,
spring=-5.0)
# Run the NEB optimization
qn = BFGS(neb, trajectory='neb.traj', restart='neb.pckl')
qn.run(fmax=0.05)
if not self.allow_shared_calculator:
calculators = [image.calc for image in images
if image.calc is not None]
if len(set(calculators)) != len(calculators):
msg = ('One or more NEB images share the same calculator. '
'Each image must have its own calculator. '
'You may wish to use the ase.mep.SingleCalculatorNEB '
'class instead, although using separate calculators '
'is recommended.')
raise ValueError(msg)
Only if the calculators are different objects, len(set(calculators)) == len(calculators). That’s why @ tianfu_liu’s method works. Otherwise you can try to set allow_shared_calculator=True when initialize a new NEB object, and using the same calculator.
Calculators are sometimes stateful and may reuse information between computations. If each calculator sees the same NEB image in successive computations, they can reuse information well. But if a calculator sees multiple different images, it cannot reuse information well because those images are too different. It ends up discarding a good wavefunctions and reconverging, which may very well cost 40%+ computation time.
Therefore, you should create a separate calculator for each image. That should answer the question of why it is designed like that, although some of the specifics could be discussed.
If you have a calculator that does not make use of previous calculation state, you can use the SingleCalculatorNEB for convenience. This is useful for force fields, for example.
I recommend that you use threading at the NEB level and SocketIOCalculator for the individual images, since DFTB supports socket io (Communication with calculators over sockets — ASE documentation). This is likely the most efficient way to run NEB with ASE and DFTB.
However I have not tried setting up such a calculation, so whether it is necessarily straightforward in your case I cannot tell.
Note also that if you were to attempt to run the same FileIOCalculators in parallel, it would overwrite its own files in a jumble and immediately corrupt the results.
That is another reason why it is wise to use separate calculators for each image.