from openff.bespokefit.workflows import BespokeWorkflowFactory
from openff.qcsubmit.common_structures import QCSpec
from openff.toolkit.topology import Molecule
from openff.bespokefit.executor import BespokeExecutor, BespokeWorkerConfig
from openff.bespokefit.executor.client import BespokeFitClient, Settings
factory = BespokeWorkflowFactory(
# Define the starting force field that will be augmented with bespoke
# parameters.
initial_force_field="openff-2.2.0.offxml",
# Change the level of theory that the reference QC data is generated at
default_qc_specs=[
QCSpec(
method="gfn2xtb",
basis=None,
program="xtb",
spec_name="xtb",
spec_description="gfn2xtb",
)
],
)
input_molecules = [
Molecule.from_smiles("C(C(=O)O)N"),
Molecule.from_smiles("C[C@@H](C1=CC=C(C=C1)CC(C)C)C(=O)O "),
] # Glycine
input_molecules = [Molecule.from_smiles("C(C(=O)O)N")] # 0
# input_molecules = [Molecule.from_smiles("C[C@@H](C1=CC=C(C=C1)CC(C)C)C(=O)O ")] # 1
workflow_schemas = factory.optimization_schemas_from_molecules(
molecules=input_molecule, processors=2
)
# create a client to interface with the executor
settings = Settings()
client = BespokeFitClient(settings=settings)
with BespokeExecutor(
n_fragmenter_workers=1,
n_optimizer_workers=1,
n_qc_compute_workers=2,
qc_compute_worker_config=BespokeWorkerConfig(n_cores=1),
) as executor:
# Submit our workflow to the executor
for workflow_schema in reversed(workflow_schemas):
task_id = client.submit_optimization(input_schema=workflow_schema)
# Wait until the executor is done
output = client.wait_until_complete(task_id)
if output.status == "success":
# Save the resulting force field to an OFFXML file
output.bespoke_force_field.to_file("output-ff-00.offxml")
elif output.status == "errored":
# OR the print the error message if unsuccessful
print(output.error)
# factory.to_file("workflow-factory.yaml")
# factory = BespokeWorkflowFactory.from_file("workflow-factory.yaml")