Hello Hiphive users and developers,
I have done some reference calculations with DFT via Wien2k code. to this aim I have generated the displaced structures with hiphive and changed the supercells_rattled.extxyz to some .xyz files and again changed them to .struct file. the forces of each struct file are computed via DFT in Wien2k code. Now for further computational work, I have to set up structure container, to do this, I am using the commands below:
sc = StructureContainer(cs)
configurations=ase.io.read(supercells_rattled.extxyz)
for i, atoms in enumerate(configurations):
sc.add_structure(atoms)
sc.write(path_to_structure_container_filename)
but I faced the error below:
âAtomâ object has no attribute âcopyâ
could you please guide me to solve it?
ase.io.read('supercells_rattled.extxyz')
returns an Atoms object, not a series of them. So the
for i, atoms ...
loop will actually loop of the series of Atom inside that Atoms object.
Instead you should load the Atoms objects with
ase.io.read('supercells_rattled.extxyz', index=':')
to specify that you want all of the structures in the file. (index
defaults to -1
, the last Atoms in the file. Very useful for geometry optimisation but not so helpful for this kind of thing!)
1 Like
Thank you, I applied the change you said but I got the following error:
ValueError: Atoms must have displacements array
I will send you the complete code. The problem may be in the previous lines:
import ase
import hiphive
from ase.io import write
from ase.io import read
from ase.build import bulk
from ase.calculators.emt import EMT
from hiphive.structure_generation import generate_mc_rattled_structures
from ase import db
from ase.db import connect
from ase.calculators.singlepoint import SinglePointCalculator
from ase.io import read
from ase.io.wien2k import read_struct
import numpy as np
from numpy import load , genfromtxt
from ase import db
from hiphive import ClusterSpace, StructureContainer
from hiphive.utilities import get_displacements
n_structures = 5
cell_size = 2
rattle_std = 0.03
minimum_distance = 2.3
prim = read(path_to_prim)
atoms_ideal = prim.repeat(cell_size)
database = db.connect('database.db')
for i in range(1, 5):
filename = f'supercell-{i}.struct'
atoms = read_struct(filename)
# Load the npy file
forces = np.load(f'forces-{i}.npy')
atoms.calc = SinglePointCalculator(atoms, forces=forces)
database.write(atoms, name=filename)
structures = []
for row in db.select():
# Get forces and displacements.
atoms = row.toatoms()
displacements = get_displacements(atoms, atoms_ideal)
forces = atoms.get_forces()
# Sanity check, displacements should not be abnormally large
# (here taken as 1.0 A)
assert np.linalg.norm(displacements, axis=1).max() < 1.0
# Finalize.
# The structure container should see the ideal structure in
# order to be able to process the symmetry.
atoms_tmp = atoms_ideal.copy()
# The displacements and forces are attached as separate arrays.
atoms_tmp.new_array('displacements', displacements)
atoms_tmp.new_array('forces', forces)
structures.append(atoms_tmp)
cutoffs = [5.0, 4.0, 4.0]
# Set up cluster space.
cs = ClusterSpace(atoms_ideal, cutoffs)
sc = StructureContainer(cs)
configurations=ase.io.read('supercells_rattled.extxyz', index=':')
for i, atoms in enumerate(configurations):
sc.add_structure(atoms)
sc.write(path_to_structure_container_filename)
It is helpful when reporting error messages to also include some of the stacktrace so people can see where it came from.
Here I assume it came from sc.add_structure(atoms)
because the StructureContainer needs the displacement information to be attached to Atoms. In the tutorials this is mostly done using hiphive.utilities.prepare_structure
.
In this script, it looks like you created a list of atoms âstructuresâ that do have a displacements array â but then this list is never used. Instead, you grab a different list of atoms called âconfigurationsâ from the extxyz file that donât have this data, and pass those to sc.add_structure()
instead.
1 Like
yes. you are right. the error is came from sc.add_structure(atoms):
ValueError Traceback (most recent call last)
Cell In[15], line 10
8 configurations=ase.io.read('supercells_rattled.extxyz', index=':')
9 for i, atoms in enumerate(configurations):
---> 10 sc.add_structure(atoms)
11 sc.write(path_to_structure_container_filename)
File ~\AppData\Roaming\Python\Python310\site-packages\hiphive\structure_container.py:166, in StructureContainer.add_structure(self, atoms, **meta_data)
164 # atoms object must contain displacements
165 if 'displacements' not in atoms_copy.arrays.keys():
--> 166 raise ValueError('Atoms must have displacements array')
168 # atoms object must contain forces
169 if 'forces' not in atoms_copy.arrays.keys():
ValueError: Atoms must have displacements array
actually I did not know what to set instead of configurations!?could you please tell me what should I set as configurations?
Some questions to consider:
- what is the purpose of StructureContainer?
- what information does the StructureContainer need in order to do its job?
- what information is in âsupercells_rattled.extxyzâ?
- why did you attach displacements and forces to âstructuresâ, but not use this object any more?
I went through this script step by step as per the tutorial. I needed togenerate SC to continue the calculations, so I faced to the configurations statement. First, I put the structures instead, which I got the following error. Then I asked about it in https://gitlab.com/materials-modeling/hiphive/-/issues/568, they said that this configuration is actually a list of structures, and thatâs why I replaced supercells_rattled.extxyz.
ValueError Traceback (most recent call last)
Cell In[7], line 10
8 #configurations=ase.io.read('supercells_rattled.extxyz', index=':')
9 for i, atoms in enumerate(structures):
---> 10 sc.add_structure(atoms)
11 sc.write(path_to_structure_container_filename)
File ~\AppData\Roaming\Python\Python310\site-packages\hiphive\structure_container.py:178, in StructureContainer.add_structure(self, atoms, **meta_data)
176 for i, structure in enumerate(self._structure_list):
177 if are_configurations_equal(atoms_copy, structure.atoms):
--> 178 raise ValueError('Atoms is identical to structure {}'.format(i))
180 logger.debug('Adding structure')
181 M = self._compute_fit_matrix(atoms)
ValueError: Atoms is identical to structure 1
It looks like you now have the right idea to use the structures that include forces and displacements.
This error message says that you passed more than one identical Atoms to add_structure()
. How did that happen? Is it possible that your database has some duplicate rows?