COSMO-RS Conformer Workflows for Acetic Acid

The ADFCOSMORSConfJob class provides a customizable conformer-generation workflow for COSMO-RS. In its default form it generates conformers, performs ADF and COSMO calculations for all unique conformers, and produces .coskf files that can be used in multi-species COSMO-RS.

The workflow can be refined with additional filters and extra calculation steps to improve the geometries passed to ADF or to increase the accuracy of the energies used in filtering. For the multi-species follow-up workflow, see the GUI tutorial and the pyCRS example.

Downloads: Notebook | Script ?

Requires: AMS2026 or later

Related examples
Related tutorials
Related documentation

Initial imports

from scm.plams.recipes.adfcosmorsconformers import ADFCOSMORSConfJob, ADFCOSMORSConfFilter
from scm.plams import Molecule, from_smiles, Settings, config, JobRunner
from scm.conformers import ConformersJob
config.default_jobrunner = JobRunner(parallel=True, maxjobs=8)  # Set the default jobrunner to be parallel
config.default_jobmanager.settings.hashing = None  # Disable rerun prevention
config.job.runscript.nproc = 1  # Number of cores for each job
config.log.stdout = 1  # Suppress plams output

Set up conformer generator

First, we input the acetic acid molecule with the from_smiles function and provide the optional compound information that can be written to the COSKF file.

mol = from_smiles("CC(=O)O")
mol_info = {
    "CAS": "64-19-7",
    "IUPAC": "Acetic acid",
    "Other Name": "Ethanoic acid; Ethylic acid",
}

Now, we’ll specify a conformer generator (identical to the default) that generates only 50 initial structures:

conf_sett = Settings()
conf_sett.input.AMS.Generator.RDKit
conf_sett.input.AMS.Generator.RDKit.InitialNConformers = 50
conf_job = ConformersJob(name="conformers_uff", molecule=mol, settings=conf_sett)

Let’s also specify an additional step to add to the default workflow. Here, we’ll add a DFTB geometry optimization.

dftb_sett = Settings()
dftb_sett.input.DFTB
dftb_sett.input.AMS.Task = "Optimize"

The final thing we need to specify are filters. Let’s make three filters, the first to take a maximum of 20 conformers with a maximum energy range of 22 kcal/mol, the second with 10 conformers and 12 kcal/mol and the third with 5 conformers and 7 kcal/mol.

# ADFCOSMORSConfFilter(max number of conformers, max energy range)
fil1 = ADFCOSMORSConfFilter(20, 22)  # applied to UFF
fil2 = ADFCOSMORSConfFilter(10, 12)  # applied to DFTB
fil3 = ADFCOSMORSConfFilter(5, 7)  # applied to ADF gas phase

Run COSMO-RS conformers job

Finally, we give this information to the ADFCOSMORSConfJob class. We also specify the name of the coskf files as well as the directory in which we’ll find them after the calculations complete.

job = ADFCOSMORSConfJob(
    mol,
    conf_gen=conf_job,
    first_filter=fil1,
    additional=[(dftb_sett, fil2)],
    final_filter=fil3,
    coskf_name="acetic_acid",
    coskf_dir="test_coskfs",
    mol_info=mol_info,
)
job.run()
job.results.wait()
[18.03|16:14:05] JOB plamsjob STARTED
[18.03|16:14:05] Waiting for job plamsjob to finish
[18.03|16:14:05] JOB plamsjob/conformers_uff STARTED
[18.03|16:14:05] JOB plamsjob/job1_additional STARTED
[18.03|16:14:05] JOB plamsjob/job2_adf STARTED
[18.03|16:14:05] JOB plamsjob/job3_adf_filter STARTED
[18.03|16:14:05] Waiting for job job3_adf_filter to finish
[18.03|16:14:05] Waiting for job job1_additional to finish
[18.03|16:14:05] Waiting for job conformers_uff to finish
[18.03|16:14:05] Waiting for job job2_adf to finish
[18.03|16:14:11] JOB plamsjob/conformers_uff SUCCESSFUL
[18.03|16:14:13] JOB plamsjob/job1_additional SUCCESSFUL
[18.03|16:23:29] JOB plamsjob/job2_adf SUCCESSFUL
[18.03|16:23:30] JOB plamsjob/job3_adf_filter SUCCESSFUL
[18.03|16:23:30] JOB plamsjob/job4_replay STARTED
[18.03|16:24:15] JOB plamsjob/job4_replay SUCCESSFUL
[18.03|16:24:20] JOB plamsjob SUCCESSFUL
!amsview test_coskfs/acetic_acid_0.coskf
!amsview test_coskfs/acetic_acid_1.coskf

See also

Python Script

#!/usr/bin/env python
# coding: utf-8

# ## Initial imports

from scm.plams.recipes.adfcosmorsconformers import ADFCOSMORSConfJob, ADFCOSMORSConfFilter
from scm.plams import Molecule, from_smiles, Settings, config, JobRunner
from scm.conformers import ConformersJob


config.default_jobrunner = JobRunner(parallel=True, maxjobs=8)  # Set the default jobrunner to be parallel
config.default_jobmanager.settings.hashing = None  # Disable rerun prevention
config.job.runscript.nproc = 1  # Number of cores for each job
config.log.stdout = 1  # Suppress plams output


# ## Set up conformer generator

# First, we input the acetic acid molecule with the `from_smiles` function and provide the optional compound information that can be written to the COSKF file.

mol = from_smiles("CC(=O)O")
mol_info = {
    "CAS": "64-19-7",
    "IUPAC": "Acetic acid",
    "Other Name": "Ethanoic acid; Ethylic acid",
}


# Now, we'll specify a conformer generator (identical to the default) that generates only 50 initial structures:

conf_sett = Settings()
conf_sett.input.AMS.Generator.RDKit
conf_sett.input.AMS.Generator.RDKit.InitialNConformers = 50
conf_job = ConformersJob(name="conformers_uff", molecule=mol, settings=conf_sett)


# Let's also specify an additional step to add to the default workflow.  Here, we'll add a DFTB geometry optimization.

dftb_sett = Settings()
dftb_sett.input.DFTB
dftb_sett.input.AMS.Task = "Optimize"


# The final thing we need to specify are filters.  Let's make three filters, the first to take a maximum of 20 conformers with a maximum energy range of 22 kcal/mol, the second with 10 conformers and 12 kcal/mol and the third with 5 conformers and 7 kcal/mol.

# ADFCOSMORSConfFilter(max number of conformers, max energy range)
fil1 = ADFCOSMORSConfFilter(20, 22)  # applied to UFF
fil2 = ADFCOSMORSConfFilter(10, 12)  # applied to DFTB
fil3 = ADFCOSMORSConfFilter(5, 7)  # applied to ADF gas phase


# ## Run COSMO-RS conformers job

# Finally, we give this information to the `ADFCOSMORSConfJob` class.  We also specify the name of the coskf files as well as the directory in which we'll find them after the calculations complete.

job = ADFCOSMORSConfJob(
    mol,
    conf_gen=conf_job,
    first_filter=fil1,
    additional=[(dftb_sett, fil2)],
    final_filter=fil3,
    coskf_name="acetic_acid",
    coskf_dir="test_coskfs",
    mol_info=mol_info,
)
job.run()
job.results.wait()


# get_ipython().system('amsview test_coskfs/acetic_acid_0.coskf')


# get_ipython().system('amsview test_coskfs/acetic_acid_1.coskf')