Reuse ForceField Parameters From Previous Calculations

Reuse force field atom types and charges assigned in a previous AMS calculation run by using the get_forcefield_params method.

Downloads: Notebook | Script ?

Requires: AMS2027 or later

Initial Imports

import sys
from scm.inputs import AMS, ForceField
from scm.plams import AMSJob

Run/Load Job with ForceField Information

First run a reference calculation where charges are guessed (using DFTB by default):

ref_job = AMSJob.from_input(
    """
Task GeometryOptimization

GeometryOptimization
   Convergence Step=1.0e-3
End

System
   Atoms
      C 0.0 0.0 0.0
      O 1.13 0.0 0.0
      C 0.0 0.0 2.1
      O 1.13 0.0 1.9
   End
End

Engine ForceField
   Verbosity Verbose
   GuessCharges True
EndEngine
"""
)

# Alternatively, load a previously run calculation
# ref_job = AMSJob.load_external("./plams_workdir/plamsjob/ams.rkf")

ref_job.run();
[19.10|12:28:09] JOB plamsjob STARTED
[19.10|12:28:09] JOB plamsjob RUNNING
[19.10|12:28:10] JOB plamsjob FINISHED
[19.10|12:28:10] JOB plamsjob SUCCESSFUL

Reuse ForceField Parameters

Extract the charges and types from the job results and add them as properties on the molecule:

charges, types, patch = ref_job.results.get_forcefield_params()
mol = ref_job.results.get_input_system()
mol.enable_atom_attributes("forcefield")

for i, at in enumerate(mol.atoms):
    at.forcefield.charge = charges[i]
    at.forcefield.type = types[i]
sett = AMS(Task="SinglePoint")
sett.Engine = ForceField(Type="UFF")
# Create a patch file if required
if patch:
    with open("patch.dat", "w") as outfile:
        outfile.write(str(patch))
        outfile.close()
    # For example with:
    # sett.Engine.GAFF.ForceFieldPatchFile = "patch.dat"
job = AMSJob(molecule=mol, settings=sett)
print(job.get_input())
Task SinglePoint
Engine ForceField
    Type UFF
EndEngine

System
   Atoms
      C 0 0 0 forcefield.type=C_1 forcefield.charge=0.2881959742945601
      O 1.13 0 0 forcefield.type=O_2 forcefield.charge=-0.2676126103835761
      C 0 0 2.1 forcefield.type=C_1 forcefield.charge=0.25361504136042523
      O 1.13 0 1.9 forcefield.type=O_2 forcefield.charge=-0.274198405270601
   End
End
job.run();
[19.10|12:28:11] JOB plamsjob STARTED
[19.10|12:28:11] Renaming job plamsjob to plamsjob.002
[19.10|12:28:11] JOB plamsjob.002 RUNNING
[19.10|12:28:11] JOB plamsjob.002 FINISHED
[19.10|12:28:11] JOB plamsjob.002 SUCCESSFUL

Python Script

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

# ## Initial Imports

import sys
from scm.inputs import AMS, ForceField
from scm.plams import AMSJob


# ## Run/Load Job with ForceField Information

# First run a reference calculation where charges are guessed (using DFTB by default):

ref_job = AMSJob.from_input(
    """
Task GeometryOptimization

GeometryOptimization
   Convergence Step=1.0e-3
End

System
   Atoms
      C 0.0 0.0 0.0
      O 1.13 0.0 0.0
      C 0.0 0.0 2.1
      O 1.13 0.0 1.9
   End
End

Engine ForceField
   Verbosity Verbose
   GuessCharges True
EndEngine
"""
)

# Alternatively, load a previously run calculation
# ref_job = AMSJob.load_external("./plams_workdir/plamsjob/ams.rkf")

ref_job.run();


# ## Reuse ForceField Parameters

# Extract the charges and types from the job results and add them as properties on the molecule:

charges, types, patch = ref_job.results.get_forcefield_params()


mol = ref_job.results.get_input_system()
mol.enable_atom_attributes("forcefield")

for i, at in enumerate(mol.atoms):
    at.forcefield.charge = charges[i]
    at.forcefield.type = types[i]


sett = AMS(Task="SinglePoint")
sett.Engine = ForceField(Type="UFF")


# Create a patch file if required
if patch:
    with open("patch.dat", "w") as outfile:
        outfile.write(str(patch))
        outfile.close()
    # For example with:
    # sett.Engine.GAFF.ForceFieldPatchFile = "patch.dat"


job = AMSJob(molecule=mol, settings=sett)


print(job.get_input())


job.run();