{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Task, Engine and Property Blocks\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PLAMS working folder: /path/plams/examples/AMSSettingsInput/plams_workdir\n" ] } ], "source": [ "from scm.plams import Settings, AMSJob, init\n", "\n", "# this line is not required in AMS2025+\n", "init()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To start with, in order to see the input that will be passed to AMS from the Settings, make a function to create an AMSJob and print the input:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def print_input(settings):\n", " print(AMSJob(settings=settings).get_input())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tasks can be specified in the settings under the `input.AMS.Task` key:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GeometryOptimization\n", " Convergence\n", " Gradients 1e-05\n", " End\n", "End\n", "\n", "Task GeometryOptimization\n", "\n", "\n" ] } ], "source": [ "go_settings = Settings()\n", "go_settings.input.AMS.Task = \"GeometryOptimization\"\n", "go_settings.input.AMS.GeometryOptimization.Convergence.Gradients = 1e-5\n", "print_input(go_settings)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Properties can be specified under the `input.AMS.Properties` key:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Properties\n", " NormalModes Yes\n", "End\n", "\n", "\n" ] } ], "source": [ "nm_settings = Settings()\n", "nm_settings.input.ams.Properties.NormalModes = \"Yes\"\n", "print_input(nm_settings)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Engine settings can be specified under the `input.AMS.` key, for the engine of interest:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Engine ADF\n", " Basis\n", " Type DZP\n", " End\n", "EndEngine\n", "\n", "\n" ] } ], "source": [ "lda_settings = Settings()\n", "lda_settings.input.ADF.Basis.Type = \"DZP\"\n", "print_input(lda_settings)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Combining Settings" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Settings objects can also be combined for easy reuse and job setup. Settings can be merged using the `+` and `+=` operators." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GeometryOptimization\n", " Convergence\n", " Gradients 1e-05\n", " End\n", "End\n", "\n", "Properties\n", " NormalModes Yes\n", "End\n", "\n", "Task GeometryOptimization\n", "\n", "\n", "Engine ADF\n", " Basis\n", " Type DZP\n", " End\n", "EndEngine\n", "\n", "\n" ] } ], "source": [ "settings = go_settings + lda_settings + nm_settings\n", "print_input(settings)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note however that this merge is a \"soft\" update, so values of existing keys will not be overwritten:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GeometryOptimization\n", " Convergence\n", " Gradients 1e-05\n", " End\n", "End\n", "\n", "Properties\n", " NormalModes Yes\n", "End\n", "\n", "Task GeometryOptimization\n", "\n", "\n", "Engine ADF\n", " Basis\n", " Type DZP\n", " End\n", " xc\n", " gga pbe\n", " End\n", "EndEngine\n", "\n", "\n" ] } ], "source": [ "pbe_settings = Settings()\n", "pbe_settings.input.ADF.Basis.Type = \"TZP\"\n", "pbe_settings.input.ADF.xc.gga = \"pbe\"\n", "settings += pbe_settings\n", "print_input(settings)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To achieve \"hard update\" behaviour, the `update` method can be used, which overwrites existing keys:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GeometryOptimization\n", " Convergence\n", " Gradients 1e-05\n", " End\n", "End\n", "\n", "Properties\n", " NormalModes Yes\n", "End\n", "\n", "Task GeometryOptimization\n", "\n", "\n", "Engine ADF\n", " Basis\n", " Type TZP\n", " End\n", " xc\n", " gga pbe\n", " End\n", "EndEngine\n", "\n", "\n" ] } ], "source": [ "settings.update(pbe_settings)\n", "print_input(settings)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In AMS2025+, settings can also be removed using the `-` and `-=` operators:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def check_ams_version():\n", " try:\n", " from scm.plams import __version__\n", "\n", " return __version__ >= \"2024.2\"\n", " except ImportError:\n", " return False\n", "\n", "\n", "is_ams_2025_or_higher = check_ams_version()" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GeometryOptimization\n", " Convergence\n", " Gradients 1e-05\n", " End\n", "End\n", "\n", "Properties\n", "End\n", "\n", "Task GeometryOptimization\n", "\n", "\n", "Engine ADF\n", " Basis\n", " Type TZP\n", " End\n", " xc\n", " gga pbe\n", " End\n", "EndEngine\n", "\n", "\n" ] } ], "source": [ "if is_ams_2025_or_higher:\n", " settings -= nm_settings\n", " print_input(settings)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Multiple values in a settings block can be configured using a list:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GeometryOptimization\n", " Convergence\n", " Gradients 1e-05\n", " End\n", "End\n", "\n", "Hybrid\n", " Energy\n", " Term\n", " EngineID adf-lda\n", " Factor 1.0\n", " Region *\n", " End\n", " Term\n", " EngineID adf-lda\n", " Factor -1.0\n", " Region one\n", " End\n", " Term\n", " EngineID adf-gga\n", " Factor 1.0\n", " Region one\n", " End\n", " Term\n", " EngineID adf-lda\n", " Factor -1.0\n", " Region two\n", " End\n", " Term\n", " EngineID adf-gga\n", " Factor 1.0\n", " Region two\n", " End\n", " End\n", " Engine ADF adf-lda\n", " Basis\n", " Type DZP\n", " End\n", " EndEngine\n", " Engine ADF adf-gga\n", " Basis\n", " Type TZP\n", " End\n", " xc\n", " gga pbe\n", " End\n", " EndEngine\n", "\n", "End\n", "\n", "Task GeometryOptimization\n", "\n", "\n" ] } ], "source": [ "hybrid_settings = go_settings.copy()\n", "hybrid_settings.input.AMS.Hybrid.Energy.Term = []\n", "for i in range(5):\n", " factor = (-1) ** (i % 2) * 1.0\n", " region = \"*\" if i == 0 else \"one\" if i < 3 else \"two\"\n", " engine_id = \"adf-lda\" if i == 0 or factor == -1 else \"adf-gga\"\n", " term = Settings({\"Factor\": factor, \"Region\": region, \"EngineID\": engine_id})\n", " hybrid_settings.input.AMS.Hybrid.Energy.Term.append(term)\n", "hybrid_settings.input.AMS.Hybrid.Engine = [lda_settings.input.ADF.copy(), pbe_settings.input.ADF.copy()]\n", "hybrid_settings.input.AMS.Hybrid.Engine[0]._h = \"ADF adf-lda\"\n", "hybrid_settings.input.AMS.Hybrid.Engine[1]._h = \"ADF adf-gga\"\n", "print_input(hybrid_settings)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note also in the example below, the use of the special `_h` \"header\" key, which can be used to add data to the header line for a block." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Nested Keys" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It can be useful to access values from a Settings object using \"nested\" keys, available in AMS2025+. These are tuples of keys, where each successive element of the tuple corresponds to a further layer in the settings. Lists are flattened so their elements can be accessed with the corresponding index." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[('input',), ('input', 'AMS'), ('input', 'AMS', 'Task'), ('input', 'AMS', 'GeometryOptimization'), ('input', 'AMS', 'GeometryOptimization', 'Convergence'), ('input', 'AMS', 'GeometryOptimization', 'Convergence', 'Gradients'), ('input', 'AMS', 'Hybrid'), ('input', 'AMS', 'Hybrid', 'Energy'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 0), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 0, 'Factor'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 0, 'Region'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 0, 'EngineID'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 1), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 1, 'Factor'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 1, 'Region'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 1, 'EngineID'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 2), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 2, 'Factor'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 2, 'Region'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 2, 'EngineID'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 3), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 3, 'Factor'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 3, 'Region'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 3, 'EngineID'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 4), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 4, 'Factor'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 4, 'Region'), ('input', 'AMS', 'Hybrid', 'Energy', 'Term', 4, 'EngineID'), ('input', 'AMS', 'Hybrid', 'Engine'), ('input', 'AMS', 'Hybrid', 'Engine', 0), ('input', 'AMS', 'Hybrid', 'Engine', 0, '_h'), ('input', 'AMS', 'Hybrid', 'Engine', 0, 'Basis'), ('input', 'AMS', 'Hybrid', 'Engine', 0, 'Basis', 'Type'), ('input', 'AMS', 'Hybrid', 'Engine', 1), ('input', 'AMS', 'Hybrid', 'Engine', 1, '_h'), ('input', 'AMS', 'Hybrid', 'Engine', 1, 'Basis'), ('input', 'AMS', 'Hybrid', 'Engine', 1, 'Basis', 'Type'), ('input', 'AMS', 'Hybrid', 'Engine', 1, 'xc'), ('input', 'AMS', 'Hybrid', 'Engine', 1, 'xc', 'gga')]\n" ] } ], "source": [ "if is_ams_2025_or_higher:\n", " print(list(hybrid_settings.nested_keys()))" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GeometryOptimization\n" ] } ], "source": [ "if is_ams_2025_or_higher:\n", " print(hybrid_settings.get_nested((\"input\", \"AMS\", \"Task\")))" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Type: \tTZP\n", "\n" ] } ], "source": [ "if is_ams_2025_or_higher:\n", " if hybrid_settings.contains_nested((\"input\", \"AMS\", \"Hybrid\", \"Engine\", 0)):\n", " hybrid_settings.set_nested((\"input\", \"AMS\", \"Hybrid\", \"Engine\", 0, \"Basis\", \"Type\"), \"TZP\")\n", " print(hybrid_settings.get_nested((\"input\", \"AMS\", \"Hybrid\", \"Engine\", 0, \"Basis\")))" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## Comparison" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In AMS2025+, two settings objects can be compared to check the differences between them. The result will show the nested key and value of any added, removed and modified entries." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Items in settings2 not in settings1:\n", " - ('input', 'DFTB', 'Model'): GFN1-xTB\n", "Items in settings1 not in settings2:\n", " - ('input', 'ADF', 'Basis', 'Type'): DZP\n", " - ('input', 'AMS', 'Properties', 'NormalModes'): Yes\n", "Items modified from settings1 to settings2:\n", " - ('input', 'AMS', 'Task'): GeometryOptimization -> SinglePoint\n" ] } ], "source": [ "if is_ams_2025_or_higher:\n", " import os\n", "\n", " settings1 = go_settings + lda_settings + nm_settings\n", " settings2 = go_settings.copy()\n", " settings2.input.AMS.Task = \"SinglePoint\"\n", " settings2.input.DFTB.Model = \"GFN1-xTB\"\n", " comparison = settings2.compare(settings1)\n", " print(\n", " f\"Items in settings2 not in settings1:{os.linesep}{os.linesep.join(f' - {k}: {v}' for k, v in comparison['added'].items())}\"\n", " )\n", " print(\n", " f\"Items in settings1 not in settings2:{os.linesep}{os.linesep.join(f' - {k}: {v}' for k, v in comparison['removed'].items())}\"\n", " )\n", " print(\n", " f\"Items modified from settings1 to settings2:{os.linesep}{os.linesep.join(f' - {k}: {v[1]} -> {v[0]}' for k, v in comparison['modified'].items())}\"\n", " )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.8.16" } }, "nbformat": 4, "nbformat_minor": 4 }