quacc: Quantum Accelerator

repository·main·Indexed 43 days ago

https://github.com/quantum-accelerators/quacc

A flexible platform for high-throughput, database-driven quantum chemistry and computational materials science. Built upon the Atomic Simulation Environment (ASE), quacc provides a unified interface to dispatch workflows across local, HPC, and cloud environments. It supports various calculators including VASP, Quantum ESPRESSO, ORCA, Psi4, and TBLite, and integrates with the Materials Project stack and Maggma for data storage.

Tokens
40.1K
Snippets
138
Records
188
Agent score
54%

What's inside quacc

  1. Overview of quacc – The Quantum Accelerator

    main

    quacc is a flexible platform designed for computational materials science and quantum chemistry, optimized for automation. It allows users to execute pre-made computational workflows that can be dispatched to various computing environments, including local machines, High-Performance Computing (HPC) clusters, or the cloud.

    Key features include:

    • Workflow Dispatching: Run materials science workflows locally or across distributed environments (HPC, Cloud).
    • Unified Interface: Access multiple workflow management solutions through a single interface to suit different computing needs.
    • Ecosystem Integration: Built upon the Atomic Simulation Environment (ASE) and leverages infrastructure used by the Materials Project.
  2. Overview of TorchSim recipes

    main

    The quacc TorchSim recipes provide a high-level interface for running batched molecular dynamics, geometry optimizations, and static calculations using machine learning potentials. They wrap the torch-sim API while adding workflow engine compatibility, automatic trajectory handling, and standardized output schemas.

    Core job types:

    • relax_job: Geometry optimization using batched optimizers.
    • md_job: Molecular dynamics simulations with various integrators.
    • static_job: Single-point energy, force, or stress calculations.
  3. How flows work in quacc

    main

    A flow is a Python function decorated with #!Python @flow that orchestrates a collection of jobs.

    Core Mental Model:

    • Logic vs. Computation: A flow should not contain computationally intensive tasks. Its purpose is to define workflow logic by calling other jobs or flows.
    • Futures and Outputs: The output of a job within a flow is a future, not the actual resolved value.
    • Data Handling: You cannot perform standard operations on job outputs directly within the flow (e.g., result["atoms"] will return a future of the atoms, not the Atoms object itself). However, if you pass these outputs as inputs to subsequent jobs, quacc will automatically resolve the future before the next job runs.
    • Customization: To maintain flexibility, flows distributed with quacc should allow users to update individual job parameters and decorators, typically using the quacc.wflow_tools.customizers.customize_jobs function.
    @flow
    def my_workflow(input_data):
        # job_output is a future
        job_output = my_job(input_data)
        # Passing job_output to another job triggers automatic resolution
        final_result = next_job(job_output)
        return final_result
  4. Understand Jobs and Recipes in quacc

    main

    In quacc, calculations are organized into two main abstractions:

    1. Jobs: Individual, discrete calculations.
    2. Recipes: Pre-packaged collections of jobs and workflows provided for specific quantum codes.

    Jobs can be stitched together to form complex workflows. This tutorial-style approach allows you to run simple calculations locally to test functionality before scaling to larger workflows.

  5. Handle Ray futures with @subflow

    main

    When using the Ray engine, quacc wraps the returned ObjectRef in a RayFuture proxy. This allows recipe code that indexes into job results (e.g., result["atoms"]) to continue working seamlessly.

    To resolve a RayFuture to its final value, call the .result() method.

    # To resolve a future to its final value
    final_value = future.result()
  6. Understand default file management behavior

    main

    By default, quacc stores results in the current working directory (RESULTS_DIR is set to Path()).

    During a job's lifecycle, the directory structure changes based on the job status:

    • At Runtime: A temporary directory is created with the prefix tmp- (e.g., tmp-quacc-YYYY-MM-DD-ID). Files are stored uncompressed.
    • On Success: The temporary directory is renamed to remove the tmp- prefix (e.g., quacc-YYYY-MM-DD-ID), and files are automatically compressed using gzip (e.g., OUTPUT.gz).
    • On Failure: The directory is renamed with a failed- prefix (e.g., failed-quacc-YYYY-MM-DD-ID). Files remain uncompressed.
  7. Compare quacc recipes with TorchSim direct API

    main

    The quacc recipes wrap the high-level torch_sim functions to provide enhanced features for large-scale simulations. Use quacc recipes instead of the direct torch_sim API if you require:

    • Batch processing: quacc uses relax_job(atoms=systems, ...) to handle multiple systems, whereas torch_sim uses ts.optimize(system=systems, ...).
    • Workflow engines: quacc has built-in support for engines like Prefect, Parsl, Dask, and Ray.
    • Standardized result schemas: quacc returns consistent dictionary formats, while torch_sim uses custom handling.
    • Automatic trajectory management: quacc manages job directories and trajectory paths automatically.
    • Simplified model loading: quacc uses model_type and model_path instead of manual instantiation.
  8. Core Workflow Syntax: @job and @flow

    main

    Quacc uses two primary decorators to define computational workflows:

    • @job: Decorates a Python function to turn it into a discrete compute task (a 'job'). The underlying implementation of this task depends on your configured WORKFLOW_ENGINE (e.g., Dask, Ray, Prefect).
    • @flow: Decorates a function that composes multiple @job calls into a single workflow. It defines the boundary of the workflow and manages how data flows between jobs.

    When you call a function decorated with @flow, it returns a reference or a proxy object (depending on the engine) rather than the immediate result. You must then use engine-specific methods or quacc's returned proxies to resolve the final value.

    from quacc import flow, job
    
    @job
    def add(a, b):
        return a + b
    
    @job
    def mult(a, b):
        return a * b
    
    @flow
    def workflow(a, b, c):
        output1 = add(a, b)
        output2 = mult(output1, c)
        return output2
    
    # workflow(1, 2, 3) returns a reference/proxy
  9. How subflows work for dynamic workflows

    main

    When the number of jobs in a workflow is not known a priori (dynamic workflows), use a subflow decorated with #!Python @subflow.

    A subflow behaves like a flow, but instead of returning a single value, it returns a list of job outputs. This allows you to iterate over data and spawn a variable number of jobs based on runtime results.

    Example Pattern:

    1. A job produces a list of values.
    2. A @subflow iterates over that list, calling a @job for each element.
    3. The @flow calls the @subflow and receives the collection of outputs.
    from random import randint
    from quacc import flow, job, subflow
    
    @job
    def add(a, b):
        return a + b
    
    @job
    def make_list(val):
        return [val] * randint(2, 5)
    
    @subflow
    def add_distributed(vals, c):
        outputs = []
        for val in vals:
            output = add(val, c)
            outputs.append(output)
        return outputs
    
    @flow
    def workflow(a, b, c):
        output1 = add(a, b)
        output2 = make_list(output1)
        output3 = add_distributed(output2, c)
        return output3
  10. Modify job decorators in a pre-made flow

    main

    When using a pre-made workflow (like bulk_to_slabs_flow), you can customize the behavior of specific jobs using the job_decorators keyword argument. This allows you to change executors, retries, or resource requests for specific internal functions without rewriting the flow.

    Use the specific job name as the key in the job_decorators dictionary, or use the special key "all" to apply decorators to every job in the flow.

    # Modify a specific job named 'static_job'
    bulk_to_slabs_flow(atoms, job_decorators={"static_job": job(retries=2)})
    
    # Modify all jobs in the flow
    bulk_to_slabs_flow(atoms, job_decorators={"all": job(num_cpus=1)})
  11. Use schemas for job outputs

    main

    A schema is a dictionary that contains tabulated input and output properties from a calculation. Using schemas ensures that your job results are quacc-compatible.

    Key features of schemas:

    • Automatic Storage: If a database is specified in the global settings, schemas will automatically store results in the user's database.
    • Type Hinting: Output type-hints associated with schemas are stored in quacc.types.
    • Location: All available schemas are located in quacc.schemas.