Note
Go to the end to download the full example code.
TOSCA spectrum from CASTEP force constants¶
Run ToscaFromForceConstantsWorkChain on
quartz force constants (a CASTEP .castep_bin). The workflow reads the force
constants, samples phonon modes across the Brillouin zone, and delegates the
spectrum calculation to
ToscaFromModesWorkChain – which appears
in the provenance graph as a called sub-workflow.
Note
Quartz is an atypical TOSCA sample. The calculation is legitimate – TOSCA samples a wide range of momentum transfer across many Brillouin zones, so the incoherent approximation works well even for a predominantly coherent scatterer like quartz – but TOSCA is mostly used for hydrogenous molecular crystals, and quartz contains no hydrogen. Treat this page as a demonstration of the method and of composing the two workflows, not as a typical measurement. For a representative sample, see the ethanol example.
Set up AiiDA¶
A shared helper loads a temporary in-memory profile and a localhost Python code.
from _aiida_setup import example_data, get_python_code, show_provenance
from aiida import orm
from aiida.engine import run_get_node
code = get_python_code()
Run the workflow¶
Inputs for the delegated spectrum calculation live under the spectrum
namespace, keeping them clearly separate from this workflow’s own
force-constants and sampling inputs.
Note
q_spacing here is deliberately coarse – a 3x3x3 grid, far coarser than
the density-of-states example uses on the same crystal –
purely to keep this page’s build time down. abinslib 0.1’s
combination-mode routine costs O(N^2) in the number of q-points (it
accumulates spectra by repeated addition, revalidating every previously
accumulated line each time), so a converged mesh would take tens of minutes
rather than seconds. The spectrum below is therefore under-sampled: the peak
positions are sound, but their relative intensities would shift on a finer
mesh.
from aiida.plugins import WorkflowFactory
# Load via WorkflowFactory (direct imports like
# `from aiida_pythonjob_ins.workflows import ToscaFromForceConstantsWorkChain`
# also work)
ToscaFromForceConstantsWorkChain = WorkflowFactory(
"pythonjob_ins.tosca_from_force_constants"
)
results, node = run_get_node(
ToscaFromForceConstantsWorkChain,
castep_file=orm.SinglefileData(example_data("quartz.castep_bin")),
q_spacing=orm.Float(0.5), # MP-grid spacing (1/Angstrom); see the note above
spectrum={
"temperature": orm.Float(10.0), # kelvin
"energy_spacing": orm.Float(10.0), # 1/cm
"group_by": orm.List(list=["atom_symbol"]),
},
code=code,
)
print(f"WorkChain finished OK: {node.is_finished_ok}")
Written to /tmp/tmpzew25csp/euphonic_object.json
Written to /tmp/tmp4yeiavr1/euphonic_object.json
WorkChain finished OK: True
Plot the spectrum¶
The outputs are those of the delegated workflow, re-exposed as this
workflow’s own: the full ungrouped line set (components) and the grouped,
broadened spectrum.
import matplotlib.pyplot as plt
spectrum = results["spectrum"]
_, energy, energy_unit = spectrum.get_x()
lines = spectrum.get_y()
intensity_unit = lines[0][2] # shared by every line of the collection
fig, ax = plt.subplots()
for label, intensity, _ in lines:
ax.plot(energy, intensity, label=label)
ax.set_xlabel(f"Energy transfer ({energy_unit})")
ax.set_ylabel(f"Intensity ({intensity_unit})")
ax.set_title("Quartz TOSCA spectrum (by element)")
ax.legend()
fig.tight_layout()

Provenance¶
The graph shows the CASTEP read and mode-interpolation PythonJobs of this
workflow, then the nested ToscaFromModesWorkChain doing the spectrum work.
show_provenance(node, title="TOSCA-from-force-constants workflow provenance")

<Figure size 1200x789.442 with 1 Axes>
Total running time of the script: (0 minutes 11.892 seconds)