Skip to content

Commit 3015631

Browse files
hmhoseiniHosseinMiryakutovicha
authored
Add the verification-pbe-v1-sirius protocol for CP2K (#312)
Co-authored-by: hmhoseini <[email protected]> Co-authored-by: Aliaksandr Yakutovich <[email protected]>
1 parent 3e4014d commit 3015631

File tree

3 files changed

+186
-47
lines changed

3 files changed

+186
-47
lines changed

aiida_common_workflows/workflows/relax/cp2k/generator.py

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,25 @@ def dict_merge(dct, merge_dct):
3838
dct[k] = merge_dct[k]
3939

4040

41-
def get_kinds_section(structure: StructureData, basis_pseudo: str, magnetization_tags=None):
42-
""" Write the &KIND sections given the structure and the settings_dict"""
41+
def get_kinds_section(structure: StructureData, basis_pseudo=None, magnetization_tags=None, use_sirius=False):
42+
"""Write the &KIND sections given the structure and the settings_dict."""
4343
kinds = []
44-
with open(pathlib.Path(__file__).parent / basis_pseudo, 'rb') as fhandle:
45-
atom_data = yaml.safe_load(fhandle)
44+
if not use_sirius:
45+
with open(pathlib.Path(__file__).parent / basis_pseudo, 'rb') as fhandle:
46+
atom_data = yaml.safe_load(fhandle)
4647
ase_structure = structure.get_ase()
4748
symbol_tag = {
4849
(symbol, str(tag)) for symbol, tag in zip(ase_structure.get_chemical_symbols(), ase_structure.get_tags())
4950
}
5051
for symbol, tag in symbol_tag:
5152
new_atom = {
5253
'_': symbol if tag == '0' else symbol + tag,
53-
'BASIS_SET': atom_data['basis_set'][symbol],
54-
'POTENTIAL': atom_data['pseudopotential'][symbol],
5554
}
55+
if use_sirius:
56+
new_atom['POTENTIAL'] = f'UPF {symbol}.json'
57+
else:
58+
new_atom['BASIS_SET'] = atom_data['basis_set'][symbol]
59+
new_atom['POTENTIAL'] = atom_data['pseudopotential'][symbol]
5660
if magnetization_tags:
5761
new_atom['MAGNETIZATION'] = magnetization_tags[tag]
5862
kinds.append(new_atom)
@@ -126,6 +130,12 @@ def get_file_section():
126130
}
127131

128132

133+
def get_upf_pseudos_section(structure: StructureData, pseudo_family):
134+
"""Provide the pseudos section to the input."""
135+
pseudos_group = orm.load_group(pseudo_family)
136+
return pseudos_group.get_pseudos(structure=structure)
137+
138+
129139
class Cp2kCommonRelaxInputGenerator(CommonRelaxInputGenerator):
130140
"""Input generator for the `Cp2kRelaxWorkChain`."""
131141

