-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding magnetic utils for atomistic StructureData
Very similar to HubbardUtils.
- Loading branch information
1 parent
bc0d815
commit b8fb12a
Showing
1 changed file
with
90 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# -*- coding: utf-8 -*- | ||
"""Utility class for handling the :class:`aiida_quantumespresso.data.hubbard_structure.HubbardStructureData`.""" | ||
# pylint: disable=no-name-in-module | ||
from itertools import product | ||
import os | ||
from typing import Tuple, Union | ||
|
||
from aiida import orm | ||
from aiida.engine import calcfunction | ||
from aiida.orm import StructureData as LegacyStructureData | ||
from aiida.plugins import DataFactory | ||
import numpy as np | ||
|
||
StructureData = DataFactory('atomistic.structure') | ||
|
||
|
||
class MagneticUtils: | ||
"""Class to manage the magnetic structure of the atomistic `LegacyStructureData`. | ||
It contains methods to manipulate the magnetic structure in such a way to produce the correct input for QuantumESPRESSO calculations. | ||
""" | ||
|
||
def __init__( | ||
self, | ||
structure: StructureData, | ||
): | ||
"""Set a the `StructureData` to manipulate.""" | ||
if isinstance(structure, StructureData): | ||
if 'magmoms' not in structure.get_defined_properties(): | ||
raise ValueError('The input structure does not contain magnetic moments.') | ||
self.structure = structure | ||
else: | ||
raise ValueError('input is not of type atomistic `StructureData') | ||
|
||
def generate_magnetic_namelist(self, parameters): | ||
"""Generate the magnetic namelist for Quantum ESPRESSO. | ||
:param parameters: dictionary of inputs for the Quantum ESPRESSO calculation. | ||
""" | ||
if 'nspin' not in parameters['SYSTEM'] and 'noncolin' not in parameters['SYSTEM']: | ||
raise ValueError("The input parameters must contain the 'nspin' or the 'noncolin' key.") | ||
|
||
namelist = {'starting_magnetization': {}, 'angle1': {}, 'angle2': {}} | ||
|
||
if parameters['SYSTEM'].get('nspin', None) == 2: | ||
namelist.pop('angle1') | ||
namelist.pop('angle2') | ||
if self.structure.is_collinear: | ||
for kind, magmom in zip(self.structure.kinds, self.structure.magmoms): | ||
# this should be fixed, now only magmom_z is considered... | ||
if magmom[2] != 0: | ||
namelist['starting_magnetization'][kind] = magmom[2] | ||
else: | ||
raise NotImplementedError( | ||
'The input structure is not collinear, but you choose collinear calculations.' | ||
) | ||
elif parameters['SYSTEM']['noncolin']: | ||
for site in self.structure.sites: | ||
for variable in namelist.keys(): | ||
namelist[variable][site.kinds] = site.get_magmom_coord(coord='spherical')[variable] | ||
|
||
return namelist | ||
|
||
|
||
@calcfunction | ||
def generate_structure_with_magmoms(input_structure=StructureData, input_magnetic_moments=orm.List): | ||
"""Generate a new structure with the magnetic moments for each site. | ||
:param input_structure: the input structure to add the magnetic moments. | ||
:param input_magnetic_moments: the magnetic moments for each site, represented as a float (see below). | ||
For now, only supports collinear magnetic moments, i.e. atomic magnetizations (along z axis). | ||
""" | ||
magmoms = input_magnetic_moments.get_list() | ||
if len(input_structure.sites) != len(magmoms): | ||
raise ValueError('The input structure and the magnetic moments must have the same length.') | ||
|
||
mutable_structure = input_structure.get_value() | ||
mutable_structure.clear_sites() | ||
for site, magmom in zip(input_structure.sites, magmoms): | ||
mutable_structure.add_atom( | ||
**{ | ||
'positions': site.positions, | ||
'symbols': site.symbols, | ||
'kinds': site.kinds, | ||
'weights': site.weights, | ||
'magmoms': [0, 0, magmom] if isinstance(magmom, float) else magmom # 3D vector | ||
} | ||
) | ||
|
||
output_structure = StructureData.from_mutable(mutable_structure, detect_kinds=True) | ||
|
||
return output_structure |