diff --git a/other/materials_designer/workflows/Introduction.ipynb b/other/materials_designer/workflows/Introduction.ipynb
new file mode 100644
index 00000000..4a4413f9
--- /dev/null
+++ b/other/materials_designer/workflows/Introduction.ipynb
@@ -0,0 +1,110 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Calculations — Contents\n",
+ "\n",
+ "This document contains links to available calculation notebooks, organized by category.\n",
+ "\n",
+ "## 1. Auxiliary\n",
+ "\n",
+ "### 1.1. Hubbard U (HP)\n",
+ "#### 1.1.1. Hubbard U parameters via HP method. *(to be added)*\n",
+ "\n",
+ "### 1.2. Parameter Convergence\n",
+ "#### 1.2.1. K-point / plane-wave cutoff / smearing convergence. *(to be added)*\n",
+ "\n",
+ "\n",
+ "## 2. Basics\n",
+ "\n",
+ "### 2.1. Total Energy\n",
+ "#### [2.1.1. Total Energy.](total_energy.ipynb)\n",
+ "\n",
+ "### 2.2. Total Energy and Post-Processing\n",
+ "#### 2.2.1. Wavefunction Amplitude / Electronic Density Mesh / Average Electrostatic Potential / LDOS. *(to be added)*\n",
+ "\n",
+ "\n",
+ "## 3. Relaxation\n",
+ "\n",
+ "### 3.1. Fixed-Cell / Variable-Cell Relaxation\n",
+ "#### 3.1.1. Fixed-cell (ionic) and variable-cell (full) relaxation. *(to be added)*\n",
+ "\n",
+ "\n",
+ "## 4. Electronic Structure\n",
+ "\n",
+ "### 4.1. Band Gap\n",
+ "#### [4.1.1. Band Gap / Band Gap+DOS (HSE).](band_gap.ipynb)\n",
+ "\n",
+ "### 4.2. Band Structure\n",
+ "#### [4.2.1. Band Structure / Band Structure+DOS / HSE / Magnetic / Spin-Orbit Coupling / DOS.](band_structure.ipynb)\n",
+ "\n",
+ "\n",
+ "## 5. Vibrational\n",
+ "\n",
+ "### 5.1. Phonons\n",
+ "#### 5.1.1. Phonon DOS and Dispersion. *(to be added)*\n",
+ "\n",
+ "\n",
+ "## 6. Thermodynamics\n",
+ "\n",
+ "### 6.1. Surface Energy\n",
+ "#### 6.1.1. Surface energy calculation. *(to be added)*\n",
+ "\n",
+ "### 6.2. Interface Energy\n",
+ "#### 6.2.1. Interface energy calculation. *(to be added)*\n",
+ "\n",
+ "### 6.3. Zero-Point Energy\n",
+ "#### 6.3.1. Zero-point energy calculation. *(to be added)*\n",
+ "\n",
+ "### 6.4. Defect Energy\n",
+ "#### 6.4.1. Defect formation energy. *(to be added)*\n",
+ "\n",
+ "### 6.5. Formation Energy\n",
+ "#### 6.5.1. Compound formation energy. *(to be added)*\n",
+ "\n",
+ "\n",
+ "## 7. Chemistry\n",
+ "\n",
+ "### 7.1. Nudged Elastic Band (NEB)\n",
+ "#### 7.1.1. NEB reaction pathway calculation. *(to be added)*\n",
+ "\n",
+ "### 7.2. HOMO-LUMO (NWChem)\n",
+ "#### 7.2.1. HOMO-LUMO gap calculation. *(to be added)*\n",
+ "\n",
+ "### 7.3. Vibrational Frequency (NWChem)\n",
+ "#### 7.3.1. Vibrational frequency calculation. *(to be added)*\n",
+ "\n",
+ "\n",
+ "## 8. Electronics\n",
+ "\n",
+ "### 8.1. Valence Band Offset\n",
+ "#### 8.1.1. Valence band offset at an interface. *(to be added)*\n",
+ "\n",
+ "### 8.2. Dielectric Tensor\n",
+ "#### 8.2.1. Dielectric tensor calculation. *(to be added)*\n",
+ "\n",
+ "\n",
+ "## 9. Custom\n",
+ "\n",
+ "### 9.1. Python / Shell\n",
+ "#### 9.1.1. Custom Python and Shell workflows. *(to be added)*\n"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "name": "python",
+ "version": "3.11.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/other/materials_designer/workflows/band_structure.ipynb b/other/materials_designer/workflows/band_structure.ipynb
new file mode 100644
index 00000000..67e59707
--- /dev/null
+++ b/other/materials_designer/workflows/band_structure.ipynb
@@ -0,0 +1,647 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0",
+ "metadata": {},
+ "source": [
+ "# Band Structure\n",
+ "\n",
+ "Calculate the electronic band structure of a material using a DFT workflow on the Mat3ra platform.\n",
+ "\n",
+ "
Usage
\n",
+ "\n",
+ "1. Set material, type of calculation and its parameters in cell 1.2. below (or use the default values).\n",
+ "1. Click \"Run\" > \"Run All\" to run all cells.\n",
+ "1. Wait for the job to complete.\n",
+ "1. Scroll down to view the result.\n",
+ "\n",
+ "## Summary\n",
+ "\n",
+ "1. Set up the environment and parameters: install packages (JupyterLite only) and configure parameters for material, workflow, compute resources, and job.\n",
+ "1. Authenticate and initialize API client: authenticate via browser, initialize the client, then select account and project.\n",
+ "1. Create material: materials are read from the `../uploads` folder — place files there manually or run a material creation notebook first. If the material is not found by name, Standata is used as a fallback. The material is then saved to the platform.\n",
+ "1. Create workflow and set its parameters: select application, load band structure workflow from Standata, optionally add relaxation or adjust model/method parameters, and save the workflow to the platform.\n",
+ "1. Configure compute: get list of clusters and create compute configuration with selected cluster, queue, and number of processors.\n",
+ "1. Create the job with material and workflow configuration: assemble the job from material, workflow, project, and compute configuration.\n",
+ "1. Submit the job and monitor the status: submit the job and wait for completion.\n",
+ "1. Retrieve results: get and display the band structure."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1",
+ "metadata": {},
+ "source": [
+ "## 1. Set up the environment and parameters\n",
+ "### 1.1. Install packages (JupyterLite)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import sys\n",
+ "\n",
+ "if sys.platform == \"emscripten\":\n",
+ " import micropip\n",
+ "\n",
+ " await micropip.install(\"mat3ra-api-examples\", deps=False)\n",
+ " await micropip.install(\"mat3ra-utils\")\n",
+ " from mat3ra.utils.jupyterlite.packages import install_packages\n",
+ "\n",
+ " await install_packages(\"api_examples\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3",
+ "metadata": {},
+ "source": [
+ "### 1.2. Set parameters and configurations for the workflow and job\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from datetime import datetime\n",
+ "from mat3ra.ide.compute import QueueName\n",
+ "\n",
+ "# 2. Auth and organization parameters\n",
+ "# Set organization name to use it as the owner, otherwise your personal account is used\n",
+ "ORGANIZATION_NAME = None\n",
+ "\n",
+ "# 3. Material parameters\n",
+ "FOLDER = \"../uploads\"\n",
+ "MATERIAL_NAME = \"Silicon\" # Name of the material to load from local file or Standata\n",
+ "\n",
+ "# 4. Workflow parameters\n",
+ "# Options: \"band_structure\" / \"band_structure_dos\" / \"band_structure_hse\" /\n",
+ "# \"band_structure_magn\" / \"band_structure_soc\" / \"dos\"\n",
+ "CALCULATION_TYPE = \"band_structure\"\n",
+ "\n",
+ "APPLICATION_NAME = \"espresso\" # Specify application name (e.g., \"espresso\", \"vasp\")\n",
+ "ADD_RELAXATION = None # Whether to add relaxation subworkflow as first unit\n",
+ "\n",
+ "WORKFLOW_SEARCH_TERM = f\"{CALCULATION_TYPE}.json\"\n",
+ "MY_WORKFLOW_NAME = CALCULATION_TYPE.replace(\"_\", \" \").title() + (\" (relax)\" if ADD_RELAXATION else \"\")\n",
+ "\n",
+ "# K-grid for SCF and relaxation steps (if not set, KPPRA is used by default)\n",
+ "RELAXATION_KGRID = None # e.g., [4, 4, 4]\n",
+ "SCF_KGRID = None # e.g., [4, 4, 4]\n",
+ "\n",
+ "# K-grid for NSCF step — used by \"band_structure_dos\" and \"dos\"\n",
+ "NSCF_KGRID = None # e.g., [8, 8, 8]\n",
+ "\n",
+ "# K-path for band structure (if not set, workflow default is used)\n",
+ "# Example for FCC: [{\"point\": \"L\", \"steps\": 20}, {\"point\": \"Г\", \"steps\": 20}, {\"point\": \"X\", \"steps\": 20}]\n",
+ "# Not used by \"dos\" or \"band_structure_hse\" (QE EXX limitation: see cell 4.3.3 for details)\n",
+ "KPATH = None\n",
+ "\n",
+ "ECUTWFC = 40 # plane-wave cutoff energies in Ry (if None, defaults are used)\n",
+ "ECUTRHO = 200 # density cutoff, typically 4-8x ECUTWFC depending on pseudopotentials (if None, defaults are used)\n",
+ "\n",
+ "# Initial magnetic moment per atomic species — used by \"band_structure_magn\"\n",
+ "# e.g., {\"Fe\": 4.0, \"O\": 0.0}\n",
+ "STARTING_MAGNETIZATION = None\n",
+ "\n",
+ "# 5. Compute parameters\n",
+ "CLUSTER_NAME = None # specify full or partial name i.e. \"cluster-001\" to select\n",
+ "QUEUE_NAME = QueueName.D\n",
+ "PPN = 1\n",
+ "\n",
+ "# 6. Job parameters\n",
+ "timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M\")\n",
+ "POLL_INTERVAL = 30 # seconds\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5",
+ "metadata": {},
+ "source": [
+ "## 2. Authenticate and initialize API client\n",
+ "### 2.1. Authenticate\n",
+ "Authenticate in the browser and have credentials stored in environment variable \"OIDC_ACCESS_TOKEN\"."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from utils.auth import authenticate\n",
+ "\n",
+ "await authenticate()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7",
+ "metadata": {},
+ "source": [
+ "### 2.2. Initialize API Client"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from mat3ra.api_client import APIClient\n",
+ "\n",
+ "client = APIClient.authenticate()\n",
+ "client"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9",
+ "metadata": {},
+ "source": [
+ "### 2.3. Select account to work under"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "client.list_accounts()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "11",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "selected_account = client.my_account\n",
+ "\n",
+ "if ORGANIZATION_NAME:\n",
+ " selected_account = client.get_account(name=ORGANIZATION_NAME)\n",
+ "\n",
+ "ACCOUNT_ID = selected_account.id\n",
+ "print(f\"✅ Selected account ID: {ACCOUNT_ID}, name: {selected_account.name}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "12",
+ "metadata": {},
+ "source": [
+ "### 2.4. Select project"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "projects = client.projects.list({\"isDefault\": True, \"owner._id\": ACCOUNT_ID})\n",
+ "project_id = projects[0][\"_id\"]\n",
+ "print(f\"✅ Using project: {projects[0]['name']} ({project_id})\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14",
+ "metadata": {},
+ "source": [
+ "## 3. Create material\n",
+ "### 3.1. Load material from local file (or Standata)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "15",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from mat3ra.made.material import Material\n",
+ "from mat3ra.standata.materials import Materials\n",
+ "from utils.visualize import visualize_materials as visualize\n",
+ "from utils.jupyterlite import load_material_from_folder\n",
+ "\n",
+ "material = load_material_from_folder(FOLDER, MATERIAL_NAME) or Material.create(\n",
+ " Materials.get_by_name_first_match(MATERIAL_NAME))\n",
+ "\n",
+ "visualize(material)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "16",
+ "metadata": {},
+ "source": [
+ "### 3.2. Save material to the platform"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "17",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from utils.api import get_or_create_material\n",
+ "\n",
+ "saved_material_response = get_or_create_material(client, material, ACCOUNT_ID)\n",
+ "saved_material = Material.create(saved_material_response)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "18",
+ "metadata": {},
+ "source": [
+ "## 4. Create workflow and set its parameters\n",
+ "### 4.1. Get list of applications and select one"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "19",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from mat3ra.standata.applications import ApplicationStandata\n",
+ "from mat3ra.ade.application import Application\n",
+ "\n",
+ "app_config = ApplicationStandata.get_by_name_first_match(APPLICATION_NAME)\n",
+ "app = Application(**app_config)\n",
+ "print(f\"Using application: {app.name}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "20",
+ "metadata": {},
+ "source": [
+ "### 4.2. Create workflow from standard workflows and preview it"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from mat3ra.standata.workflows import WorkflowStandata\n",
+ "from mat3ra.wode.workflows import Workflow\n",
+ "from utils.visualize import visualize_workflow\n",
+ "\n",
+ "workflow_config = WorkflowStandata.filter_by_application(app.name).get_by_name_first_match(WORKFLOW_SEARCH_TERM)\n",
+ "workflow = Workflow.create(workflow_config)\n",
+ "workflow.name = MY_WORKFLOW_NAME\n",
+ "\n",
+ "visualize_workflow(workflow)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "22",
+ "metadata": {},
+ "source": [
+ "### 4.3. Modify workflow (Optional)\n",
+ "#### 4.3.1. Add relaxation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if ADD_RELAXATION:\n",
+ " workflow.add_relaxation()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "24",
+ "metadata": {},
+ "source": [
+ "#### 4.3.2. Modify model and method parameters (Optional)\n",
+ "Uncomment the code below and adjust selection of model parameters as needed."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "25",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Most variants use the model/method embedded in their standata definition:\n",
+ "# - \"band_structure_hse\" → hybrid DFT (HSE06), ultrasoft pseudopotentials\n",
+ "# - \"band_structure_soc\" → norm-conserving fully-relativistic pseudopotentials (nc-fr)\n",
+ "# - all others → GGA/LDA with default pseudopotentials\n",
+ "#\n",
+ "# Uncomment and adjust below to override the model for any variant:\n",
+ "#\n",
+ "# from mat3ra.mode.model import Model\n",
+ "# from mat3ra.standata.model_tree import ModelTreeStandata\n",
+ "#\n",
+ "# model_config = ModelTreeStandata.get_model_by_parameters(\n",
+ "# type=\"dft\",\n",
+ "# subtype=\"gga\", # e.g., \"lda\", \"gga\", \"hybrid\"\n",
+ "# functional=\"pbe\" # e.g., \"pz\" (LDA), \"pbe\" (GGA), \"hse06\" (HSE)\n",
+ "# )\n",
+ "# model_config[\"method\"] = {\"type\": \"pseudopotential\", \"subtype\": \"us\"} # e.g., \"us\", \"nc\", \"nc-fr\"\n",
+ "# model = Model.create(model_config)\n",
+ "#\n",
+ "# for subworkflow in workflow.subworkflows:\n",
+ "# subworkflow.model = model\n",
+ "#\n",
+ "# visualize_workflow(workflow)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "26",
+ "metadata": {},
+ "source": [
+ "#### 4.3.3. Modify important settings\n",
+ "Set k-grid, k-path, and energy cutoffs."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "27",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from mat3ra.wode.context.providers import PlanewaveCutoffsContextProvider, PointsGridDataProvider, \\\n",
+ " PointsPathDataProvider\n",
+ "\n",
+ "# For HSE, subworkflows are: [pw_scf, espresso_extract_kpoints, band_structure_hse]\n",
+ "# bs_subworkflow is used for NSCF and STARTING_MAGNETIZATION lookups on the first BS subworkflow\n",
+ "bs_subworkflow = workflow.subworkflows[1 if ADD_RELAXATION else 0]\n",
+ "\n",
+ "if RELAXATION_KGRID is not None and ADD_RELAXATION:\n",
+ " unit = workflow.subworkflows[0].get_unit_by_name(name_regex=\"relax\")\n",
+ " unit.add_context(PointsGridDataProvider(dimensions=RELAXATION_KGRID, isEdited=True).yield_data())\n",
+ " workflow.subworkflows[0].set_unit(unit)\n",
+ "\n",
+ "# SCF k-grid for standard variants; also sets qgrid (nqx1/2/3) for HSE — the template reads\n",
+ "# qgrid.dimensions, not kgrid, so both contexts are needed on pw_scf_bands_hse.\n",
+ "if SCF_KGRID is not None:\n",
+ " for unit_name in [\"pw_scf\", \"pw_scf_magn\", \"pw_scf_soc\"]:\n",
+ " for swf in workflow.subworkflows:\n",
+ " unit = swf.get_unit_by_name(name=unit_name)\n",
+ " if unit:\n",
+ " unit.add_context(PointsGridDataProvider(dimensions=SCF_KGRID, isEdited=True).yield_data())\n",
+ " swf.set_unit(unit)\n",
+ " for swf in workflow.subworkflows:\n",
+ " unit = swf.get_unit_by_name(name=\"pw_scf_bands_hse\")\n",
+ " if unit:\n",
+ " unit.add_context(PointsGridDataProvider(dimensions=SCF_KGRID, isEdited=True).yield_data())\n",
+ " unit.add_context(PointsGridDataProvider(name=\"qgrid\", dimensions=SCF_KGRID, isEdited=True).yield_data())\n",
+ " swf.set_unit(unit)\n",
+ "\n",
+ "# KPATH: applied to pw_bands variants; NOT applied to pw_scf_bands_hse (QE EXX limitation).\n",
+ "if KPATH is not None:\n",
+ " for unit_name in [\"pw_bands\", \"pw_bands_magn\", \"pw_bands_soc\"]:\n",
+ " for swf in workflow.subworkflows:\n",
+ " unit = swf.get_unit_by_name(name=unit_name)\n",
+ " if unit:\n",
+ " unit.add_context(PointsPathDataProvider(path=KPATH, isEdited=True).yield_data())\n",
+ " swf.set_unit(unit)\n",
+ "\n",
+ "# NSCF_KGRID: used by \"band_structure_dos\" and \"dos\"\n",
+ "if NSCF_KGRID is not None:\n",
+ " unit = bs_subworkflow.get_unit_by_name(name=\"pw_nscf\")\n",
+ " if unit:\n",
+ " unit.add_context(PointsGridDataProvider(dimensions=NSCF_KGRID, isEdited=True).yield_data())\n",
+ " bs_subworkflow.set_unit(unit)\n",
+ "\n",
+ "if ECUTWFC is not None:\n",
+ " cutoffs_context = PlanewaveCutoffsContextProvider(wavefunction=ECUTWFC, density=ECUTRHO, isEdited=True).yield_data()\n",
+ " for unit_name in [\"pw_vc-relax\", \"pw_scf\", \"pw_scf_magn\", \"pw_scf_soc\", \"pw_scf_bands_hse\", \"pw_bands\",\n",
+ " \"pw_bands_magn\", \"pw_bands_soc\"]:\n",
+ " for swf in workflow.subworkflows:\n",
+ " unit = swf.get_unit_by_name(name=unit_name)\n",
+ " if unit:\n",
+ " unit.add_context(cutoffs_context)\n",
+ " swf.set_unit(unit)\n",
+ "\n",
+ "# STARTING_MAGNETIZATION: used by \"band_structure_magn\"\n",
+ "if STARTING_MAGNETIZATION is not None:\n",
+ " unit = bs_subworkflow.get_unit_by_name(name=\"pw_scf_magn\")\n",
+ " if unit:\n",
+ " magn_lines = \"\\n\".join(\n",
+ " f\" starting_magnetization({i + 1}) = {val}\"\n",
+ " for i, val in enumerate(STARTING_MAGNETIZATION.values())\n",
+ " )\n",
+ " existing = unit.input[0][\"content\"] if unit.input else \"\"\n",
+ " unit.input = [{\"name\": unit.input[0][\"name\"] if unit.input else \"pw_scf_magn.in\",\n",
+ " \"content\": existing.replace(\"/\", f\"{magn_lines}\\n/\")}]\n",
+ " bs_subworkflow.set_unit(unit)\n",
+ "\n",
+ "visualize_workflow(workflow)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "28",
+ "metadata": {},
+ "source": [
+ "### 4.4. Save workflow to collection"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "29",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from utils.generic import dict_to_namespace\n",
+ "from utils.api import get_or_create_workflow\n",
+ "\n",
+ "saved_workflow_response = get_or_create_workflow(client, workflow, ACCOUNT_ID)\n",
+ "saved_workflow = Workflow.create(saved_workflow_response)\n",
+ "print(f\"Workflow ID: {saved_workflow.id}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "30",
+ "metadata": {},
+ "source": [
+ "## 5. Create the compute configuration\n",
+ "### 5.1. Get list of clusters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "31",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "clusters = client.clusters.list()\n",
+ "print(f\"Available clusters: {[c['hostname'] for c in clusters]}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "32",
+ "metadata": {},
+ "source": [
+ "### 5.2. Create compute configuration for the job"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "33",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from mat3ra.ide.compute import Compute\n",
+ "\n",
+ "# Select cluster: use specified name if provided, otherwise use first available\n",
+ "if CLUSTER_NAME:\n",
+ " cluster = next((c for c in clusters if CLUSTER_NAME in c[\"hostname\"]), None)\n",
+ "else:\n",
+ " cluster = clusters[0]\n",
+ "\n",
+ "compute = Compute(\n",
+ " cluster=cluster,\n",
+ " queue=QUEUE_NAME,\n",
+ " ppn=PPN\n",
+ ")\n",
+ "print(f\"Using cluster: {compute.cluster.hostname}, queue: {QUEUE_NAME}, ppn: {PPN}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "34",
+ "metadata": {},
+ "source": [
+ "## 6. Create the job with material and workflow configuration\n",
+ "### 6.1. Create job"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "35",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from utils.api import create_job\n",
+ "from utils.visualize import display_JSON\n",
+ "\n",
+ "print(f\"Material: {saved_material.id}\")\n",
+ "print(f\"Workflow: {saved_workflow.id}\")\n",
+ "print(f\"Project: {project_id}\")\n",
+ "\n",
+ "job_name = MY_WORKFLOW_NAME + \" \" + saved_material.formula + \" \" + timestamp\n",
+ "job_response = create_job(\n",
+ " api_client=client,\n",
+ " materials=[saved_material],\n",
+ " workflow=workflow,\n",
+ " project_id=project_id,\n",
+ " owner_id=ACCOUNT_ID,\n",
+ " prefix=job_name,\n",
+ " compute=compute.to_dict()\n",
+ ")\n",
+ "\n",
+ "job = dict_to_namespace(job_response)\n",
+ "job_id = job._id\n",
+ "print(\"✅ Job created successfully!\")\n",
+ "print(f\"Job ID: {job_id}\")\n",
+ "display_JSON(job_response)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "36",
+ "metadata": {},
+ "source": [
+ "## 7. Submit the job and monitor the status"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "37",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "client.jobs.submit(job_id)\n",
+ "print(f\"✅ Job {job_id} submitted successfully!\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "38",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from utils.api import wait_for_jobs_to_finish_async\n",
+ "\n",
+ "await wait_for_jobs_to_finish_async(client.jobs, [job_id], poll_interval=POLL_INTERVAL)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "39",
+ "metadata": {},
+ "source": [
+ "## 8. Retrieve results"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "40",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from utils.visualize import visualize_properties\n",
+ "\n",
+ "property_data = client.properties.get_for_job(job_id)\n",
+ "visualize_properties(property_data, title=\"Band Structure\")\n"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "name": "python",
+ "version": "3.11.2"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}