@@ -150,7 +160,7 @@ def define(cls, spec):
150160
super().define(spec)
151161
spec.input(
152162
'protocol',
153-
valid_type=ChoiceType(('fast', 'moderate', 'precise', 'verification-pbe-v1')),
163+
valid_type=ChoiceType(('fast', 'moderate', 'precise', 'verification-pbe-v1', 'verification-pbe-v1-sirius')),
154164
default='moderate',
155165
help='The protocol to use for the automated input generation. This value indicates the level of precision '
156166
'of the results and computational cost that the input parameters will be selected for.',
@@ -190,52 +200,66 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder:
190200
kpoints_distance = protocol_dict.pop('kpoints_distance', None)
191201
kpoints = self._get_kpoints(kpoints_distance, structure, reference_workchain)
192202
mesh, _ = kpoints.get_kpoints_mesh()
193-
if mesh != [1, 1, 1]:
203+
if 'sirius' in protocol:
204+
parameters['FORCE_EVAL']['PW_DFT']['PARAMETERS']['NGRIDK'] = f'{mesh[0]} {mesh[1]} {mesh[2]}'
205+
elif mesh != [1, 1, 1]:
194206
builder.cp2k.kpoints = kpoints
195207

196208
magnetization_tags = None
197209

198210
# Metal or insulator.
199-
# If metal then add smearing, unoccupied orbitals, and employ diagonalization.
200-
if electronic_type == ElectronicType.METAL:
201-
parameters['FORCE_EVAL']['DFT']['SCF']['SMEAR'] = {
202-
'_': 'ON',
203-
'METHOD': 'FERMI_DIRAC',
204-
'ELECTRONIC_TEMPERATURE': '[K] 710.5',
205-
}
206-
parameters['FORCE_EVAL']['DFT']['SCF']['DIAGONALIZATION'] = {
207-
'EPS_ADAPT': '1',
208-
}
209-
parameters['FORCE_EVAL']['DFT']['SCF']['MIXING'] = {
210-
'METHOD': 'BROYDEN_MIXING',
211-
'ALPHA': '0.1',
212-
'BETA': '1.5',
213-
}
214-
parameters['FORCE_EVAL']['DFT']['SCF']['ADDED_MOS'] = 20
215-
parameters['FORCE_EVAL']['DFT']['SCF']['CHOLESKY'] = 'OFF'
216-
217-
# If insulator then employ OT.
218-
elif electronic_type == ElectronicType.INSULATOR:
219-
parameters['FORCE_EVAL']['DFT']['SCF']['OT'] = {
220-
'PRECONDITIONER': 'FULL_SINGLE_INVERSE',
221-
'MINIMIZER': 'CG',
222-
}
223-
224-
# Magnetic calculation.
225-
if spin_type == SpinType.NONE:
226-
parameters['FORCE_EVAL']['DFT']['UKS'] = False
227-
if magnetization_per_site is not None:
228-
import warnings
229-
warnings.warn('`magnetization_per_site` will be ignored as `spin_type` is set to SpinType.NONE')
230-
231-
elif spin_type == SpinType.COLLINEAR:
232-
parameters['FORCE_EVAL']['DFT']['UKS'] = True
233-
structure, magnetization_tags = tags_and_magnetization(structure, magnetization_per_site)
234-
parameters['FORCE_EVAL']['DFT']['MULTIPLICITY'] = guess_multiplicity(structure, magnetization_per_site)
211+
if 'sirius' not in protocol: # It is not possible to disable smearing for sirius.
212+
# If metal then add smearing, unoccupied orbitals, and employ diagonalization.
213+
if electronic_type == ElectronicType.METAL:
214+
parameters['FORCE_EVAL']['DFT']['SCF']['SMEAR'] = {
215+
'_': 'ON',
216+
'METHOD': 'FERMI_DIRAC',
217+
'ELECTRONIC_TEMPERATURE': '[K] 710.5',
218+
}
219+
parameters['FORCE_EVAL']['DFT']['SCF']['DIAGONALIZATION'] = {
220+
'EPS_ADAPT': '1',
221+
}
222+
parameters['FORCE_EVAL']['DFT']['SCF']['MIXING'] = {
223+
'METHOD': 'BROYDEN_MIXING',
224+
'ALPHA': '0.1',
225+
'BETA': '1.5',
226+
}
227+
parameters['FORCE_EVAL']['DFT']['SCF']['ADDED_MOS'] = 20
228+
parameters['FORCE_EVAL']['DFT']['SCF']['CHOLESKY'] = 'OFF'
229+
230+
# If insulator then employ OT.
231+
elif electronic_type == ElectronicType.INSULATOR:
232+
parameters['FORCE_EVAL']['DFT']['SCF']['OT'] = {
233+
'PRECONDITIONER': 'FULL_SINGLE_INVERSE',
234+
'MINIMIZER': 'CG',
235+
}
236+
237+
# Magnetic calculation. Changing this configuration has no effect on sirius calculations.
238+
if spin_type == SpinType.NONE:
239+
parameters['FORCE_EVAL']['DFT']['UKS'] = False
240+
if magnetization_per_site is not None:
241+
import warnings
242+
warnings.warn('`magnetization_per_site` will be ignored as `spin_type` is set to SpinType.NONE')
243+
244+
elif spin_type == SpinType.COLLINEAR:
245+
parameters['FORCE_EVAL']['DFT']['UKS'] = True
246+
structure, magnetization_tags = tags_and_magnetization(structure, magnetization_per_site)
247+
parameters['FORCE_EVAL']['DFT']['MULTIPLICITY'] = guess_multiplicity(structure, magnetization_per_site)
235248

236249
# Starting magnetization.
237250
basis_pseudo = protocol_dict.pop('basis_pseudo')
238-
dict_merge(parameters, get_kinds_section(structure, basis_pseudo, magnetization_tags))
251+
if 'sirius' in protocol:
252+
dict_merge(
253+
parameters,
254+
get_kinds_section(structure, basis_pseudo=None, magnetization_tags=magnetization_tags, use_sirius=True)
255+
)
256+
else:
257+
dict_merge(
258+
parameters,
259+
get_kinds_section(
260+
structure, basis_pseudo=basis_pseudo, magnetization_tags=magnetization_tags, use_sirius=False
261+
)
262+
)
239263

240264
# Relaxation type.
241265
if relax_type == RelaxType.POSITIONS:
@@ -281,7 +305,10 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder:
281305
builder.handler_overrides = orm.Dict(dict={'restart_incomplete_calculation': True})
282306

283307
# Files.
284-
builder.cp2k.file = get_file_section()
308+
if 'sirius' in protocol:
309+
builder.cp2k.pseudos_upf = get_upf_pseudos_section(structure, basis_pseudo)
310+
else:
311+
builder.cp2k.file = get_file_section()
285312

286313
# Input structure.
287314
builder.cp2k.structure = structure

aiida_common_workflows/workflows/relax/cp2k/protocol.yml

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,3 +467,115 @@ verification-pbe-v1:
467467
RMS_FORCE: "[bohr^-1*hartree] 0.00030" #default: [bohr^-1*hartree] 0.00030
468468
BFGS:
469469
TRUST_RADIUS: "[angstrom] 0.5"
470+
verification-pbe-v1-sirius:
471+
description: 'Protocol to relax a structure with SIRIUS and UPF pseudopotentials'
472+
kpoints_distance: 0.06
473+
basis_pseudo: SSSP/1.2/PBE/precision
474+
input:
475+
GLOBAL:
476+
EXTENDED_FFT_LENGTHS: True
477+
PREFERRED_DIAG_LIBRARY: ScaLAPACK
478+
PRINT_LEVEL: MEDIUM #default: MEDIUM. Important to have the correct parsing
479+
FORCE_EVAL:
480+
METHOD: SIRIUS
481+
STRESS_TENSOR: ANALYTICAL
482+
PRINT:
483+
FORCES:
484+
FILENAME: requested-forces
485+
ADD_LAST: SYMBOLIC
486+
PW_DFT:
487+
CONTROL:
488+
VERBOSITY: 2
489+
PARAMETERS:
490+
ELECTRONIC_STRUCTURE_METHOD: pseudopotential
491+
USE_SYMMETRY: TRUE
492+
GK_CUTOFF: 10 # a.u.^-1
493+
PW_CUTOFF: 55 # a.u.^-1
494+
ENERGY_TOL: 1e-15
495+
NUM_DFT_ITER: 400
496+
SMEARING: FERMI_DIRAC
497+
SMEARING_WIDTH: 0.00225
498+
ITERATIVE_SOLVER:
499+
ENERGY_TOLERANCE: 0.001
500+
NUM_STEPS: 20
501+
SUBSPACE_SIZE: 4
502+
CONVERGE_BY_ENERGY: 1
503+
DFT:
504+
XC:
505+
XC_FUNCTIONAL:
506+
GGA_X_PBE:
507+
_: ''
508+
GGA_C_PBE:
509+
_: ''
510+
PRINT:
511+
MO:
512+
_: 'OFF'
513+
ADD_LAST: SYMBOLIC
514+
EIGENVALUES: ON
515+
OCCUPATION_NUMBERS: ON
516+
NDIGITS: 12
517+
EACH:
518+
CELL_OPT: 0
519+
GEO_OPT: 0
520+
MD: 0
521+
QS_SCF: 0
522+
MULLIKEN:
523+
_: 'ON'
524+
ADD_LAST: SYMBOLIC
525+
EACH:
526+
CELL_OPT: 0
527+
GEO_OPT: 0
528+
MD: 0
529+
LOWDIN:
530+
_: 'OFF'
531+
HIRSHFELD:
532+
_: 'OFF'
533+
SUBSYS:
534+
MOTION:
535+
PRINT:
536+
TRAJECTORY:
537+
FORMAT: DCD_ALIGNED_CELL
538+
EACH:
539+
CELL_OPT: 1
540+
GEO_OPT: 1
541+
MD: 1
542+
RESTART:
543+
BACKUP_COPIES: 0
544+
EACH:
545+
CELL_OPT: 1
546+
GEO_OPT: 1
547+
MD: 1
548+
RESTART_HISTORY:
549+
_: 'OFF'
550+
CELL:
551+
_: 'OFF'
552+
VELOCITIES:
553+
_: 'OFF'
554+
FORCES:
555+
_: 'ON'
556+
STRESS:
557+
_: 'ON'
558+
GEO_OPT:
559+
TYPE: MINIMIZATION #default: MINIMIZATION
560+
OPTIMIZER: BFGS #default: BFGS
561+
MAX_ITER: 1000 #default: 200
562+
MAX_DR: "[bohr] 0.0030" #default: [bohr] 0.0030
563+
RMS_DR: "[bohr] 0.0015" #default: [bohr] 0.0015
564+
MAX_FORCE: "[bohr^-1*hartree] 0.00045" #default: [bohr^-1*hartree] 0.00045
565+
RMS_FORCE: "[bohr^-1*hartree] 0.00030" #default: [bohr^-1*hartree] 0.00030
566+
BFGS:
567+
TRUST_RADIUS: "[angstrom] 0.25" #default: [angstrom] 0.25
568+
CELL_OPT:
569+
TYPE: DIRECT_CELL_OPT #default: DIRECT_CELL_OPT
570+
EXTERNAL_PRESSURE: "[bar] 0.0"
571+
PRESSURE_TOLERANCE: "[bar] 100" #default: 100
572+
KEEP_ANGLES: False
573+
KEEP_SYMMETRY: False
574+
OPTIMIZER: BFGS #default: BFGS
575+
MAX_ITER: 1000 #default: 200
576+
MAX_DR: "[bohr] 0.0030" #default: [bohr] 0.0030
577+
RMS_DR: "[bohr] 0.0015" #default: [bohr] 0.0015
578+
MAX_FORCE: "[bohr^-1*hartree] 0.00045" #default: [bohr^-1*hartree] 0.00045
579+
RMS_FORCE: "[bohr^-1*hartree] 0.00030" #default: [bohr^-1*hartree] 0.00030
580+
BFGS:
581+
TRUST_RADIUS: "[angstrom] 0.5"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ dependencies = [
2626
'aiida-bigdft>=0.2.6',
2727
'aiida-castep>=1.2.0a5',
2828
'aiida-core[atomic_tools]~=1.6',
29-
'aiida-cp2k~=1.3',
29+
'aiida-cp2k~=1.6',
3030
'aiida-fleur>=1.3.0',
3131
'aiida-gaussian',
3232
'aiida-nwchem>=2.1.0',

0 commit comments

Comments
 (0)