Skip to content

About

Accelerated screening using a multifidelity pipeline for generative OLED design.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Accelerated multifidelity pipeline for OLED screening

This repository contains a customized Python-based pipeline for high-throughput quantum chemical calculations at different levels of theory. It is designed and tested on the Trillium HPC cluster and keeps clean, per-molecule metadata plus centralized logs/ for easy auditing and recovery. It’s also El Agente–friendly.


Step-by-Step Workflow

std2 pre-screening:

1. Generate XYZ coordinates from smiles, filter and create the partitions:

python src/run/obabel.py --smiles smiles.csv --root compounds --logs logs
python src/checking/check_obabel.py --root compounds --logs logs
python src/run/partition_compounds.py --root compounds --partition_size 1000

2. Obtain the best conformer using CREST

python src/submit/submit_crest_partition.py \
    --partition_dir compounds/partition_0 \
    --templates sh_templates \
    --cpus-per-task 40 \
    --time 12:00:00 \
    --gbsa dichlormethane

and filter for correct CREST calculations:

python src/run/filter_crest.py --root compounds --logs logs

3. Compute approximate optical properties with std2:

python src/submit/submit_std2.py --partition_dir compounds/partition_0 \
        --gbsa ch2cl2 --emax 20.0 --chunk-size 50 \
            --cpus-per-task 40 --time 02:00:00

Parse and plot results:

python src/run/parse_std2.py --root compounds --output-dir results/std2 \
          --smiles-csv smiles.csv
python src/plotting/std2_plots.py --csv results/std2/std2.csv \
    --output_dir results/std2/plots --n_permutations 5000

After downselecting candidates molecules from std2 pre-screening

4. ORCA geometry optimization at the b97_3c level:

python scr/submit/submit_orca_opt.py --downselection-path validation \
        --threads-per-job 16 \
        --jobs-per-node 12 \
        --time 08:00:00 \
        --charge 0 --mult 1

Check if all geometry optimizations succeeded:

python src/checking/check_opt_b97_3c.py --root validation

To resubmit only failed molecules (success == false in metadata.json), renaming old opt_b97_3c -> opt_b97_3c_failed_YYYYMMDD_HHMMSS:

python src/submit/submit_orca_opt.py --downselection-path validation \
    --threads-per-job 48 \
    --jobs-per-node 4 \
    --time 08:00:00 \
    --charge 0 --mult 1 \
    --resubmit-failed

5. Calculate frequencies:

This step is essential, as imaginary frequencies mean that our geometry optimization did not lead to a real minima but rather a saddle point of order ≥1 in the PES (Potential Energy Surface).

python src/submit/submit_orca_freq.py --downselection-path validation \
        --threads-per-job 32 \
        --jobs-per-node 6 \
        --time 08:00:00 \
        --charge 0 --mult 1

As with the geometry optimization, we check if the calculation was successful and if for some molecules it was not, we resubmit them using the resubmit-failed flag:

python src/checking/check_freq_b97_3c.py --root validation
python src/submit/submit_orca_freq.py --downselection-path validation \
        --threads-per-job 192 \
        --jobs-per-node 1 \
        --time 08:00:00 \
        --charge 0 --mult 1 \
        --resubmit-failed

Then we check for molecules with imaginary frequencies:

python src/checking/check_imaginary_freq.py --root validation

This scripts writes an imaginary_freq.json:

{
  "contain_imaginary_freq": true,
  "largest_imag": -34.95,
  "all_imag": [
    -34.95,
    -7.85
  ]
}

that stores the largest imaginary value and a list containing all of them. We select molecules that either: i) have one imaginary value larger than 20 or ii) have more than one imaginary value.

In those cases we run:

python src/run/set_reopt_imag_freq.py --root validation

set_reopt_imag_freq.py extracts frame 8 of the vibrational mode visualization generated by orca_pltvib, which corresponds to a moderate displacement along the normal mode. This step helps escape the saddle toward the nearest minimum.

6. Reoptimize geometries along imaginary modes

Run the B97-3c reoptimization on the displaced geometries:

python src/submit/submit_orca_reopt.py --downselection-path validation \
        --threads-per-job 32 \
        --jobs-per-node 6 \
        --time 08:00:00 \
        --charge 0 --mult 1

submit_orca_reopt.py scans validation/molXXXX/reopt_b97_3c/molXXXX_reopt.xyz, creates ORCA input files and Slurm job scripts, and submits node-parallel reoptimization jobs.

Check that all reoptimizations finished correctly:

python src/checking/check_reopt_b97_3c.py --root validation

check_reopt_b97_3c.py reports which reopt_b97_3c runs terminated normally and which failed or are missing outputs.

If some reoptimizations fail, you can re-run only the failed ones using the --resubmit-failed flag (see the usage example at the end of src/submit/submit_orca_reopt.py), e.g.:

