Main Calculation

The crystal17.main plugin is the core calculation plugin. It is designed with a more programmatic input interface , to create the input .d12 and .gui files, from a set of AiiDA Data nodes.

See also

See Main Calculation Immigration for a method to immigrate existing output/input files as a crystal17.main calculation.

Initial Setup

To run a computation, first ensure AiiDA is running:

!verdi status
profile:     On profile test_profile
repository:  /var/folders/dm/b2qnkb_n3r72slmpxlfmcjvm00lbnd/T/tmpvsllm_zf/test_repo
postgres:    Connected as aiida@localhost:61847
rabbitmq:    Connected to amqp://127.0.0.1?heartbeat=600
daemon:      Daemon is running as PID 38435 since 2019-08-12 11:39:10

See also

AiiDA documentation: Getting Started

If aiida-crystal17 is installed, the crystal17.main computation should be available:

!verdi plugin list aiida.calculations crystal17.main
-/|\-/Inputs
      basissets:  required  BasisSetData        Use a node for the basis set of one of the elements in the structure. You h ...
           code:  required  Code                The Code to use for this job.
     parameters:  required  CryInputParamsData  the input parameters to create the .d12 file content.
      structure:  required  StructureData       structure used to construct the input fort.34 (gui) file
          kinds:  optional  KindData            additional structure kind specific data (e.g. initial spin)
       metadata:  optional                      
       symmetry:  optional  SymmetryData        the symmetry of the structure, used to construct the input .gui file (fort. ...
      wf_folder:  optional  RemoteData          An optional working directory, of a previously completed calculation, conta ...
Outputs
  remote_folder:  required  RemoteData          Input files necessary to run the process will be stored in this folder node ...
        results:  required  Dict                the data extracted from the main output file
      retrieved:  required  FolderData          Files that are retrieved by the daemon will be stored in this node. By defa ...
   optimisation:  optional  TrajectoryData      atomic configurations, for each optimisation step
      structure:  optional  StructureData       the structure output from the calculation
       symmetry:  optional  SymmetryData        the symmetry data from the calculation
Exit codes
              1:  The process has failed with an unspecified error.
              2:  The process failed with legacy failure mode.
             10:  The process returned an invalid output.
             11:  The process did not register a required output.
            200:  The retrieved folder data node could not be accessed.
            210:  The main (stdout) output file was not found
            211:  The temporary retrieved folder was not found
            300:  An error was flagged trying to parse the crystal exec stdout file
            301:  An error occurred parsing the 'opta'/'optc' geometry files
            302:  The crystal exec stdout file denoted that the run was a testgeom
            350:  The input file could not be read by crystal
            351:  Crystal could not find the required wavefunction file
            400:  The calculation stopped prematurely because it ran out of walltime.
            401:  The calculation stopped prematurely because it ran out of memory.
            402:  The calculation stopped prematurely because it ran out of virtual memory.
            411:  Scf convergence did not finalise (usually due to reaching step limit)
            412:  Geometry convergence did not finalise (usually due to reaching step limit)
            413:  An error encountered usually during geometry optimisation
            414:  An error was encountered during an scf computation
            415:  An unknown error was encountered, causing the mpi to abort
            499:  The main crystal output file flagged an unhandled error
            510:  Inconsistency in the input and output symmetry
            520:  Primitive symmops were not found in the output file

To use the python interface, first ensure a profile is loaded in the python kernel, and import the required modules:

from aiida import load_profile
profile = load_profile()
profile.name
'test_crystal17'
import os
from six import StringIO
from aiida.orm import Code
from aiida.plugins import (
    DataFactory, WorkflowFactory, CalculationFactory)
from aiida.engine import run_get_node
from aiida_crystal17.common import display_json
from aiida_crystal17.tests import read_resource_text, resource_context
from aiida.tools.visualization import Graph
from jsonextended import edict

Input Node Creation

See also

CRYSTAL17 Manual

Code

See also

AiiDA documentation: How to run external codes

An Code node should be set up in advance, to use the crystal17.basic calculation plugin, and call the runcry17 executable (or mock_runcry17 used here for test purposes).

from aiida_crystal17.tests.utils import get_or_create_local_computer, get_or_create_code
computer = get_or_create_local_computer('work_directory', 'localhost')
code = get_or_create_code('crystal17.main', computer, 'mock_crystal17')
code.get_full_text_info()
[['PK', 1],
 ['UUID', 'a2241a9c-deac-4960-9812-088666800dee'],
 ['Label', 'crystal17.main-mock_crystal17@localhost'],
 ['Description', ''],
 ['Default plugin', 'crystal17.main'],
 ['Type', 'remote'],
 ['Remote machine', 'localhost'],
 ['Remote absolute path',
  '//anaconda/envs/aiida_crystal17/bin/mock_crystal17'],
 ['Prepend text', 'No prepend text'],
 ['Append text', 'No append text']]

Input Parameters (Geometry Independent)

The CryInputParamsData supplies (geometry independent) data required to create the input.d12 file.

param_dict = {"scf":{"k_points": (8, 8)}}
params = DataFactory('crystal17.parameters')(data=param_dict)
params
<CryInputParamsData: uuid: 626c1897-3632-4eec-b375-b3a3875317c8 (unstored)>

The input data is validated against the CryMainCalculation Input Schema, which can also be obtained from the data_schema attribute.

Note

The only mandated key is scf.k_points (known as SHRINK in CRYSTAL17)

param_cls = DataFactory('crystal17.parameters')
edict.pprint(params.data_schema, keycolor="blue")
$schema:     http://json-schema.org/draft-04/schema#
additionalProperties: False
description: Allowed Inputs For CRYSTAL17 .d12 file
properties:
  basis_set:
    additionalProperties: False
    description: Basis sets input and control
    properties:  {...}
    title:       Block 2
    type:        object
  geometry:
    additionalProperties: False
    description: Geometry input, manipulation and optimisation control
    properties:  {...}
    title:       Block 1
    type:        object
  scf:
    additionalProperties: False
    dependencies: {...}
    description: Single particle Hamiltonian and SCF control
    properties:  {...}
    required:    [k_points]
    title:       Block 3
    type:        object
  title:
    description: the title of the run
    type: string
required:    [scf]
title:       CRYSTAL17 Input
type:        object
params = DataFactory('crystal17.parameters')(data={"scf": {}})
---------------------------------------------------------------------------
ValidationError                           Traceback (most recent call last)
<ipython-input-8-4a25c6adca90> in <module>()
----> 1 params = DataFactory('crystal17.parameters')(data={"scf": {}})

/Users/cjs14/GitHub/aiida-crystal17/aiida_crystal17/data/input_params.py in __init__(self, data, unflatten, **kwargs)
     61             if unflatten:
     62                 data = unflatten_dict(data)
---> 63             self.set_data(data)
     64 
     65     def _validate(self):

/Users/cjs14/GitHub/aiida-crystal17/aiida_crystal17/data/input_params.py in set_data(self, data)
     79 
     80         # first validate the inputs
---> 81         self.validate_parameters(data)
     82 
     83         # store all but the symmetry operations as attributes

/Users/cjs14/GitHub/aiida-crystal17/aiida_crystal17/data/input_params.py in validate_parameters(cls, dct)
     44 
     45         """
---> 46         validate_against_schema(dct, cls.data_schema)
     47 
     48     def __init__(self, data=None, unflatten=False, **kwargs):

/Users/cjs14/GitHub/aiida-crystal17/aiida_crystal17/validation/utils.py in validate_against_schema(data, schema)
    109     if errors:
    110         raise jsonschema.ValidationError('\n'.join([
--> 111             "- {} [key path: '{}']".format(error.message, '/'.join([str(p) for p in error.path])) for error in errors
    112         ]))
    113 

ValidationError: - 'k_points' is a required property [key path: 'scf']

It is also possible to reverse engineer the input data, from an existing input file, using extract_data, which is also exposed on the command line as verdi data crystal17.parse stdin.

from aiida_crystal17.parsers.raw.inputd12_read import extract_data
param_dict, basis_sets, atom_props = extract_data("""\
MgO bulk
EXTERNAL
OPTGEOM
FULLOPTG
END
END
12 3
1 0 3  2.  0.
1 1 3  8.  0.
1 1 3  2.  0.
8 2
1 0 3  2.  0.
1 1 3  6.  0.
99   0
END
DFT
B3LYP
SPIN
END
SHRINK
8 8
ANDERSON
SMEAR
0.1
ATOMSPIN
2
1 1 2 -1
PPAN
END
""")
param_dict
{'title': 'MgO bulk',
 'geometry': {'optimise': {'type': 'FULLOPTG'}},
 'scf': {'dft': {'xc': 'B3LYP', 'SPIN': True},
  'k_points': (8, 8),
  'fock_mixing': 'ANDERSON',
  'numerical': {'SMEAR': 0.1},
  'post_scf': ['PPAN']}}
from aiida_crystal17.parsers.raw.inputd12_write import write_input
print(write_input(param_dict, basis_sets, atom_props))
MgO bulk
EXTERNAL
OPTGEOM
FULLOPTG
ENDOPT
END
12 3
1 0 3  2.  0.
1 1 3  8.  0.
1 1 3  2.  0.
8 2
1 0 3  2.  0.
1 1 3  6.  0.
99 0
END
DFT
B3LYP
SPIN
END
SHRINK
8 8
ATOMSPIN
2
1 1
2 -1
SMEAR
0.1
ANDERSON
PPAN
END

Atomic Structure

The structure refers to a standard StructureData node, and is used to create the main.gui.

Structures consist of:

  • A cell with a basis vectors and whether it is periodic, for each dimension

  • Site with a cartesian coordinate and reference to a kind

  • Kind which details the species and composition at one or more sites

The simplest way to create a structure is via ase:

from ase.spacegroup import crystal
atoms = crystal(
    symbols=[12, 8],
    basis=[[0, 0, 0], [0.5, 0.5, 0.5]],
    spacegroup=225,
    cellpar=[4.21, 4.21, 4.21, 90, 90, 90])
struct_cls = DataFactory('structure')
structure = struct_cls(ase=atoms)
structure
<StructureData: uuid: e66d91f2-577a-4ec5-a453-d3ae698300d5 (unstored)>

These structures can be visualised using standard ASE methods.

%matplotlib inline
import matplotlib.pyplot as plt
from ase.visualize.plot import plot_atoms
atoms = structure.get_ase()
fig, ax = plt.subplots()
plot_atoms(atoms.repeat((2,2,2)),
           ax, radii=0.8, show_unit_cell=True,
           rotation=('45x,0y,0z'));
../_images/calc_main_31_0.png

As default, one kind is created per atomic species (named as the atomic symbol):

structure.get_site_kindnames()
['Mg', 'Mg', 'Mg', 'Mg', 'O1', 'O1', 'O1', 'O1']

However, we may want to specify more than one kind per species (for example to setup anti-ferromagnetic spin). We can achieve this by tagging the atoms:

atoms_afm = atoms.copy()
atoms_afm.set_tags([1, 1, 2, 2, 0, 0, 0, 0])
structure_afm = struct_cls(ase=atoms_afm)
structure_afm.get_site_kindnames()
['Mg1', 'Mg1', 'Mg2', 'Mg2', 'O', 'O', 'O', 'O']

Note

Since we always use the EXTERNAL keyword for geometry, any manipulation to the geometry is undertaken before calling CRYSTAL (i.e. we delegate the responsibility for geometry away from CRYSTAL).

Kind Specific Parameters

Also, we may want to add atom specific inputs to the .d12, such as initial spin and frozen atoms (for optimisation).

kind_cls = DataFactory("crystal17.kinds")
kind_data = kind_cls(data={
    "kind_names": ["Mg1", "Mg2", "O"],
    "spin_alpha": [True, False, False],
    "spin_beta": [False, True, False],
    "fixed": [False, False, True],
    "ghosts": [False, False, False]
})
display_json(kind_data.kind_dict)
{
  "Mg1": {
    "spin_alpha": true,
    "spin_beta": false,
    "fixed": false,
    "ghosts": false
  },
  "Mg2": {
    "spin_alpha": false,
    "spin_beta": true,
    "fixed": false,
    "ghosts": false
  },
  "O": {
    "spin_alpha": false,
    "spin_beta": false,
    "fixed": true,
    "ghosts": false
  }
}
from aiida_crystal17.parsers.raw.inputd12_write import create_atom_properties
atom_props2 = create_atom_properties(structure_afm, kind_data)
atom_props2
{'spin_alpha': [1, 2],
 'spin_beta': [3, 4],
 'unfixed': [1, 2, 3, 4],
 'ghosts': []}
print(write_input(param_dict, basis_sets, atom_props2))
MgO bulk
EXTERNAL
OPTGEOM
FULLOPTG
FRAGMENT
4
1 2 3 4
ENDOPT
END
12 3
1 0 3  2.  0.
1 1 3  8.  0.
1 1 3  2.  0.
8 2
1 0 3  2.  0.
1 1 3  6.  0.
99 0
END
DFT
B3LYP
SPIN
END
SHRINK
8 8
ATOMSPIN
4
1 1
2 1
3 -1
4 -1
SMEAR
0.1
ANDERSON
PPAN
END

Basis Sets

Basis sets are stored as separate BasisSetData nodes, in a similar fashion to UpfData. They are created individually from a text file, which contains the content of the basis set and (optionally) a YAML style header section, fenced by ---:

mg_basis_content = read_resource_text('basis_sets', 'sto3g', 'sto3g_Mg.basis')
print(mg_basis_content)
---
author: John Smith
year: 1999
class: sto3g
---
12 3
1 0 3  2.  0.
1 1 3  8.  0.
1 1 3  2.  0.

The attributes of the basis set are stored in the database, and the md5 hash-sum is used to test equivalence of two basis sets.

basis_cls = DataFactory('crystal17.basisset')
mg_basis, created = basis_cls.get_or_create(StringIO(mg_basis_content))
display_json(mg_basis.attributes)
mg_basis.content
{
  "md5": "0731ecc3339d2b8736e61add113d0c6f",
  "year": 1999,
  "class": "sto3g",
  "author": "John Smith",
  "element": "Mg",
  "filename": "stringio.txt",
  "basis_type": "all-electron",
  "num_shells": 3,
  "atomic_number": 12,
  "orbital_types": [
    "S",
    "SP",
    "SP"
  ]
}
'12 3\n1 0 3  2.  0.\n1 1 3  8.  0.\n1 1 3  2.  0.'

A simpler way to create and refer to basis sets, is via a family group. All basis sets in a folder can be read and saved to a named family by:

with resource_context('basis_sets', 'sto3g') as path:
   nfiles, nuploaded = basis_cls.upload_basisset_family(
                           path,
                           "sto3g", "group of sto3g basis sets",
                           extension=".basis", stop_if_existing=False)
basis_cls.get_basis_group_map("sto3g")
{'Mg': <BasisSetData: uuid: 5f28ddd8-b55d-4724-82fb-fb884010cd39 (pk: 2)>,
 'Ni': <BasisSetData: uuid: dbf86b0d-0f68-4733-930f-ea48d8f2946d (pk: 3)>,
 'O': <BasisSetData: uuid: 93a07f42-b17c-42ab-a7b8-620b6ccd9a39 (pk: 4)>}

or at the command line:

!verdi data crystal17.basis uploadfamily --help
Usage: verdi data crystal17.basis uploadfamily [OPTIONS]

  Upload a family of CRYSTAL Basis Set files.

Options:
  --path PATH                    Path to a folder containing the Basis Set
                                 files
  --ext TEXT                     the file extension to filter by
  --name TEXT                    Name of the BasisSet family  [required]
  -D, --description DESCRIPTION  A description for the family
  --stop-if-existing             Abort when encountering a previously uploaded
                                 Basis Set file
  --dry-run                      do not commit to database or modify
                                 configuration files
  -h, --help                     Show this message and exit.
!verdi data crystal17.basis listfamilies
-/|\-/Family      Num Basis Sets
--------  ----------------
sto3g                    3

Basis families can be searched by the elements they contain:

basis_cls.get_basis_groups(["Ni", "O"])
[<Group: "sto3g" [type crystal17.basisset], of user test@aiida.mail>]

Basis sets can also be extracted for a particular structure.

basis_cls.get_basissets_from_structure(structure, "sto3g")
{'Mg': <BasisSetData: uuid: 5f28ddd8-b55d-4724-82fb-fb884010cd39 (pk: 2)>,
 'O': <BasisSetData: uuid: 93a07f42-b17c-42ab-a7b8-620b6ccd9a39 (pk: 4)>}

Important

Unlike aiida-quantumespresso.pw, crystal17.main uses one basis sets per atomic number only NOT per kind. This is because, using multiple basis sets per atomic number is rarely used in CRYSTAL17, and is limited anyway to only two types per atomic number.

Symmetry

In the main.gui file, as well as using the dimensionality (i.e. periodic boundary conditions), basis vectors and atomic positions, provided by the structure, we also need to specify the atomic symmetry of the structure.

SymmetryData is used to store this data, as a validated dictionary.

Note

The operations are given as a flattened version of the rotation matrix, followed by the translation vector.

symmetry_cls = DataFactory("crystal17.symmetry")
edict.pprint(symmetry_cls.data_schema, keycolor="blue")
$schema:     http://json-schema.org/draft-07/schema
additionalProperties: True
properties:
  basis:
    description: whether the symmetry operations are fractional or cartesian
    enum: [fractional, cartesian]
    type: string
  computation:
    description: details of the computation
    type: object
  equivalent_sites:
    description: mapping table to equivalent atomic sites
    items: {...}
    type: array
  hall_number:
    description: Hall number defining the symmetry group
    maximum: 530
    minimum: 1
    type: [null, integer]
  operations:
    description: symmetry operations, should at least include the unity
                 operation
    items: {...}
    minItems: 1
    type: array
    uniqueItems: True
required:    [hall_number, operations, basis]
title:       structure symmetry settings
type:        object

The simplest symmetry would be the unitary operator.

symmetry = symmetry_cls(data={
    "hall_number": 1,
    "basis": "fractional",
    "operations": [
        [1,0,0,0,1,0,0,0,1,0,0,0]
    ]
})
symmetry.attributes
{'hall_number': 1, 'basis': 'fractional', 'num_symops': 1}

The full symmetry operations of a periodic structure, can be computed using the crystal17.sym3d workflow. This uses the spglib <https://atztogo.github.io/spglib/>_ library to compute symmetries, but with the added constraint that sites with the same Kind must be symmetrically equivalent.

!verdi plugin list aiida.workflows crystal17.sym3d
-/|\-/Inputs
   settings:  required  Dict           
        cif:  optional  CifData        
   metadata:  optional                 
  structure:  optional  StructureData  
Outputs
   symmetry:  required  SymmetryData   
  structure:  optional  StructureData  
Exit codes
          1:  The process has failed with an unspecified error.
          2:  The process failed with legacy failure mode.
         10:  The process returned an invalid output.
         11:  The process did not register a required output.
        300:  One of either a structure or cif input must be supplied
        301:  The supplied structure must be 3d (i.e. have all dimensions pbc=true)"
        302:  Idealize can only be used when standardize=true
        303:  The kind names supplied are not compatible with the structure
        304:  Error creating new structure
        305:  Error computing symmetry operations
sym3d_cls = WorkflowFactory("crystal17.sym3d")
builder = sym3d_cls.get_builder()
builder.settings = {"symprec": 0.01}
builder.structure = structure
sym_result = run_get_node(builder)
graph = Graph(graph_attr={'size': "8,8!", "rankdir": "LR"})
graph.recurse_ancestors(sym_result.result["symmetry"],
                        annotate_links="both")
graph.graphviz
../_images/calc_main_65_0.svg

This workflow can also optionally compute the primitive and/or standardised form of the structure, before computing the symmetry of the new structure.

builder.settings = {
    "symprec": 0.01,
    "compute_primitive": True,
    "standardize_cell": True}
sym_result2 = run_get_node(builder)
graph = Graph(graph_attr={'size': "9,9!", "rankdir": "LR"})
graph.recurse_ancestors(sym_result2.result["structure"],
                        annotate_links="both")
graph.recurse_ancestors(sym_result2.result["symmetry"],
                        annotate_links="both")
graph.graphviz
../_images/calc_main_67_0.svg

The other option is to idealize the structure, which removes distortions of the unit cell’s atomic positions, compared to the ideal symmetry.

Setting Up and Running the Calculation

See also

AiiDA documentation: Processes

CryMainCalculation provides a helper function to create, populate and validate the input builder.

from aiida_crystal17.tests import get_test_structure_and_symm
from aiida_crystal17.data.kinds import KindData

calc_cls = CalculationFactory('crystal17.main')
structure, symmetry  = get_test_structure_and_symm("NiO_afm")
kind_data = KindData(data={
    "kind_names": ["Ni1", "Ni2", "O"],
    "spin_alpha": [True, False, False],
    "spin_beta": [False, True, False]})

calc_builder = calc_cls.create_builder(
    parameters={
        "title": "NiO Bulk with AFM spin",
        "scf.single": "UHF",
        "scf.k_points": (8, 8),
        "scf.spinlock.SPINLOCK": (0, 15),
        "scf.numerical.FMIXING": 30,
        "scf.post_scf": ["PPAN"]
    },
    unflatten=True,
    structure=structure,
    symmetry=symmetry,
    kinds=kind_data,
    bases="sto3g",
    code=code,
    metadata={"options": {"resources": {
        "num_machines": 1, "num_mpiprocs_per_machine": 1}}}
)
display_json(calc_builder)
{
  "metadata": {
    "options": {
      "resources": {
        "num_machines": 1,
        "num_mpiprocs_per_machine": 1
      }
    }
  },
  "basissets": {
    "Ni": [
      "uuid: dbf86b0d-0f68-4733-930f-ea48d8f2946d (pk: 3)"
    ],
    "O": [
      "uuid: 93a07f42-b17c-42ab-a7b8-620b6ccd9a39 (pk: 4)"
    ]
  },
  "parameters": [
    "uuid: c594fdb9-9fc2-4e06-a52d-7b187b1a4cfa (unstored)"
  ],
  "structure": [
    "uuid: 000fd6e6-4253-44aa-baae-6b45bb7d5fc7 (pk: 20)"
  ],
  "symmetry": [
    "uuid: 93db2f1e-0949-4e62-a14b-0d68e2d114ad (pk: 22)"
  ],
  "kinds": [
    "uuid: 7481e639-81c2-4227-b35b-1849d8c2748f (unstored)"
  ],
  "code": [
    "Remote code 'crystal17.main-mock_crystal17@localhost' on localhost,",
    "pk: 1, uuid: a2241a9c-deac-4960-9812-088666800dee"
  ]
}

In order to run the computation, the builder can be parsed to one of the AiiDA run (blocking execution) or submit (non-blocking execution) functions:

result, calcnode = run_get_node(calc_builder)

The process can be monitored on the command line:

!verdi process list -a -D desc -l 4
-/|\-/|  PK  Created    Process label          Process State    Process status
----  ---------  ---------------------  ---------------  ----------------
  25  15s ago    CryMainCalculation     ⏹ Finished [0]
  21  15s ago    compute_symmetry       ⏹ Finished [0]
  19  16s ago    primitive_structure    ⏹ Finished [0]
  18  16s ago    Symmetrise3DStructure  ⏹ Finished [0]

Total results: 4

Info: last time an entry changed state: 2s ago (at 10:39:42 on 2019-08-12)

Once the calculation is complete, a CalcJobNode will be created, to store the settings and outcome of the computation. Crucially, if the computation has completed successfully, the exit_status will be 0.

This can be assessed on the command line or with the python API.

!verdi process show {calcnode.pk}
-/|\-/|Property       Value
-------------  ------------------------------------
type           CalcJobNode
pk             25
uuid           42166254-7530-4e9e-a7f8-bef09e6a6e6f
label
description
ctime          2019-08-12 10:39:28.969540+00:00
mtime          2019-08-12 10:39:42.274641+00:00
process state  Finished
exit status    0
computer       [1] localhost

Inputs      PK    Type
----------  ----  ------------------
basissets
    O       4     BasisSetData
    Ni      3     BasisSetData
code        1     Code
kinds       24    KindData
parameters  23    CryInputParamsData
structure   20    StructureData
symmetry    22    SymmetryData

Outputs          PK  Type
-------------  ----  ----------
remote_folder    26  RemoteData
results          28  Dict
retrieved        27  FolderData
print(calcnode.is_finished_ok)
print(calcnode.process_state)
print(calcnode.exit_status)
True
ProcessState.FINISHED
0

If the calculation fails, there are three things that should be checked:

  1. The calculation’s exit_message

  2. The calculation’s log messages and scheduler output

  3. The results output node (if available)

print("Exit Message:", calcnode.exit_message)
from aiida.cmdline.utils.common import get_calcjob_report
print(get_calcjob_report(calcnode))
Exit Message: None
*** 25: None
*** (empty scheduler output file)
*** (empty scheduler errors file)
*** 0 LOG MESSAGES
!verdi process report {calcnode.pk}
-/|\-/|*** 25: None
*** (empty scheduler output file)
*** (empty scheduler errors file)
*** 0 LOG MESSAGES

Analysis of Outputs

The Graph can be used to visualise the calculations provenance graph:

graph = Graph(graph_attr={'size': "6,8!", "rankdir": "LR"})
graph.add_node(calcnode)
graph.add_incoming(calcnode, annotate_links="both")
graph.add_outgoing(calcnode, annotate_links="both")
graph.graphviz
../_images/calc_main_85_0.svg

The retrieved FolderData output node contains the CRYSTAL17 main input and output file.

calcnode.outputs.retrieved.list_object_names()
['_scheduler-stderr.txt', '_scheduler-stdout.txt', 'fort.34', 'main.out']

The results Dict output node contains key values extracted from the CRYSTAL17 standard output file.

display_json(calcnode.outputs.results.get_dict())
{
  "units": {
    "angle": "degrees",
    "energy": "eV",
    "length": "angstrom",
    "conversion": "CODATA2014"
  },
  "energy": -85124.893667339,
  "errors": [],
  "header": {
    "crystal_version": 17,
    "crystal_subversion": "1.0.1"
  },
  "volume": 36.099581472,
  "warnings": [],
  "calculation": {
    "n_ao": 46,
    "spin": true,
    "type": "unrestricted open shell",
    "n_atoms": 4,
    "n_shells": 14,
    "n_symops": 16,
    "n_core_el": 40,
    "n_electrons": 72,
    "n_kpoints_ibz": 75,
    "n_kpoints_gilat": 75
  },
  "energy_units": "eV",
  "parser_class": "CryMainParser",
  "parser_errors": [],
  "mulliken_spins": [
    3.057,
    -3.057,
    -0.072,
    0.072
  ],
  "parser_version": "0.11.0",
  "scf_iterations": 13,
  "number_of_atoms": 4,
  "parser_warnings": [],
  "mulliken_charges": [
    0.398,
    0.397,
    -0.398,
    -0.397
  ],
  "parser_exceptions": [],
  "mulliken_electrons": [
    27.602,
    27.603,
    8.398,
    8.397
  ],
  "mulliken_spin_total": 0.0,
  "number_of_assymetric": 4,
  "execution_time_seconds": 187
}

To understand the format of the parsed data, the raw parser is exposed on the command line as verdi data crystal17.parse stdout, which can be used to parse existing output files.