Quick Start

Introduction

In this tutorial, you will get a quick view of AiiDA-Bader. To run this tutorial, you need to install aiida-bader. Open a terminal and run:

pip install aiida-bader

Set up bader code and pseudopotentials

Create a yaml file named bader-localhost.yml with the following content:

python -m aiida_bader post-install

Load the AiiDA profile.

[1]:
%load_ext aiida
from aiida import load_profile
load_profile()
[1]:
Profile<uuid='91ab760297b7474e99505a4bc4da8805' name='presto'>

Quantum Espresso

Here, we will carry out the Bader charge analysis on H2O molecule using Quantum Espresso.

Three steps:

  • Self consistent calculation using pw.x.

  • Post-processing to obtain cube files using pp.x.

  • Bader charge analysis using bader.

[2]:
from aiida import load_profile
from aiida.orm import Dict, KpointsData, StructureData, load_code
from ase.build import molecule
from aiida_bader.workgraph.qe_bader import bader_workgraph
from aiida_bader.utils import load_pseudos

load_profile()
#===============================================================================
# load the codes
pw_code = load_code("pw-7.2@localhost")
pp_code = load_code("pp-7.2@localhost")
bader_code = load_code("bader@localhost")
# ===============================================================================
# create input structure
atoms = molecule("H2O")
atoms.center(vacuum=3.0)
atoms.pbc = True
structure = StructureData(ase=atoms)
# create input parameters node
scf_paras = Dict(
    {
        "SYSTEM": {
            "ecutwfc": 30,
            "ecutrho": 240,
            "occupations": "smearing",
            "smearing": "cold",
            "degauss": 0.02,
        },
    }
)
pseudo_group = "psl_kjpaw_pbesol"
pseudos = load_pseudos(structure, pseudo_group)
#
metadata = {
    "options": {
        "resources": {
            "num_machines": 1,
            "num_mpiprocs_per_machine": 1,
        },
    }
}
# ===============================================================================
# prepare inputs and submit
wg = bader_workgraph(structure=structure,
                     pw_code=pw_code,
                     pp_code=pp_code,
                     bader_code=bader_code,
                     parameters=scf_paras,
                     pseudos=pseudos,
                     metadata_pw=metadata,
                     metadata_pp=metadata,
                     metadata_bader=metadata,)
wg.run()
#------------------------- Print the output -------------------------
charges = wg.tasks["bader"].node.outputs.bader_charge.get_array("charge")
print("Bader charges:")
print("Index    Symbol    Charge")
for i, charge in enumerate(charges):
    print(f"{i:5d}    {atoms.get_chemical_symbols()[i]:5s}    {charge:5.3f}")

04/08/2025 10:29:34 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|continue_workgraph]: tasks ready to run: scf
04/08/2025 10:29:35 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|on_wait]: Process status: Waiting for child processes: 66354
04/08/2025 10:29:38 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66354|PwBaseWorkChain|run_process]: launching PwCalculation<66360> iteration #1
04/08/2025 10:30:34 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66354|PwBaseWorkChain|results]: work chain completed after 1 iterations
04/08/2025 10:30:34 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66354|PwBaseWorkChain|on_terminated]: remote folders will not be cleaned
04/08/2025 10:30:34 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|update_task_state]: Task: scf, type: WORKCHAIN, finished.
04/08/2025 10:30:35 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|continue_workgraph]: tasks ready to run: pp_valence,pp_all
04/08/2025 10:30:37 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|on_wait]: Process status: Waiting for child processes: 66366, 66367
04/08/2025 10:30:51 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|update_task_state]: Task: pp_valence, type: CALCJOB, finished.
04/08/2025 10:30:52 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|update_task_state]: Task: pp_all, type: CALCJOB, finished.
04/08/2025 10:30:53 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|continue_workgraph]: tasks ready to run: bader
04/08/2025 10:30:54 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|on_wait]: Process status: Waiting for child processes: 66378
04/08/2025 10:30:59 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|update_task_state]: Task: bader, type: CALCJOB, finished.
04/08/2025 10:31:00 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|continue_workgraph]: tasks ready to run:
04/08/2025 10:31:00 PM <343662> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [66350|WorkGraphEngine|finalize]: Finalize workgraph.
Bader charges:
Index    Symbol    Charge
    0    O        7.169
    1    H        0.415
    2    H        0.416

