-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from lauragranmar/psi4
Added basic support for psi4
- Loading branch information
Showing
4 changed files
with
272 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import basis_set_exchange | ||
import numpy as np | ||
|
||
from ccinput.utilities import ( | ||
get_method, | ||
get_solvent, | ||
get_basis_set, | ||
clean_xyz, | ||
get_distance, | ||
get_angle, | ||
get_dihedral, | ||
get_npxyz, | ||
) | ||
from ccinput.calculation import Calculation | ||
from ccinput.constants import CalcType, ATOMIC_NUMBER, LOWERCASE_ATOMIC_SYMBOLS | ||
from ccinput.exceptions import UnimplementedError | ||
|
||
|
||
class Psi4Calculation: | ||
TEMPLATE = """ | ||
molecule {{ | ||
{charge} {multiplicity} | ||
{coordinates} | ||
}} | ||
{command_line} | ||
""" | ||
|
||
CALC_TYPES = { | ||
CalcType.SP: ["sp","energy"], | ||
CalcType.OPT: ["optimize"], | ||
# CalcType.CONSTR_OPT, | ||
# CalcType.FREQ, | ||
# CalcType.TS, | ||
# CalcType.OPTFREQ, | ||
} | ||
|
||
def __init__(self, calc: Calculation): | ||
self.calc = calc | ||
self.has_scan = False | ||
self.appendix = [] | ||
self.command_line = "" | ||
|
||
self.commands = {} | ||
self.solvation_radii = {} | ||
|
||
self.confirmed_specifications = "" | ||
self.xyz_structure = "" | ||
self.input_file = "" | ||
|
||
if self.calc.type not in self.CALC_TYPES: | ||
raise UnimplementedError(f"Calculation Type {self.calc.type} not implemented yet for psi4" | ||
) | ||
self.type_method = "" | ||
|
||
self.handle_specifications() | ||
self.handle_command() | ||
self.handle_xyz() | ||
|
||
self.handle_solvation() | ||
|
||
|
||
|
||
self.create_input_file() | ||
|
||
def clean(self, s): | ||
WHITELIST = set( | ||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/()=-,. " | ||
) | ||
return "".join([c for c in s if c in WHITELIST]) | ||
|
||
def add_option(self, key, option): | ||
_option = option.strip() | ||
if key in self.commands: | ||
if _option not in self.commands[key]: | ||
self.commands[key].append(_option) | ||
else: | ||
self.commands[key] = [_option] | ||
|
||
def add_options(self, key, options): | ||
for option in options: | ||
self.add_option(key, option) | ||
|
||
def handle_specifications(self): | ||
return | ||
|
||
def handle_command(self): | ||
#method label, can be used to specifyiing xc func or the level of theory. | ||
method = get_method(self.calc.parameters.method,'psi4') | ||
|
||
basis_set = get_basis_set(self.calc.parameters.basis_set, 'psi4') | ||
|
||
if self.calc.type == CalcType.SP: | ||
self.command_line += f"energy('{method}/{basis_set}')" | ||
elif self.calc.type == CalcType.OPT: | ||
self.command_line += f"optimize('{method}/{basis_set}')" | ||
else: | ||
raise UnimplementedError(f"Calculation Type {self.calc.type} not implemented yet for psi4") | ||
|
||
|
||
|
||
def handle_xyz(self): | ||
lines = [i + "\n" for i in clean_xyz(self.calc.xyz).split("\n") if i != ""] | ||
self.xyz_structure = "".join(lines) | ||
|
||
def handle_solvation(self): | ||
return | ||
|
||
|
||
|
||
|
||
def create_input_file(self) -> None: | ||
self.input_file = self.TEMPLATE.format( | ||
charge= self.calc.charge, | ||
multiplicity = self.calc.multiplicity, | ||
coordinates = self.xyz_structure, | ||
command_line = self.command_line | ||
) | ||
return | ||
|
||
|
||
|
||
@property | ||
def output(self): | ||
return self.input_file |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
from ccinput.tests.testing_utilities import InputTests | ||
from ccinput.exceptions import InvalidParameter, ImpossibleCalculation | ||
|
||
|
||
class Psi4Tests(InputTests): | ||
# def test_sp_SE(self): | ||
# params = { | ||
|
||
# } | ||
|
||
|
||
# inp = self.generate_calculation(**params) | ||
|
||
# REF = """ | ||
|
||
# """ | ||
|
||
# self.assertTrue(self.is_equivalent(REF, inp.input_file)) | ||
|
||
def test_sp_HF(self): | ||
params = { | ||
"type": "Energy", | ||
"file": "Cl.xyz", | ||
"software": "psi4", | ||
"method": "hf", | ||
"basis_set": "sto3g", | ||
"charge": "-1", | ||
"multiplicity" : "1", | ||
} | ||
inp = self.generate_calculation(**params) | ||
|
||
REF = """ | ||
molecule { | ||
-1 1 | ||
Cl 0.00000000 0.00000000 0.00000000 | ||
} | ||
energy('scf/sto-3g') | ||
""" | ||
|
||
self.assertTrue(self.is_equivalent(REF, inp.input_file)) | ||
|
||
def test_sp_DFT(self): | ||
params = { | ||
"type": "Energy", | ||
"file": "Cl.xyz", | ||
"software": "psi4", | ||
"method": "b3lyp", | ||
"basis_set": "def2-tzvp", | ||
"charge": "-1", | ||
"multiplicity" : "1", | ||
} | ||
|
||
inp = self.generate_calculation(**params) | ||
|
||
REF = """ | ||
molecule { | ||
-1 1 | ||
Cl 0.00000000 0.00000000 0.00000000 | ||
} | ||
energy('b3lyp/def2-tzvp') | ||
""" | ||
self.assertTrue(self.is_equivalent(REF, inp.input_file)) | ||
|
||
def test_opt_HF(self): | ||
params = { | ||
"type": "Geometrical Optimisation", | ||
"file": "Cl.xyz", | ||
"software": "psi4", | ||
"method": "HF", | ||
"basis_set": "ccpVDZ", | ||
"charge": "-1", | ||
"multiplicity" : "1", | ||
} | ||
|
||
inp = self.generate_calculation(**params) | ||
|
||
REF = """ | ||
molecule { | ||
-1 1 | ||
Cl 0.00000000 0.00000000 0.00000000 | ||
} | ||
optimize('scf/cc-pVDZ') | ||
""" | ||
|
||
self.assertTrue(self.is_equivalent(REF, inp.input_file)) | ||
|
||
def test_opt_DFT(self): | ||
params = { | ||
"type": "Opt", | ||
"file": "Cl.xyz", | ||
"software": "psi4", | ||
"method": "b3lyp", | ||
"basis_set": "631g", | ||
"charge": "-1", | ||
} | ||
|
||
inp = self.generate_calculation(**params) | ||
|
||
REF = """ | ||
molecule { | ||
-1 1 | ||
Cl 0.00000000 0.00000000 0.00000000 | ||
} | ||
optimize('b3lyp/6-31G') | ||
""" | ||
|
||
self.assertTrue(self.is_equivalent(REF, inp.input_file)) | ||
|
||
def test_unavailable_calc_type(self): | ||
params = { | ||
"type": "freq", | ||
"file": "Cl.xyz", | ||
"software": "psi4", | ||
"method": "HF", | ||
"basis_set": "cc-pvdz", | ||
"charge": "-1", | ||
} | ||
|
||
self.assertRaises(ImpossibleCalculation, msg=f"Calculation Type of {params['type']} not implemented yet for psi4") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters