Gridoptimization calculations ===================================== Grid optimizations perform a multi-dimensional scan over internal coordinates (distance, angle, dihedral). At each grid point, a constrained geometry optimization is performed to minimize the energy while holding selected coordinates fixed. This produces a grid of optimized structures and their final energies. .. _gridoptimization_record: Gridoptimization Records ------------------------ Gridoptimization records contain all the fields of a :doc:`base record `, and additionally include: - ``initial_molecule`` - The molecule used as the starting geometry for the scan - ``starting_molecule`` - The molecule actually used to start the scan (after optional preoptimization) - ``starting_grid`` - The grid indices where the scan started (if relative steps were used) - ``optimizations`` - A mapping from grid keys to each constrained :class:`~qcportal.optimization.record_models.OptimizationRecord` - ``specification`` - The scan/optimization setup (see below) The optimizations can be accessed via the :attr:`~qcportal.gridoptimization.record_models.GridoptimizationRecord.optimizations` property, which returns a dictionary mapping grid keys to optimization records. Grid keys are tuples of integers (one per scan dimension) that index the steps defined in your scan. A special key ``"preoptimization"`` is used for the optional initial unconstrained optimization. The convenience property :attr:`~qcportal.gridoptimization.record_models.GridoptimizationRecord.final_energies` returns a dictionary mapping grid keys (tuples) to the final energy from each optimization. .. note:: The mapping keys are represented as strings when serialized; use :func:`~qcportal.gridoptimization.record_models.serialize_key` and :func:`~qcportal.gridoptimization.record_models.deserialize_key` for conversions if needed. .. _gridoptimization_specification: Gridoptimization Specification ------------------------------ The :ref:`glossary_specification` for a grid optimization is a :class:`~qcportal.gridoptimization.record_models.GridoptimizationSpecification`. The key fields are: - ``program`` - The gridoptimization driver program (``"gridoptimization"``) - ``optimization_specification`` - How each constrained optimization should be run; see :ref:`optimization_specification` - ``keywords`` - The scan definition and related options (see below) The keywords are provided via :class:`~qcportal.gridoptimization.record_models.GridoptimizationKeywords` and include: - ``scans`` - A list of :class:`~qcportal.gridoptimization.record_models.ScanDimension` objects describing each scan dimension: - ``type`` - One of :class:`~qcportal.gridoptimization.record_models.ScanTypeEnum` (``distance``, ``angle``, ``dihedral``) - ``indices`` - Atom indices. This is zero-indexed, so the first atom of the molecule has index 0. There are 2 indices for distance, 3 for angle, 4 for dihedral. - ``steps`` - A strictly monotonic list of values; units are Bohr for distances and degrees for angles/dihedrals - ``step_type`` - :class:`~qcportal.gridoptimization.record_models.StepTypeEnum` (``absolute`` or ``relative``) - ``preoptimization`` - If ``True``, perform an unconstrained optimization before scanning. This is especially useful with ``relative`` step types so that relative steps are taken from a relaxed starting geometry. Note: The constrained optimizations at each grid point use the specification supplied by the :class:`~qcportal.optimization.record_models.OptimizationSpecification`, including the level of theory and programs. See :ref:`optimization_specification`. Absolute vs. Relative step_type ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Each :class:`~qcportal.gridoptimization.record_models.ScanDimension` declares how its ``steps`` should be interpreted via the ``step_type`` field: - ``absolute`` – The values in ``steps`` are the absolute target values for the corresponding internal coordinate. For example, a dihedral scan with ``steps=[-180, -165, ..., 180]`` constrains that dihedral to those exact angles at each grid point. Likewise, a bond-distance scan with ``steps=[2.5, 2.6, 2.7]`` (in Bohr) constrains the distance to those exact values. - ``relative`` – The values in ``steps`` are offsets relative to the value measured on the starting molecule for the scan. At submission time the server constructs the constraints by adding the offset to the measured value on the starting geometry. Concretely, for a given grid index ``i`` the constraint value used is ``steps[i] + measure(starting_molecule, indices)``. Starting molecule and starting grid ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - If ``preoptimization`` is ``True``, the starting molecule is the final geometry from an initial unconstrained optimization of the input structure. If ``preoptimization`` is ``False``, the starting molecule is simply the initial molecule you submitted. - The ``starting_grid`` stored on the record is the index tuple of the first constrained optimization that is launched: it is chosen as the grid point whose target value is closest to the starting molecule. For ``absolute`` dimensions this means picking the step closest to ``measure(starting_molecule, indices)``; for ``relative`` dimensions this means picking the step closest to ``0`` (no change). Practical tips ~~~~~~~~~~~~~~ - Use ``relative`` steps when you want to explore around the current structure without having to compute absolute values ahead of time (for example, ``[-0.2, 0.0, 0.2]`` Bohr around the current bond length, or ``[-10, 0, 10]`` degrees around a torsion). - Use ``absolute`` steps when you want the grid aligned to specific absolute values (for example, a canonical ``[-180, -165, ..., 180]`` dihedral scan). - ``preoptimization=True`` is often helpful with ``relative`` scans so the offsets are applied from a relaxed geometry. Examples of building specifications ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. dropdown:: Single-dimension dihedral scan with preoptimization .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 from qcportal.gridoptimization import GridoptimizationSpecification, GridoptimizationKeywords, ScanDimension from qcportal.optimization import OptimizationSpecification from qcportal.singlepoint import QCSpecification go_spec = GridoptimizationSpecification( program="gridoptimization", optimization_specification=OptimizationSpecification( program="geometric", qc_specification=QCSpecification(program="psi4", method="b3lyp", basis="def2-svp", driver="deferred"), ), keywords=GridoptimizationKeywords( scans=[ ScanDimension(type="dihedral", indices=[0, 1, 2, 3], step_type="absolute", steps=list(range(-180, 181, 15))) ], preoptimization=True, ), ) .. dropdown:: Two-dimensional scan combining a bond stretch and angle bend .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 from qcportal.gridoptimization import GridoptimizationSpecification, GridoptimizationKeywords, ScanDimension from qcportal.optimization import OptimizationSpecification from qcportal.singlepoint import QCSpecification go_spec = GridoptimizationSpecification( program="gridoptimization", optimization_specification=OptimizationSpecification( program="geometric", qc_specification=QCSpecification(program="psi4", method="wb97x-d", basis="def2-tzvp", driver="deferred"), ), keywords=GridoptimizationKeywords( scans=[ ScanDimension(type="distance", indices=[0, 1], step_type="relative", steps=[-0.2, 0.0, 0.2]), ScanDimension(type="angle", indices=[1, 2, 3], step_type="absolute", steps=[90.0, 110.0, 130.0]), ], preoptimization=True, ), ) .. dropdown:: Relative dihedral offsets around the starting torsion (with preoptimization) .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 from qcportal.gridoptimization import GridoptimizationSpecification, GridoptimizationKeywords, ScanDimension from qcportal.optimization import OptimizationSpecification from qcportal.singlepoint import QCSpecification go_spec = GridoptimizationSpecification( program="gridoptimization", optimization_specification=OptimizationSpecification( program="geometric", qc_specification=QCSpecification(program="psi4", method="b3lyp", basis="def2-svp", driver="deferred"), ), keywords=GridoptimizationKeywords( scans=[ # Offsets in degrees relative to the starting torsion value ScanDimension(type="dihedral", indices=[0, 1, 2, 3], step_type="relative", steps=[-30.0, 0.0, 30.0]) ], preoptimization=True, ), ) .. dropdown:: Relative bond-length scan without preoptimization .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 from qcportal.gridoptimization import GridoptimizationSpecification, GridoptimizationKeywords, ScanDimension from qcportal.optimization import OptimizationSpecification from qcportal.singlepoint import QCSpecification go_spec = GridoptimizationSpecification( program="gridoptimization", optimization_specification=OptimizationSpecification( program="geometric", qc_specification=QCSpecification(program="psi4", method="wb97x-d", basis="def2-tzvp", driver="deferred"), ), keywords=GridoptimizationKeywords( scans=[ # Offsets in Bohr relative to the starting bond length ScanDimension(type="distance", indices=[0, 1], step_type="relative", steps=[-0.2, 0.0, 0.2]) ], preoptimization=False, ), ) .. _gridoptimization_submission: Submitting Records ------------------ Gridoptimization records can be submitted using a client via the :meth:`~qcportal.client.PortalClient.add_gridoptimizations` method. This method takes the following key information: - ``initial_molecules`` - A single molecule or list of molecules to scan - ``program`` - The gridoptimization program (use ``"gridoptimization"``) - ``optimization_specification`` - The optimization setup for each grid point (see :ref:`gridoptimization_specification`) - ``keywords`` - The grid scan definition and options See :doc:`../record_submission` for more information about other common fields such as compute tag and priority. Client Examples --------------- .. dropdown:: Obtain a single gridoptimization record by ID .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 r = client.get_gridoptimizations(123) .. dropdown:: Obtain multiple gridoptimization records by ID .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 r_lst = client.get_gridoptimizations([123, 456]) .. dropdown:: Include molecules and child optimizations during initial fetch .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 r = client.get_gridoptimizations(123, include=["**"]) # include all data .. dropdown:: Query gridoptimizations by QC method/basis and include optimizations .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 r_iter = client.query_gridoptimizations(qc_method='b3lyp', qc_basis='def2-svp', include=['optimizations']) for r in r_iter: print(r.id, len(r.optimizations)) .. dropdown:: Submit gridoptimizations .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 from qcportal.gridoptimization import GridoptimizationSpecification, GridoptimizationKeywords, ScanDimension from qcportal.optimization import OptimizationSpecification from qcportal.singlepoint import QCSpecification spec = GridoptimizationSpecification( program='gridoptimization', optimization_specification=OptimizationSpecification( program='geometric', qc_specification=QCSpecification(program='psi4', method='b3lyp', basis='def2-svp', driver='deferred'), ), keywords=GridoptimizationKeywords( scans=[ScanDimension(type='dihedral', indices=[0,1,2,3], step_type='absolute', steps=list(range(-180,181,15)))], preoptimization=True, ), ) meta, ids = client.add_gridoptimizations([mol1, mol2], program='gridoptimization', optimization_specification=spec.optimization_specification, keywords=spec.keywords) .. _gridoptimization_dataset: Gridoptimization Datasets ------------------------- Gridoptimization :ref:`datasets ` are collections of gridoptimization records. :class:`Entries ` contain a single initial molecule and optional metadata. The :class:`dataset specifications ` wrap a :class:`GridoptimizationSpecification `. See :doc:`../datasets/index` for general dataset operations and advanced usage. Dataset Examples ---------------- .. dropdown:: Create a gridoptimization dataset .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 ds = client.add_dataset("gridoptimization", "Grid Scan Dataset", "A demonstration grid scan dataset") .. dropdown:: Add entries to a gridoptimization dataset .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 from qcportal.gridoptimization import GridoptimizationDatasetEntry from qcportal.molecules import Molecule entries = [] for name, geom in [("butane", butane_geom), ("ethane", ethane_geom)]: mol = Molecule.from_data(geom) if isinstance(geom, str) else Molecule(**geom) entries.append(GridoptimizationDatasetEntry(name=name, initial_molecule=mol)) ds.add_entries(entries) .. dropdown:: Add a specification to a gridoptimization dataset .. tab-set:: .. tab-item:: PYTHON .. code-block:: py3 from qcportal.gridoptimization import GridoptimizationSpecification, GridoptimizationKeywords, ScanDimension from qcportal.optimization import OptimizationSpecification from qcportal.singlepoint import QCSpecification go_spec = GridoptimizationSpecification( program="gridoptimization", optimization_specification=OptimizationSpecification( program="geometric", qc_specification=QCSpecification(program="psi4", method="b3lyp", basis="def2-svp", driver="deferred"), ), keywords=GridoptimizationKeywords( scans=[ScanDimension(type="dihedral", indices=[0, 1, 2, 3], step_type="absolute", steps=list(range(-180, 181, 60)))], preoptimization=True, ), ) ds.add_specification("go-geometric/psi4-b3lyp-def2-svp", go_spec) .. _gridoptimization_qcportal_api: Gridoptimization QCPortal API ----------------------------- * :mod:`Record models ` * :mod:`Dataset models ` * PortalClient methods * :meth:`~qcportal.client.PortalClient.add_gridoptimizations` * :meth:`~qcportal.client.PortalClient.get_gridoptimizations` * :meth:`~qcportal.client.PortalClient.query_gridoptimizations`