CP2K

Here, we will carry out the Bader charge analysis on H2O molecule using CP2K.

Two steps:

  • Self consistent calculation using cp2k, and print out the charge density as cube file.

  • Bader charge analysis using bader.

[12]:
from aiida import load_profile
from aiida.orm import Dict, StructureData, load_code, load_node, Str
from ase.build import molecule

load_profile()
#===============================================================================
# load the codes
cp2k_code = load_code("cp2k-psmp-9.1@localhost")
bader_code = load_code("bader@localhost")
basis_file = load_node(3745)
pseudo_file = load_node(3746)
# ===============================================================================
# create input structure node
h2o = molecule("H2O")
h2o.center(vacuum=3.0)
h2o.pbc = True
structure = StructureData(ase=h2o)
# Parameters.
cp2k_parameters = Dict(
    {
        "GLOBAL": {
            "RUN_TYPE": "ENERGY_FORCE",
        },
        "FORCE_EVAL": {
            "METHOD": "Quickstep",
            "DFT": {
                "BASIS_SET_FILE_NAME": "BASIS_MOLOPT",
                "POTENTIAL_FILE_NAME": "GTH_POTENTIALS",
                "SCF": {
                    "EPS_DIIS": 0.1,
                    "EPS_SCF": 1e-06,
                    "MAX_SCF": 50,
                    "SCF_GUESS": "ATOMIC",
                    "OUTER_SCF": {
                        "MAX_SCF": 20,
                        "EPS_SCF": 1e-06,
                    },
                    "OT": {
                        "ORTHO_IRAC": "CHOL",
                        "N_HISTORY_VEC": 7,
                        "SAFE_DIIS": False,
                        "PRECONDITIONER": "FULL_ALL",
                        "ENERGY_GAP": 0.05,
                        "MINIMIZER": "CG",
                        "ALGORITHM": "IRAC",
                        "EPS_IRAC_SWITCH": 0.01,
                    },
                },
                "QS": {
                    "METHOD": "GPW",
                    "EPS_DEFAULT": 1.0e-12,
                    "EXTRAPOLATION_ORDER": 3,
                },
                "MGRID": {
                    "NGRIDS": 5,
                    "CUTOFF": 800,
                    "REL_CUTOFF": 50,
                },
                "XC": {
                    "XC_FUNCTIONAL": {
                        "_": "PBE",
                    },
                },
                "PRINT": {
                    "E_DENSITY_CUBE":{
                        "EACH": {
                            "GEO_OPT": 0,
                        },
                        "ADD_LAST": "NUMERIC",
                        "STRIDE": "1 1 1",
                    }
                },
            },
            "PRINT": {
            #   "STRESS_TENSOR": {"_": "ON"},
            #   "FORCES": {"_": "ON"},
            },
            "SUBSYS": {
                "KIND": [
                    {
                        "_": "O",
                        "BASIS_SET": "DZVP-MOLOPT-GTH-q6",
                        "POTENTIAL": "GTH-PBE-q6",
                    },
                    {
                        "_": "H",
                        "BASIS_SET": "TZVP-MOLOPT-GTH",
                        "POTENTIAL": "GTH-PBE",
                    },
                ],
            },
        },
    }
)
#
metadata = {
    "options": {
        "resources": {
            "num_machines": 1,
            "num_mpiprocs_per_machine": 4,
        },
        'withmpi': False,
    }
}
# ===============================================================================
from aiida_bader.worktrees.cp2k_bader import Cp2kBaderWorkTree
wt = Cp2kBaderWorkTree()
wt.nodes["cp2k_base"].set({"cp2k": {
            "code": cp2k_code,
            "structure": structure,
            "parameters": cp2k_parameters,
            "file": {
                "basis": basis_file,
                "pseudo": pseudo_file,
            },
            "metadata": metadata,
        },
    })
wt.nodes["bader"].set({"code": bader_code,
                       "charge_density_filename": Str("aiida-ELECTRON_DENSITY-1_0.cube")})
# submit
wt.submit(wait=True, timeout=300)

Check status and results

[13]:
wt.update()
print("State of WorkTree:   {}".format(wt.state))
print('Result of bader      : {}'.format(wt.nodes["bader"].node.outputs.bader_charge.get_array("charge")))
State of WorkTree:   FINISHED
Result of bader      : [7.112106 0.44395  0.443945]