From b4511c1620c997c9d3474e6237cf039cb0d51d61 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Thu, 12 Mar 2026 12:40:13 -0700 Subject: [PATCH 1/4] update: sync with BS NB --- .../workflows/band_gap.ipynb | 497 ++++++++---------- 1 file changed, 223 insertions(+), 274 deletions(-) diff --git a/other/materials_designer/workflows/band_gap.ipynb b/other/materials_designer/workflows/band_gap.ipynb index 055199b9..081d920a 100644 --- a/other/materials_designer/workflows/band_gap.ipynb +++ b/other/materials_designer/workflows/band_gap.ipynb @@ -5,19 +5,27 @@ "id": "0", "metadata": {}, "source": [ - "# Bandgap Workflow Example\n", + "# Band Gap\n", "\n", - "This notebook demonstrates how to build and run a bandgap calculation workflow for materials using the Mat3ra API. The example uses Silicon as the target material and shows how to configure DFT calculations with custom model parameters and k-grids.\n", + "Calculate the electronic band gap of a material using a DFT workflow on the Mat3ra platform.\n", "\n", - "## Process Overview\n", - "1. Set up environment and parameters\n", - "2. Authenticate and initialize API client\n", - "3. Create and save material to the platform\n", - "4. Create workflow configuration with relaxation and band structure calculations\n", - "5. Configure compute resources\n", - "6. Create and submit job\n", - "7. Monitor job execution\n", - "8. Retrieve and display bandgap results" + "

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 gap 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 gap." ] }, { @@ -25,7 +33,8 @@ "id": "1", "metadata": {}, "source": [ - "## 1. Set up the environment and parameters" + "## 1. Set up the environment and parameters\n", + "### 1.1. Install packages (JupyterLite)" ] }, { @@ -35,102 +44,120 @@ "metadata": {}, "outputs": [], "source": [ - "from datetime import datetime\n", - "\n", - "# Material parameters\n", - "FOLDER = \"../uploads\"\n", - "MATERIAL_NAME = \"Silicon\"\n", - "\n", - "# Workflow parameters\n", - "WORKFLOW_SEARCH_TERM = \"band_gap.json\"\n", - "MY_WORKFLOW_NAME = \"Band Gap Calculation Workflow\"\n", - "ADD_RELAXATION = True # Whether to add relaxation subworkflow before band structure calculation\n", - "\n", - "# Model parameters\n", - "MODEL_TYPE = \"dft\"\n", - "MODEL_SUBTYPE = \"lda\" # or \"gga\"\n", - "MODEL_FUNCTIONAL = \"pz\" # for lda: pz, for gga: pbe\n", - "\n", - "# K-grid parameters\n", - "RELAXATION_KGRID = [1, 2, 3] # k-grid for relaxation\n", - "SCF_KGRID = [1, 1, 1] # k-grid for SCF calculation\n", - "NSCF_KGRID = [1, 1, 1] # k-grid for NSCF calculation\n", + "import sys\n", "\n", - "# Job parameters\n", - "timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M\")\n", - "JOB_NAME = f\"Band Gap {timestamp}\"\n", + "if sys.platform == \"emscripten\":\n", + " import micropip\n", "\n", - "POLL_INTERVAL = 30 # seconds\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", - "# Set organization name to use it as the owner for materials and job created here, otherwise your personal account is used\n", - "ORGANIZATION_NAME = None\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" ] }, { "cell_type": "code", "execution_count": null, - "id": "3", + "id": "4", "metadata": {}, "outputs": [], "source": [ - "import sys\n", + "from datetime import datetime\n", + "from mat3ra.ide.compute import QueueName\n", "\n", - "if sys.platform == \"emscripten\":\n", - " import micropip\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", - " await micropip.install(\"mat3ra-api-examples\", deps=False)\n", - " await micropip.install(\"mat3ra-utils\")\n", - " from mat3ra.utils.jupyterlite.packages import install_packages\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_gap\" / \"band_gap_dos_hse\"\n", + "CALCULATION_TYPE = \"band_gap\"\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", - " await install_packages(\"api_examples\")" + "# 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_gap_dos_hse\"\n", + "NSCF_KGRID = None # e.g., [8, 8, 8]\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", + "# 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" ] }, { "cell_type": "markdown", - "id": "4", + "id": "5", "metadata": {}, "source": [ "## 2. Authenticate and initialize API client\n", - "### 2.1. Upon running of this cell, the browser with Mat3ra CLI login page will open." + "### 2.1. Authenticate\n", + "Authenticate in the browser and have credentials stored in environment variables." ] }, { "cell_type": "code", "execution_count": null, - "id": "5", + "id": "6", "metadata": {}, "outputs": [], "source": [ "from utils.auth import authenticate\n", "\n", - "# Authenticate and have credentials stored in environment variables\n", "await authenticate()" ] }, { "cell_type": "markdown", - "id": "6", + "id": "7", "metadata": {}, "source": [ - "### 2.2. Initialize API client\n", - "Authorization is done via environment variables, where token is stored after authentication." + "### 2.2. Initialize API Client" ] }, { "cell_type": "code", "execution_count": null, - "id": "7", + "id": "8", "metadata": {}, "outputs": [], "source": [ "from mat3ra.api_client import APIClient\n", "\n", - "client = APIClient.authenticate()" + "client = APIClient.authenticate()\n", + "client" ] }, { "cell_type": "markdown", - "id": "8", + "id": "9", "metadata": {}, "source": [ "### 2.3. Select account to work under\n", @@ -140,7 +167,7 @@ { "cell_type": "code", "execution_count": null, - "id": "9", + "id": "10", "metadata": {}, "outputs": [], "source": [ @@ -150,7 +177,7 @@ { "cell_type": "code", "execution_count": null, - "id": "10", + "id": "11", "metadata": {}, "outputs": [], "source": [ @@ -165,106 +192,94 @@ }, { "cell_type": "markdown", - "id": "11", + "id": "12", "metadata": {}, "source": [ - "## 3. Create material\n", - "### 3.1. Load material from local file (or Standata)" + "### 2.4. Select project" ] }, { "cell_type": "code", "execution_count": null, - "id": "12", + "id": "13", "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)" + "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": "13", + "id": "14", "metadata": {}, "source": [ - "### 3.2. Save material to the platform" + "## 3. Create material\n", + "### 3.1. Load material from local file (or Standata)" ] }, { "cell_type": "code", "execution_count": null, - "id": "14", + "id": "15", "metadata": {}, "outputs": [], "source": [ - "from utils.generic import dict_to_namespace\n", + "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.basis.set_labels_from_list([])\n", - "saved_material_response = client.materials.create(material.to_dict(), owner_id=ACCOUNT_ID)\n", - "saved_material = dict_to_namespace(saved_material_response)\n", - "print(f\"✅ Material created: {saved_material._id}\")" + "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": "15", - "metadata": { - "tags": [] - }, + "id": "16", + "metadata": {}, "source": [ - "### 3.3. Get material id" + "### 3.2. Save material to the platform" ] }, { "cell_type": "code", "execution_count": null, - "id": "16", + "id": "17", "metadata": {}, "outputs": [], "source": [ - "print(\"Material ID:\", saved_material._id)" + "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": "17", + "id": "18", "metadata": {}, "source": [ - "## 5. Create workflow and set its parameters\n", - "### 5.1. Get list of applications and select one" + "## 4. Create workflow and set its parameters\n", + "### 4.1. Get list of applications and select one" ] }, { "cell_type": "code", "execution_count": null, - "id": "18", + "id": "19", "metadata": {}, "outputs": [], "source": [ "from mat3ra.standata.applications import ApplicationStandata\n", "from mat3ra.ade.application import Application\n", "\n", - "apps_list = ApplicationStandata.list_all()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "19", - "metadata": {}, - "outputs": [], - "source": [ - "app_config = ApplicationStandata.get_by_name_first_match(\"espresso\")\n", + "app_config = ApplicationStandata.get_by_name_first_match(APPLICATION_NAME)\n", "app = Application(**app_config)\n", - "app.name" + "print(f\"Using application: {app.name}\")" ] }, { @@ -272,7 +287,7 @@ "id": "20", "metadata": {}, "source": [ - "### 5.2. Create workflow from standard workflows and preview it" + "### 4.2. Create workflow from standard workflows and preview it" ] }, { @@ -288,6 +303,7 @@ "\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)" ] @@ -297,7 +313,8 @@ "id": "22", "metadata": {}, "source": [ - "### 5.3. Add relaxation subworkflow" + "### 4.3. Modify workflow (Optional)\n", + "#### 4.3.1. Add relaxation" ] }, { @@ -307,12 +324,8 @@ "metadata": {}, "outputs": [], "source": [ - "from utils.visualize import visualize_workflow\n", - "\n", "if ADD_RELAXATION:\n", - " workflow.add_relaxation()\n", - " # Relaxation subworkflow is added as the first subworkflow\n", - " visualize_workflow(workflow)" + " workflow.add_relaxation()\n" ] }, { @@ -320,8 +333,8 @@ "id": "24", "metadata": {}, "source": [ - "### 5.4. Change subworkflow details (Model subtype)\n", - "#### 5.4.1. Get available model subtypes and functionals" + "#### 4.3.2. Modify model and method parameters (Optional)\n", + "Uncomment the code below and adjust selected model and method (e.g. LDA vs GGA)." ] }, { @@ -331,11 +344,23 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.standata.model_tree import ModelTreeStandata\n", - "\n", - "# Change model subtype for relaxation subworkflow\n", - "subtypes = ModelTreeStandata.get_subtypes_by_model_type(MODEL_TYPE)\n", - "functionals = ModelTreeStandata.get_functionals_by_subtype(MODEL_TYPE, MODEL_SUBTYPE)" + "# 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\"\n", + "# functional=\"pbe\" # e.g., \"pz\" (LDA), \"pbe\" (GGA)\n", + "# )\n", + "# model_config[\"method\"] = {\"type\": \"pseudopotential\", \"subtype\": \"us\"} # e.g., \"us\", \"nc\"\n", + "# model = Model.create(model_config)\n", + "#\n", + "# for subworkflow in workflow.subworkflows:\n", + "# subworkflow.model = model\n", + "#\n", + "# visualize_workflow(workflow)" ] }, { @@ -343,7 +368,8 @@ "id": "26", "metadata": {}, "source": [ - "#### 5.4.2. Modify model in subworkflow units" + "#### 4.3.3. Modify important settings\n", + "Set k-grid and energy cutoffs." ] }, { @@ -353,28 +379,38 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.mode import Model\n", - "\n", - "RELAXATION_SWF_INDEX = 0 if ADD_RELAXATION else None\n", - "BAND_GAP_SWF_INDEX = 1 if ADD_RELAXATION else 0\n", - "\n", - "swf_0 = workflow.subworkflows[RELAXATION_SWF_INDEX] if ADD_RELAXATION else None\n", - "swf_1 = workflow.subworkflows[BAND_GAP_SWF_INDEX]\n", + "from mat3ra.wode.context.providers import PlanewaveCutoffsContextProvider, PointsGridDataProvider\n", + "\n", + "bg_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", + "if SCF_KGRID is not None:\n", + " unit = bg_subworkflow.get_unit_by_name(name=\"pw_scf\")\n", + " if unit:\n", + " unit.add_context(PointsGridDataProvider(dimensions=SCF_KGRID, isEdited=True).yield_data())\n", + " bg_subworkflow.set_unit(unit)\n", + "\n", + "# NSCF_KGRID: used by \"band_gap_dos_hse\"\n", + "if NSCF_KGRID is not None:\n", + " unit = bg_subworkflow.get_unit_by_name(name=\"pw_nscf\")\n", + " if unit:\n", + " unit.add_context(PointsGridDataProvider(dimensions=NSCF_KGRID, isEdited=True).yield_data())\n", + " bg_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_nscf\"]:\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", - "model_config = ModelTreeStandata.get_model_by_parameters(\n", - " type=MODEL_TYPE,\n", - " subtype=MODEL_SUBTYPE,\n", - " functional={\"slug\": MODEL_FUNCTIONAL},\n", - ")\n", - "\n", - "method_config = {\"type\": \"pseudopotential\", \"subtype\": \"us\"}\n", - "model_config[\"method\"] = method_config\n", - "\n", - "model = Model.create(model_config)\n", - "if ADD_RELAXATION:\n", - " swf_0.model = model\n", - "swf_1.model = model\n", - "print(model)\n" + "visualize_workflow(workflow)" ] }, { @@ -382,8 +418,7 @@ "id": "28", "metadata": {}, "source": [ - "### 5.5. Modify k-grid in subworkflow units\n", - "#### 5.5.1. Get k-grid context" + "### 4.4. Save workflow to collection" ] }, { @@ -393,11 +428,12 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.wode.context.providers import PointsGridDataProvider\n", + "from utils.generic import dict_to_namespace\n", + "from utils.api import get_or_create_workflow\n", "\n", - "new_context_relax = PointsGridDataProvider(dimensions=RELAXATION_KGRID, isEdited=True).yield_data() if ADD_RELAXATION else None\n", - "new_context_scf = PointsGridDataProvider(dimensions=SCF_KGRID, isEdited=True).yield_data()\n", - "new_context_nscf = PointsGridDataProvider(dimensions=NSCF_KGRID, isEdited=True).yield_data()" + "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}\")" ] }, { @@ -405,7 +441,8 @@ "id": "30", "metadata": {}, "source": [ - "#### 5.5.3. Modify workflow units with new context" + "## 5. Create the compute configuration\n", + "### 5.1. Get list of clusters" ] }, { @@ -415,26 +452,8 @@ "metadata": {}, "outputs": [], "source": [ - "# Get workflow's specific unit that needs to be modified\n", - "if ADD_RELAXATION:\n", - " relaxation_subworkflow = workflow.subworkflows[RELAXATION_SWF_INDEX]\n", - " unit_to_modify_relax = relaxation_subworkflow.get_unit_by_name(name_regex=\"relax\")\n", - " unit_to_modify_relax.add_context(new_context_relax)\n", - " # Set the modified unit back to the workflow\n", - " # Option 1: direct set by unit object, replacing the existing one\n", - " relaxation_subworkflow.set_unit(unit_to_modify_relax)\n", - "\n", - "band_gap_subworkflow = workflow.subworkflows[BAND_GAP_SWF_INDEX]\n", - "unit_to_modify_scf = band_gap_subworkflow.get_unit_by_name(name=\"pw_scf\")\n", - "unit_to_modify_scf.add_context(new_context_scf)\n", - "unit_to_modify_nscf = band_gap_subworkflow.get_unit_by_name(name=\"pw_nscf\")\n", - "unit_to_modify_nscf.add_context(new_context_nscf)\n", - "\n", - "# Option 2: set by unit flowchart id and new unit object\n", - "band_gap_subworkflow.set_unit(unit_flowchart_id=unit_to_modify_scf.flowchart_id, new_unit=unit_to_modify_scf)\n", - "band_gap_subworkflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)\n", - "workflow.name = workflow.name + \" (custom k-grids)\"\n", - "visualize_workflow(workflow)" + "clusters = client.clusters.list()\n", + "print(f\"Available clusters: {[c['hostname'] for c in clusters]}\")" ] }, { @@ -442,7 +461,7 @@ "id": "32", "metadata": {}, "source": [ - "### 5.6. Save workflow to collection" + "### 5.2. Create compute configuration for the job" ] }, { @@ -452,140 +471,86 @@ "metadata": {}, "outputs": [], "source": [ - "workflow_dict = workflow.to_dict()\n", + "from mat3ra.ide.compute import Compute\n", "\n", - "saved_workflow_response = client.workflows.create(workflow_dict, owner_id=ACCOUNT_ID)\n", - "\n", - "saved_workflow = dict_to_namespace(saved_workflow_response)\n", - "print(f\"✅ Workflow created: {saved_workflow._id}\")" - ] - }, - { - "cell_type": "markdown", - "id": "34", - "metadata": {}, - "source": [ - "## 6. Create the compute configuration\n", - "### 6.1. Get list of clusters" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "35", - "metadata": {}, - "outputs": [], - "source": [ - "clusters = client.clusters.list()\n", - "clusters" - ] - }, - { - "cell_type": "markdown", - "id": "36", - "metadata": {}, - "source": [ - "### 6.2. Create compute configuration for the job" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "37", - "metadata": {}, - "outputs": [], - "source": [ - "from mat3ra.ide.compute import Compute, QueueName\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", - "cluster = clusters[0]\n", "compute = Compute(\n", " cluster=cluster,\n", - " queue=QueueName.D,\n", - " ppn=1\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "38", - "metadata": {}, - "source": [ - "## 7. Create the job with material and workflow configuration\n", - "### 7.1. Get default project id" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "39", - "metadata": {}, - "outputs": [], - "source": [ - "projects = client.projects.list({\"isDefault\": True, \"owner._id\": ACCOUNT_ID})\n", - "project_id = projects[0][\"_id\"]\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": "40", + "id": "34", "metadata": {}, "source": [ - "### 7.2. Create job" + "## 6. Create the job with material and workflow configuration\n", + "### 6.1. Create job" ] }, { "cell_type": "code", "execution_count": null, - "id": "41", + "id": "35", "metadata": {}, "outputs": [], "source": [ + "from utils.api import create_job\n", "from utils.visualize import display_JSON\n", "\n", - "material_from_collection = client.materials.get(saved_material._id)\n", - "\n", - "print(f\"📦 Material: {material_from_collection['_id']}\")\n", - "print(f\"📦 Workflow: {saved_workflow._id}\")\n", - "print(f\"📦 Project: {project_id}\")\n", + "print(f\"Material: {saved_material.id}\")\n", + "print(f\"Workflow: {saved_workflow.id}\")\n", + "print(f\"Project: {project_id}\")\n", "\n", - "job_response = client.jobs.create_by_ids(\n", - " materials=[vars(saved_material)],\n", - " workflow_id=saved_workflow._id,\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", - " prefix=JOB_NAME,\n", " owner_id=ACCOUNT_ID,\n", - " compute=compute.to_dict(),\n", + " prefix=job_name,\n", + " compute=compute.to_dict()\n", ")\n", "\n", - "job_dict = job_response[0]\n", - "job = dict_to_namespace(job_dict)\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": "42", + "id": "36", "metadata": {}, "source": [ - "## 8. Submit the job and monitor the status" + "## 7. Submit the job and monitor the status" ] }, { "cell_type": "code", "execution_count": null, - "id": "43", + "id": "37", "metadata": {}, "outputs": [], "source": [ - "client.jobs.submit(job_id)" + "client.jobs.submit(job_id)\n", + "print(f\"✅ Job {job_id} submitted successfully!\")" ] }, { "cell_type": "code", "execution_count": null, - "id": "44", + "id": "38", "metadata": {}, "outputs": [], "source": [ @@ -596,16 +561,16 @@ }, { "cell_type": "markdown", - "id": "45", + "id": "39", "metadata": {}, "source": [ - "## 9. Retrieve results" + "## 8. Retrieve results" ] }, { "cell_type": "code", "execution_count": null, - "id": "46", + "id": "40", "metadata": {}, "outputs": [], "source": [ @@ -613,34 +578,18 @@ "from mat3ra.prode import PropertyName\n", "\n", "band_gaps_property = client.properties.get_for_job(job_id, property_name=PropertyName.non_scalar.band_gaps)\n", - "visualize_properties(band_gaps_property, title=\"Band Gaps\")" + "visualize_properties(band_gaps_property, title=\"Band Gap\")" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "47", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": ".venv-3.11.2 (3.11.2)", + "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", "version": "3.11.2" } }, From 588d719047db73c97f34348b5fb781c3eacd343b Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Thu, 12 Mar 2026 12:53:05 -0700 Subject: [PATCH 2/4] update: remove labels --- other/materials_designer/workflows/band_gap.ipynb | 12 +++++++----- .../workflows/band_structure.ipynb | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/other/materials_designer/workflows/band_gap.ipynb b/other/materials_designer/workflows/band_gap.ipynb index 081d920a..3e5178c1 100644 --- a/other/materials_designer/workflows/band_gap.ipynb +++ b/other/materials_designer/workflows/band_gap.ipynb @@ -254,6 +254,7 @@ "source": [ "from utils.api import get_or_create_material\n", "\n", + "material.basis.set_labels_from_list([])\n", "saved_material_response = get_or_create_material(client, material, ACCOUNT_ID)\n", "saved_material = Material.create(saved_material_response)" ] @@ -389,10 +390,11 @@ " workflow.subworkflows[0].set_unit(unit)\n", "\n", "if SCF_KGRID is not None:\n", - " unit = bg_subworkflow.get_unit_by_name(name=\"pw_scf\")\n", - " if unit:\n", - " unit.add_context(PointsGridDataProvider(dimensions=SCF_KGRID, isEdited=True).yield_data())\n", - " bg_subworkflow.set_unit(unit)\n", + " for unit_name in [\"pw_scf\", \"pw_scf_hse\"]:\n", + " unit = bg_subworkflow.get_unit_by_name(name=unit_name)\n", + " if unit:\n", + " unit.add_context(PointsGridDataProvider(dimensions=SCF_KGRID, isEdited=True).yield_data())\n", + " bg_subworkflow.set_unit(unit)\n", "\n", "# NSCF_KGRID: used by \"band_gap_dos_hse\"\n", "if NSCF_KGRID is not None:\n", @@ -403,7 +405,7 @@ "\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_nscf\"]:\n", + " for unit_name in [\"pw_vc-relax\", \"pw_scf\", \"pw_scf_hse\", \"pw_nscf\"]:\n", " for swf in workflow.subworkflows:\n", " unit = swf.get_unit_by_name(name=unit_name)\n", " if unit:\n", diff --git a/other/materials_designer/workflows/band_structure.ipynb b/other/materials_designer/workflows/band_structure.ipynb index 67e59707..8ea294c6 100644 --- a/other/materials_designer/workflows/band_structure.ipynb +++ b/other/materials_designer/workflows/band_structure.ipynb @@ -263,6 +263,7 @@ "source": [ "from utils.api import get_or_create_material\n", "\n", + "material.basis.set_labels_from_list([])\n", "saved_material_response = get_or_create_material(client, material, ACCOUNT_ID)\n", "saved_material = Material.create(saved_material_response)" ] From 71c743c57125e3b4e00aa7af5d39408612f24668 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Fri, 13 Mar 2026 09:50:22 -0700 Subject: [PATCH 3/4] update: model and method at the top --- .../workflows/band_gap.ipynb | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/other/materials_designer/workflows/band_gap.ipynb b/other/materials_designer/workflows/band_gap.ipynb index 3e5178c1..1894b29e 100644 --- a/other/materials_designer/workflows/band_gap.ipynb +++ b/other/materials_designer/workflows/band_gap.ipynb @@ -46,6 +46,8 @@ "source": [ "import sys\n", "\n", + "from mypy.errorcodes import METHOD_ASSIGN\n", + "\n", "if sys.platform == \"emscripten\":\n", " import micropip\n", "\n", @@ -86,12 +88,19 @@ "# Options: \"band_gap\" / \"band_gap_dos_hse\"\n", "CALCULATION_TYPE = \"band_gap\"\n", "\n", - "APPLICATION_NAME = \"espresso\" # Specify application name (e.g., \"espresso\", \"vasp\")\n", + "APPLICATION_NAME = \"espresso\" # Specify application name (e.g., \"espresso\")\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", + "# Model parameters\n", + "MODEL_TYPE = \"dft\"\n", + "MODEL_SUBTYPE = \"lda\" # or \"gga\"\n", + "MODEL_FUNCTIONAL = \"pz\" # for lda: pz, for gga: pbe\n", + "METHOD_TYPE = \"pseudopotential\"\n", + "METHOD_SUBTYPE = \"us\" # or \"nc\"\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", @@ -103,7 +112,7 @@ "ECUTRHO = 200 # density cutoff, typically 4-8x ECUTWFC depending on pseudopotentials (if None, defaults are used)\n", "\n", "# 5. Compute parameters\n", - "CLUSTER_NAME = None # specify full or partial name i.e. \"cluster-001\" to select\n", + "CLUSTER_NAME = \"001\" # specify full or partial name i.e. \"cluster-001\" to select\n", "QUEUE_NAME = QueueName.D\n", "PPN = 1\n", "\n", @@ -130,7 +139,8 @@ "outputs": [], "source": [ "from utils.auth import authenticate\n", - "\n", + "import os\n", + "os.environ[\"OIDC_ACCESS_TOKEN\"] = \"-V_tMk8Q-FVX83eGSYpO287p1pXFZJQXA7d0Q8caHO0\"\n", "await authenticate()" ] }, @@ -334,8 +344,7 @@ "id": "24", "metadata": {}, "source": [ - "#### 4.3.2. Modify model and method parameters (Optional)\n", - "Uncomment the code below and adjust selected model and method (e.g. LDA vs GGA)." + "#### 4.3.2. Modify model and method parameters" ] }, { @@ -345,23 +354,21 @@ "metadata": {}, "outputs": [], "source": [ - "# 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\"\n", - "# functional=\"pbe\" # e.g., \"pz\" (LDA), \"pbe\" (GGA)\n", - "# )\n", - "# model_config[\"method\"] = {\"type\": \"pseudopotential\", \"subtype\": \"us\"} # e.g., \"us\", \"nc\"\n", - "# model = Model.create(model_config)\n", - "#\n", - "# for subworkflow in workflow.subworkflows:\n", - "# subworkflow.model = model\n", - "#\n", - "# visualize_workflow(workflow)" + "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=MODEL_TYPE,\n", + " subtype=MODEL_SUBTYPE,\n", + " functional=MODEL_FUNCTIONAL\n", + ")\n", + "model_config[\"method\"] = {\"type\": METHOD_TYPE, \"subtype\": METHOD_SUBTYPE}\n", + "model = Model.create(model_config)\n", + "\n", + "for subworkflow in workflow.subworkflows:\n", + " subworkflow.model = model\n", + "\n", + "visualize_workflow(workflow)" ] }, { From c9edd507a8e293eef0f137d32bd5bbf890989631 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Fri, 13 Mar 2026 15:31:53 -0700 Subject: [PATCH 4/4] update: separate specific parameters --- .../workflows/band_gap.ipynb | 221 ++++++++++-------- 1 file changed, 122 insertions(+), 99 deletions(-) diff --git a/other/materials_designer/workflows/band_gap.ipynb b/other/materials_designer/workflows/band_gap.ipynb index 1894b29e..b2c099b0 100644 --- a/other/materials_designer/workflows/band_gap.ipynb +++ b/other/materials_designer/workflows/band_gap.ipynb @@ -11,7 +11,7 @@ "\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. Set material and calculation parameters in cells 1.2 and 1.3 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", @@ -21,7 +21,7 @@ "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 gap workflow from Standata, optionally add relaxation or adjust model/method parameters, and save the workflow to the platform.\n", + "1. Configure workflow: select application, load band gap workflow from Standata, optionally add relaxation, set model and computational parameters, and save the workflow.\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", @@ -46,8 +46,6 @@ "source": [ "import sys\n", "\n", - "from mypy.errorcodes import METHOD_ASSIGN\n", - "\n", "if sys.platform == \"emscripten\":\n", " import micropip\n", "\n", @@ -55,7 +53,7 @@ " await micropip.install(\"mat3ra-utils\")\n", " from mat3ra.utils.jupyterlite.packages import install_packages\n", "\n", - " await install_packages(\"api_examples\")\n" + " await install_packages(\"api_examples\")" ] }, { @@ -63,7 +61,7 @@ "id": "3", "metadata": {}, "source": [ - "### 1.2. Set parameters and configurations for the workflow and job" + "### 1.2. Set parameters" ] }, { @@ -77,42 +75,27 @@ "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", + "MATERIAL_NAME = \"Silicon\"\n", "\n", "# 4. Workflow parameters\n", "# Options: \"band_gap\" / \"band_gap_dos_hse\"\n", "CALCULATION_TYPE = \"band_gap\"\n", "\n", - "APPLICATION_NAME = \"espresso\" # Specify application name (e.g., \"espresso\")\n", - "ADD_RELAXATION = None # Whether to add relaxation subworkflow as first unit\n", + "APPLICATION_NAME = \"espresso\"\n", + "ADD_RELAXATION = False\n", "\n", "WORKFLOW_SEARCH_TERM = f\"{CALCULATION_TYPE}.json\"\n", "MY_WORKFLOW_NAME = CALCULATION_TYPE.replace(\"_\", \" \").title() + (\" (relax)\" if ADD_RELAXATION else \"\")\n", "\n", "# Model parameters\n", - "MODEL_TYPE = \"dft\"\n", - "MODEL_SUBTYPE = \"lda\" # or \"gga\"\n", - "MODEL_FUNCTIONAL = \"pz\" # for lda: pz, for gga: pbe\n", - "METHOD_TYPE = \"pseudopotential\"\n", - "METHOD_SUBTYPE = \"us\" # or \"nc\"\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_gap_dos_hse\"\n", - "NSCF_KGRID = None # e.g., [8, 8, 8]\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", + "MODEL_SUBTYPE = \"gga\" # or \"lda\"\n", "\n", "# 5. Compute parameters\n", - "CLUSTER_NAME = \"001\" # specify full or partial name i.e. \"cluster-001\" to select\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", @@ -125,37 +108,65 @@ "cell_type": "markdown", "id": "5", "metadata": {}, + "source": [ + "### 1.3. Set specific band gap parameters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "# Method parameters\n", + "PSEUDOPOTENTIAL_TYPE = \"us\" # \"us\" (ultrasoft), \"nc\" (norm-conserving), \"paw\"\n", + "FUNCTIONAL = \"pbe\" # for lda: \"pz\"; for gga: \"pbe\", \"pbesol\"\n", + "\n", + "# K-grids\n", + "RELAXATION_KGRID = None # e.g. [4, 4, 4]\n", + "SCF_KGRID = None # e.g. [4, 4, 4]\n", + "NSCF_KGRID = None # e.g. [8, 8, 8] — used for band_gap_dos_hse\n", + "\n", + "# Energy cutoffs\n", + "ECUTWFC = 40\n", + "ECUTRHO = 200" + ] + }, + { + "cell_type": "markdown", + "id": "7", + "metadata": {}, "source": [ "## 2. Authenticate and initialize API client\n", "### 2.1. Authenticate\n", - "Authenticate in the browser and have credentials stored in environment variables." + "Authenticate in the browser and have credentials stored in environment variable \"OIDC_ACCESS_TOKEN\"." ] }, { "cell_type": "code", "execution_count": null, - "id": "6", + "id": "8", "metadata": {}, "outputs": [], "source": [ "from utils.auth import authenticate\n", - "import os\n", - "os.environ[\"OIDC_ACCESS_TOKEN\"] = \"-V_tMk8Q-FVX83eGSYpO287p1pXFZJQXA7d0Q8caHO0\"\n", + "\n", "await authenticate()" ] }, { "cell_type": "markdown", - "id": "7", + "id": "9", "metadata": {}, "source": [ - "### 2.2. Initialize API Client" + "### 2.2. Initialize API client" ] }, { "cell_type": "code", "execution_count": null, - "id": "8", + "id": "10", "metadata": {}, "outputs": [], "source": [ @@ -167,17 +178,16 @@ }, { "cell_type": "markdown", - "id": "9", + "id": "11", "metadata": {}, "source": [ - "### 2.3. Select account to work under\n", - "You can choose to use your personal one or any of the organizations you belong to." + "### 2.3. Select account" ] }, { "cell_type": "code", "execution_count": null, - "id": "10", + "id": "12", "metadata": {}, "outputs": [], "source": [ @@ -187,7 +197,7 @@ { "cell_type": "code", "execution_count": null, - "id": "11", + "id": "13", "metadata": {}, "outputs": [], "source": [ @@ -197,12 +207,12 @@ " 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}\")" + "print(f\"\\u2705 Selected account ID: {ACCOUNT_ID}, name: {selected_account.name}\")" ] }, { "cell_type": "markdown", - "id": "12", + "id": "14", "metadata": {}, "source": [ "### 2.4. Select project" @@ -211,18 +221,18 @@ { "cell_type": "code", "execution_count": null, - "id": "13", + "id": "15", "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})\")" + "print(f\"\\u2705 Using project: {projects[0]['name']} ({project_id})\")" ] }, { "cell_type": "markdown", - "id": "14", + "id": "16", "metadata": {}, "source": [ "## 3. Create material\n", @@ -232,7 +242,7 @@ { "cell_type": "code", "execution_count": null, - "id": "15", + "id": "17", "metadata": {}, "outputs": [], "source": [ @@ -249,7 +259,7 @@ }, { "cell_type": "markdown", - "id": "16", + "id": "18", "metadata": {}, "source": [ "### 3.2. Save material to the platform" @@ -258,7 +268,7 @@ { "cell_type": "code", "execution_count": null, - "id": "17", + "id": "19", "metadata": {}, "outputs": [], "source": [ @@ -271,17 +281,17 @@ }, { "cell_type": "markdown", - "id": "18", + "id": "20", "metadata": {}, "source": [ - "## 4. Create workflow and set its parameters\n", - "### 4.1. Get list of applications and select one" + "## 4. Configure workflow\n", + "### 4.1. Select application" ] }, { "cell_type": "code", "execution_count": null, - "id": "19", + "id": "21", "metadata": {}, "outputs": [], "source": [ @@ -295,16 +305,16 @@ }, { "cell_type": "markdown", - "id": "20", + "id": "22", "metadata": {}, "source": [ - "### 4.2. Create workflow from standard workflows and preview it" + "### 4.2. Load workflow from Standata and preview it" ] }, { "cell_type": "code", "execution_count": null, - "id": "21", + "id": "23", "metadata": {}, "outputs": [], "source": [ @@ -321,48 +331,46 @@ }, { "cell_type": "markdown", - "id": "22", + "id": "24", "metadata": {}, "source": [ - "### 4.3. Modify workflow (Optional)\n", - "#### 4.3.1. Add relaxation" + "### 4.3. Add relaxation (optional)" ] }, { "cell_type": "code", "execution_count": null, - "id": "23", + "id": "25", "metadata": {}, "outputs": [], "source": [ "if ADD_RELAXATION:\n", - " workflow.add_relaxation()\n" + " workflow.add_relaxation()\n", + " visualize_workflow(workflow)" ] }, { "cell_type": "markdown", - "id": "24", + "id": "26", "metadata": {}, "source": [ - "#### 4.3.2. Modify model and method parameters" + "### 4.4. Set Model and its parameters (physics)" ] }, { "cell_type": "code", "execution_count": null, - "id": "25", + "id": "27", "metadata": {}, "outputs": [], "source": [ - "from mat3ra.mode.model import Model\n", "from mat3ra.standata.model_tree import ModelTreeStandata\n", + "from mat3ra.mode.model import Model\n", "\n", "model_config = ModelTreeStandata.get_model_by_parameters(\n", - " type=MODEL_TYPE,\n", - " subtype=MODEL_SUBTYPE,\n", - " functional=MODEL_FUNCTIONAL\n", + " type=\"dft\", subtype=MODEL_SUBTYPE, functional=FUNCTIONAL\n", ")\n", - "model_config[\"method\"] = {\"type\": METHOD_TYPE, \"subtype\": METHOD_SUBTYPE}\n", + "model_config[\"method\"] = {\"type\": \"pseudopotential\", \"subtype\": PSEUDOPOTENTIAL_TYPE}\n", "model = Model.create(model_config)\n", "\n", "for subworkflow in workflow.subworkflows:\n", @@ -373,17 +381,16 @@ }, { "cell_type": "markdown", - "id": "26", + "id": "28", "metadata": {}, "source": [ - "#### 4.3.3. Modify important settings\n", - "Set k-grid and energy cutoffs." + "### 4.5. Modify Method (computational parameters): k-grid and cutoffs" ] }, { "cell_type": "code", "execution_count": null, - "id": "27", + "id": "29", "metadata": {}, "outputs": [], "source": [ @@ -403,7 +410,6 @@ " unit.add_context(PointsGridDataProvider(dimensions=SCF_KGRID, isEdited=True).yield_data())\n", " bg_subworkflow.set_unit(unit)\n", "\n", - "# NSCF_KGRID: used by \"band_gap_dos_hse\"\n", "if NSCF_KGRID is not None:\n", " unit = bg_subworkflow.get_unit_by_name(name=\"pw_nscf\")\n", " if unit:\n", @@ -412,28 +418,45 @@ "\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_hse\", \"pw_nscf\"]:\n", + " for unit_name in [\"pw_relax\", \"pw_vc-relax\", \"pw_scf\", \"pw_scf_hse\", \"pw_nscf\"]:\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", - "visualize_workflow(workflow)" + " swf.set_unit(unit)" ] }, { "cell_type": "markdown", - "id": "28", + "id": "30", "metadata": {}, "source": [ - "### 4.4. Save workflow to collection" + "### 4.6. Preview final workflow" ] }, { "cell_type": "code", "execution_count": null, - "id": "29", + "id": "31", + "metadata": {}, + "outputs": [], + "source": [ + "visualize_workflow(workflow)\n", + "workflow.to_dict()" + ] + }, + { + "cell_type": "markdown", + "id": "32", + "metadata": {}, + "source": [ + "### 4.7. Save workflow to collection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "33", "metadata": {}, "outputs": [], "source": [ @@ -447,7 +470,7 @@ }, { "cell_type": "markdown", - "id": "30", + "id": "34", "metadata": {}, "source": [ "## 5. Create the compute configuration\n", @@ -457,7 +480,7 @@ { "cell_type": "code", "execution_count": null, - "id": "31", + "id": "35", "metadata": {}, "outputs": [], "source": [ @@ -467,22 +490,21 @@ }, { "cell_type": "markdown", - "id": "32", + "id": "36", "metadata": {}, "source": [ - "### 5.2. Create compute configuration for the job" + "### 5.2. Create compute configuration" ] }, { "cell_type": "code", "execution_count": null, - "id": "33", + "id": "37", "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", @@ -498,17 +520,17 @@ }, { "cell_type": "markdown", - "id": "34", + "id": "38", "metadata": {}, "source": [ - "## 6. Create the job with material and workflow configuration\n", + "## 6. Create the job\n", "### 6.1. Create job" ] }, { "cell_type": "code", "execution_count": null, - "id": "35", + "id": "39", "metadata": {}, "outputs": [], "source": [ @@ -527,19 +549,19 @@ " project_id=project_id,\n", " owner_id=ACCOUNT_ID,\n", " prefix=job_name,\n", - " compute=compute.to_dict()\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(\"\\u2705 Job created successfully!\")\n", "print(f\"Job ID: {job_id}\")\n", "display_JSON(job_response)" ] }, { "cell_type": "markdown", - "id": "36", + "id": "40", "metadata": {}, "source": [ "## 7. Submit the job and monitor the status" @@ -548,18 +570,18 @@ { "cell_type": "code", "execution_count": null, - "id": "37", + "id": "41", "metadata": {}, "outputs": [], "source": [ "client.jobs.submit(job_id)\n", - "print(f\"✅ Job {job_id} submitted successfully!\")" + "print(f\"\\u2705 Job {job_id} submitted successfully!\")" ] }, { "cell_type": "code", "execution_count": null, - "id": "38", + "id": "42", "metadata": {}, "outputs": [], "source": [ @@ -570,24 +592,25 @@ }, { "cell_type": "markdown", - "id": "39", + "id": "43", "metadata": {}, "source": [ - "## 8. Retrieve results" + "## 8. Retrieve and visualize results\n", + "### 8.1. Band Gap" ] }, { "cell_type": "code", "execution_count": null, - "id": "40", + "id": "44", "metadata": {}, "outputs": [], "source": [ - "from utils.visualize import visualize_properties\n", "from mat3ra.prode import PropertyName\n", + "from utils.visualize import visualize_properties\n", "\n", - "band_gaps_property = client.properties.get_for_job(job_id, property_name=PropertyName.non_scalar.band_gaps)\n", - "visualize_properties(band_gaps_property, title=\"Band Gap\")" + "band_gaps_data = client.properties.get_for_job(job_id, property_name=PropertyName.non_scalar.band_gaps.value)\n", + "visualize_properties(band_gaps_data, title=\"Band Gap\")" ] } ],