python src/submit/submit_orca_reopt.py --downselection-path validation \
        --threads-per-job 32 \
        --jobs-per-node 4 \
        --time 08:00:00 \
        --charge 0 --mult 1 \
        --resubmit-failed

7. Frequencies on reoptimized geometries and imaginary-frequency check

Compute B97-3c frequencies using the reoptimized geometries:

python src/submit/submit_orca_freq_for_reopt.py --downselection-path validation \
        --threads-per-job 32 \
        --jobs-per-node 6 \
        --time 08:00:00 \
        --charge 0 --mult 1

submit_orca_freq_for_reopt.py only schedules frequency calculations for molecules whose reoptimization succeeded (based on reopt_b97_3c/metadata.json). If some of these frequency jobs fail, you can re-run just the failed cases with:

python src/submit/submit_orca_freq_for_reopt.py --downselection-path validation \
        --threads-per-job 48 \
        --jobs-per-node 4 \
        --time 08:00:00 \
        --charge 0 --mult 1 \
        --resubmit-failed

as illustrated in the usage section at the bottom of src/submit/submit_orca_freq_for_reopt.py. In resubmission mode the script backs up the old failed frequency directories before creating fresh ones.

After the reoptimized-frequency calculations finish, check for remaining imaginary modes:

python src/checking/check_imaginary_freq_reopt.py --root validation

check_imaginary_freq_reopt.py scans freq_b97_3c_for_reopt outputs, writes a per-molecule imaginary_freq.json (listing all imaginary frequencies and the most negative one), and summarizes which molecules still have problematic modes.

8. TD-DFT preparation, submission, and analysis

Prepare TD-DFT input folders using geometries that pass the imaginary-frequency criteria:

python src/run/prepare_td-dft.py --root validation

prepare_td-dft.py chooses, for each molecule, between the reoptimized branch (reopt_b97_3c + freq_b97_3c_for_reopt) and the original branch (opt_b97_3c + freq_b97_3c), based on the corresponding imaginary_freq.json. It accepts a single small imaginary mode below a threshold (default 20 cm⁻¹); otherwise that geometry is rejected. For accepted molecules it creates td-dft_wb97x-D3, copies the final geometry as molXXXX.xyz, and writes metadata.json.

Submit the TD-DFT calculations:

python src/submit/submit_td-dft.py --downselection-path validation \
        --threads-per-job 32 \
        --sh-template sh_templates/orca_cpcm_dcm_td-dft_safe.sh \
        --jobs-per-node 6 \
        --time 08:00:00 \
        --charge 0 --mult 1

submit_td-dft.py reads the TD-DFT folders under td-dft_wb97x-D3, builds ORCA TD-DFT input files and Slurm scripts, and submits node-parallel TD-DFT jobs. If some TD-DFT runs fail, you can resubmit only those molecules using:

python src/submit/submit_td-dft.py --downselection-path validation \
        --threads-per-job 32 \
        --sh-template sh_templates/orca_cpcm_dcm_td-dft_safe.sh \
        --jobs-per-node 6 \
        --time 08:00:00 \
        --charge 0 --mult 1 \
        --resubmit-failed

as described in the usage block at the end of src/submit/submit_td-dft.py. In resubmission mode, existing .out files are renamed with a timestamped _out_failed_YYYYMMDD_HHMMSS suffix before new jobs are launched.

Check TD-DFT outputs and, if needed, use the --resubmit-failed option as above to re-run only failed cases:

python src/checking/check_td-dft.py --root downselected

check_td-dft.py verifies that each TD-DFT output contains both the generic ORCA termination banner and the TD-DFT-specific *** ORCA-CIS/TD-DFT FINISHED WITHOUT ERROR *** line, summarizing successes, failures, and missing outputs.

Finally, parse the TD-DFT results into a CSV:

python src/run/parse_orca_td-dft.py \
          --root downselected \
          --output-dir results/downselection/td-dft \
          --td-dir-name td-dft_wb97x-D3 \
          --num-states 3 \
          --std2-csv results/std2/std2.csv

parse_orca_td-dft.py extracts singlet and triplet excitation energies, oscillator strengths, SOC-corrected transitions (if present), HOMO/LUMO levels, HOMO–LUMO gaps, and associates each spectrum with the corresponding SMILES string (from results/std2/std2.csv or per-molecule metadata).

Notes

ORCA Dependency
This project uses the ORCA quantum chemistry software, which is not included in this repository.
To run ORCA-dependent scripts, please download ORCA separately from the official website after accepting its academic license agreement.
We do not distribute ORCA binaries, source, or installation tools. Installation time
The main quantum chemistry packages (ORCA, CREST) were accessed via pre-installed HPC modules, so installation time on a desktop computer is not applicable. Modules To run src/submit/set_reopt_imag_freq.py you need to load: module load StdEnv/2023 gcc/12.3 openmpi/4.1.5 orca/6.1.0 As we need to use ${EBROOTORCA}/orca_pltvib

About

Accelerated screening using a multifidelity pipeline for generative OLED design.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages