Initial Work on Reading Crystal and Creation Gaussian Input
This commit is contained in:
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
0
tests/shared/__init__.py
Normal file
0
tests/shared/__init__.py
Normal file
0
tests/shared/config/__init__.py
Normal file
0
tests/shared/config/__init__.py
Normal file
21
tests/shared/config/test_config.py
Normal file
21
tests/shared/config/test_config.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from crystalpol.shared.config import Config
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class TestConfig(unittest.TestCase):
|
||||
def test_class_instantiation(self):
|
||||
config = Config(
|
||||
mem=1,
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10
|
||||
)
|
||||
self.assertIsInstance(config, Config)
|
||||
|
||||
def test_config_raises_exception(self):
|
||||
with self.assertRaises(ValueError):
|
||||
Config(
|
||||
mem="1",
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10
|
||||
)
|
||||
0
tests/shared/system/__init__.py
Normal file
0
tests/shared/system/__init__.py
Normal file
19
tests/shared/system/test_atom.py
Normal file
19
tests/shared/system/test_atom.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from crystalpol.shared.system.atom import Atom
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class TestAtom(unittest.TestCase):
|
||||
def test_atom_instantiation(self):
|
||||
atom = Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
|
||||
self.assertIsInstance(atom, Atom)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
102
tests/shared/system/test_crystal.py
Normal file
102
tests/shared/system/test_crystal.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import unittest
|
||||
|
||||
from crystalpol.shared.system.atom import Atom
|
||||
from crystalpol.shared.system.crystal import Crystal
|
||||
from crystalpol.shared.system.molecule import Molecule
|
||||
|
||||
|
||||
class TestCrystal(unittest.TestCase):
|
||||
def test_class_instantiation(self):
|
||||
# Note that this is not a valid crystal
|
||||
crystal_structure = [
|
||||
['H']
|
||||
]
|
||||
|
||||
crystal = Crystal(crystal_structure)
|
||||
|
||||
self.assertIsInstance(crystal, Crystal)
|
||||
|
||||
def test_is_valid_cell(self):
|
||||
crystal_structure = [
|
||||
['H ']
|
||||
]
|
||||
|
||||
crystal = Crystal(crystal_structure)
|
||||
|
||||
molecule = Molecule("TESTE")
|
||||
molecule.add_atom(
|
||||
Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
)
|
||||
|
||||
self.assertTrue(crystal._is_valid_cell([molecule]))
|
||||
|
||||
molecule.add_atom(
|
||||
Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
)
|
||||
|
||||
self.assertFalse(crystal._is_valid_cell([molecule]))
|
||||
|
||||
def test_add_cell(self):
|
||||
# Note that this is not a valid crystal
|
||||
crystal_structure = [
|
||||
['H ']
|
||||
]
|
||||
|
||||
crystal = Crystal(crystal_structure)
|
||||
|
||||
molecule = Molecule("TESTE")
|
||||
molecule.add_atom(
|
||||
Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
)
|
||||
|
||||
crystal.add_cell([molecule])
|
||||
|
||||
self.assertIsInstance(crystal, Crystal)
|
||||
|
||||
def test_add_cell_raises_exception(self):
|
||||
# Note that this is not a valid crystal
|
||||
crystal_structure = [
|
||||
['H ']
|
||||
]
|
||||
|
||||
crystal = Crystal(crystal_structure)
|
||||
|
||||
molecule = Molecule("TESTE")
|
||||
molecule.add_atom(
|
||||
Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
)
|
||||
molecule.add_atom(
|
||||
Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
crystal.add_cell([molecule])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
87
tests/shared/system/test_molecule.py
Normal file
87
tests/shared/system/test_molecule.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from crystalpol.shared.system.molecule import Molecule
|
||||
from crystalpol.shared.system.atom import Atom
|
||||
|
||||
import io
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class TestMolecule(unittest.TestCase):
|
||||
def test_class_instantiation(self):
|
||||
molecule = Molecule("TEST")
|
||||
|
||||
self.assertEqual(molecule.mol_name, "TEST")
|
||||
self.assertIsInstance(molecule, Molecule)
|
||||
|
||||
def test_add_atom(self):
|
||||
molecule = Molecule("TEST")
|
||||
|
||||
atom = Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
|
||||
molecule.add_atom(atom)
|
||||
|
||||
self.assertEqual(len(molecule.atoms), 1)
|
||||
self.assertEqual(molecule.atoms[0], atom)
|
||||
|
||||
def test_update_charges(self):
|
||||
molecule = Molecule("TEST")
|
||||
|
||||
atom = Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
|
||||
molecule.add_atom(atom)
|
||||
|
||||
molecule.update_charges([1])
|
||||
|
||||
self.assertEqual(molecule.atoms[-1].chg, 1)
|
||||
|
||||
def test_update_charges_raises_exception(self):
|
||||
molecule = Molecule("TEST")
|
||||
|
||||
atom = Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
|
||||
molecule.add_atom(atom)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
molecule.update_charges([1, 1])
|
||||
|
||||
def test_print_mol_info(self):
|
||||
molecule = Molecule("TEST")
|
||||
|
||||
atom = Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
|
||||
molecule.add_atom(atom)
|
||||
|
||||
with io.StringIO() as file:
|
||||
molecule.print_mol_info(file)
|
||||
|
||||
file.seek(0)
|
||||
info_string = file.read()
|
||||
|
||||
self.assertIsNotNone(info_string)
|
||||
self.assertTrue(len(info_string) > 0)
|
||||
self.assertTrue("Molecule Name: TEST" in info_string)
|
||||
self.assertTrue("H r: [0, 0, 0] charge: None" in info_string)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
199
tests/shared/test_gaussian.py
Normal file
199
tests/shared/test_gaussian.py
Normal file
@@ -0,0 +1,199 @@
|
||||
from crystalpol.shared.system.molecule import Molecule
|
||||
from crystalpol.shared.system.crystal import Crystal
|
||||
from crystalpol.shared.system.atom import Atom
|
||||
from crystalpol.shared.config import Config
|
||||
from crystalpol.gaussian import Gaussian
|
||||
|
||||
from io import StringIO
|
||||
|
||||
from unittest import mock, TestCase
|
||||
import unittest
|
||||
|
||||
|
||||
class TestGaussian(TestCase):
|
||||
|
||||
def test_class_instantiation(self):
|
||||
gaussian = Gaussian(
|
||||
Config(
|
||||
mem=1,
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10
|
||||
)
|
||||
)
|
||||
|
||||
self.assertIsInstance(gaussian, Gaussian)
|
||||
|
||||
def test_check_keyword(self):
|
||||
gaussian = Gaussian(
|
||||
Config(
|
||||
mem=1,
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10,
|
||||
pop="lorota"
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(gaussian.config.pop, "chelpg")
|
||||
|
||||
@mock.patch('crystalpol.gaussian.os')
|
||||
def test_create_simulation_dir(self, os_mock):
|
||||
os_mock.path.exists.return_value = False
|
||||
|
||||
gaussian = Gaussian(
|
||||
Config(
|
||||
mem=1,
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10
|
||||
)
|
||||
)
|
||||
gaussian.create_simulation_dir()
|
||||
|
||||
self.assertTrue(os_mock.makedirs.called)
|
||||
|
||||
@mock.patch('crystalpol.gaussian.os')
|
||||
def test_create_simulation_dir_raises_exception(self, os_mock):
|
||||
os_mock.path.exists.return_value = True
|
||||
gaussian = Gaussian(
|
||||
Config(
|
||||
mem=1,
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10
|
||||
)
|
||||
)
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
gaussian.create_simulation_dir()
|
||||
|
||||
@mock.patch('crystalpol.gaussian.open')
|
||||
def test_make_gaussian_input_cycle_1(self, open_mock):
|
||||
|
||||
open_mock.return_value = StringIO()
|
||||
|
||||
crystal = self.create_crystal()
|
||||
|
||||
gaussian = Gaussian(
|
||||
Config(
|
||||
mem=1,
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10
|
||||
)
|
||||
)
|
||||
gaussian_input = gaussian.make_gaussian_input(1, crystal)
|
||||
expected_output = """\
|
||||
%Mem=1MB
|
||||
%Nprocs=1
|
||||
#P b3lyp/aug-cc-pVDZ Pop = chelpg Density = Current NoSymm
|
||||
|
||||
crystalpol - Cycle number 1
|
||||
|
||||
0, 1
|
||||
H 0.00000 0.00000 0.00000
|
||||
"""
|
||||
self.assertEqual(gaussian_input, expected_output)
|
||||
|
||||
@mock.patch('crystalpol.gaussian.open')
|
||||
def test_make_gaussian_input_cycle_2(self, open_mock):
|
||||
|
||||
open_mock.return_value = StringIO()
|
||||
|
||||
crystal = self.create_crystal()
|
||||
|
||||
gaussian = Gaussian(
|
||||
Config(
|
||||
mem=1,
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10
|
||||
)
|
||||
)
|
||||
gaussian_input = gaussian.make_gaussian_input(2, "test", crystal)
|
||||
expected_output = """\
|
||||
%Mem=1MB
|
||||
%Nprocs=1
|
||||
#P b3lyp/aug-cc-pVDZ Pop = chelpg Density = Current NoSymm charge
|
||||
|
||||
crystalpol - Cycle number 2
|
||||
|
||||
0, 1
|
||||
H 0.00000 0.00000 0.00000
|
||||
|
||||
H 0.00000 0.00000 0.00000
|
||||
"""
|
||||
self.assertEqual(gaussian_input, expected_output)
|
||||
|
||||
def test_make_gaussian_charges(self):
|
||||
|
||||
file = StringIO()
|
||||
crystal = self.create_crystal()
|
||||
|
||||
gaussian = Gaussian(
|
||||
Config(
|
||||
mem=1,
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10
|
||||
)
|
||||
)
|
||||
gaussian.make_gaussian_charges(file, crystal)
|
||||
file.seek(0)
|
||||
|
||||
charges_string = file.read()
|
||||
expected_charges = '\nH 0.00000 0.00000 0.00000\n'
|
||||
|
||||
self.assertEqual(charges_string, expected_charges)
|
||||
|
||||
@mock.patch('crystalpol.gaussian.subprocess.call', autospec=True, return_value=0)
|
||||
@mock.patch('crystalpol.gaussian.Gaussian.make_gaussian_input')
|
||||
def test_run(self, subprocess_call_mock, make_gaussian_input_mock):
|
||||
|
||||
gaussian = Gaussian(
|
||||
Config(
|
||||
mem=1,
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10
|
||||
)
|
||||
)
|
||||
gaussian.run(1, self.create_crystal())
|
||||
|
||||
self.assertTrue(subprocess_call_mock.called)
|
||||
|
||||
@mock.patch('crystalpol.gaussian.subprocess.call', autospec=True, return_value=1)
|
||||
@mock.patch('crystalpol.gaussian.Gaussian.make_gaussian_input')
|
||||
def test_run_raises_exception(self, subprocess_call_mock, make_gaussian_input_mock):
|
||||
|
||||
gaussian = Gaussian(
|
||||
Config(
|
||||
mem=1,
|
||||
level="b3lyp/aug-cc-pVDZ",
|
||||
n_atoms=10
|
||||
)
|
||||
)
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
gaussian.run(1, self.create_crystal())
|
||||
|
||||
@staticmethod
|
||||
def create_crystal():
|
||||
|
||||
crystal_structure = [
|
||||
['H ']
|
||||
]
|
||||
|
||||
crystal = Crystal(crystal_structure)
|
||||
|
||||
molecule = Molecule("TESTE")
|
||||
molecule.add_atom(
|
||||
Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
)
|
||||
|
||||
crystal.add_cell([molecule])
|
||||
crystal.add_cell([molecule])
|
||||
|
||||
return crystal
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
101
tests/test_polarization.py
Normal file
101
tests/test_polarization.py
Normal file
@@ -0,0 +1,101 @@
|
||||
from crystalpol.polarization import Polarization
|
||||
from crystalpol.shared.config import Config
|
||||
from crystalpol.shared.system.atom import Atom
|
||||
from crystalpol.shared.system.molecule import Molecule
|
||||
|
||||
from unittest import TestCase, mock
|
||||
import unittest
|
||||
|
||||
|
||||
GEOM_DATA = """\
|
||||
Cl 0.529511 -1.626652 1.247344
|
||||
N 3.703161 2.470259 1.679277
|
||||
Cl 0.362927 -1.511555 4.375374
|
||||
N 3.582138 2.531106 3.906529
|
||||
"""
|
||||
|
||||
|
||||
class TestPolarization(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = Config(
|
||||
mem=42,
|
||||
n_atoms=2,
|
||||
level="b3lyp/aug-cc-pVDZ"
|
||||
)
|
||||
|
||||
def test_class_instantiation(self):
|
||||
pol = Polarization("geom_file", "outfile", self.config)
|
||||
|
||||
self.assertIsInstance(pol, Polarization)
|
||||
|
||||
def test_get_molecules_from_lines(self):
|
||||
pol = Polarization("geom_file", "outfile", self.config)
|
||||
|
||||
lines = [
|
||||
"Cl 0.529511 -1.626652 1.247344",
|
||||
"N 3.703161 2.470259 1.679277",
|
||||
"Cl 0.362927 -1.511555 4.375374",
|
||||
"N 3.582138 2.531106 3.906529",
|
||||
]
|
||||
|
||||
molecules = pol._get_molecules_from_lines(lines)
|
||||
|
||||
self.assertIsNotNone(molecules)
|
||||
self.assertTrue(any(atom.symbol == "Cl" for atom in molecules[0]))
|
||||
self.assertTrue(any(atom.symbol == "N " for atom in molecules[1]))
|
||||
|
||||
def test_get_molecules_from_lines_raises_exception(self):
|
||||
pol = Polarization("geom_file", "outfile", self.config)
|
||||
|
||||
lines = [
|
||||
"Cl 0.529511 -1.626652 1.247344",
|
||||
"N 3.703161 2.470259 1.679277",
|
||||
"Cl 0.362927 -1.511555 4.375374",
|
||||
"N 3.582138 2.531106 3.906529",
|
||||
"N 3.582138 2.531106 3.906529",
|
||||
]
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
pol._get_molecules_from_lines(lines)
|
||||
|
||||
def test_get_crystal_structure(self):
|
||||
pol = Polarization("geom_file", "outfile", self.config)
|
||||
|
||||
molecule = Molecule("TEST")
|
||||
molecule.add_atom(
|
||||
Atom(
|
||||
na=1,
|
||||
rx=0,
|
||||
ry=0,
|
||||
rz=0,
|
||||
)
|
||||
)
|
||||
|
||||
structure = pol._get_crystal_structure(molecule)
|
||||
self.assertEqual(structure, ['H '])
|
||||
|
||||
@mock.patch('builtins.open', mock.mock_open(read_data=GEOM_DATA))
|
||||
def test_read_crystal(self):
|
||||
pol = Polarization("geom_file", "outfile", self.config)
|
||||
|
||||
pol.read_crystal()
|
||||
|
||||
self.assertIsNotNone(pol.crystal)
|
||||
self.assertEqual(len(pol.crystal), 2)
|
||||
self.assertEqual(len(pol.crystal[0]), 1)
|
||||
|
||||
|
||||
@mock.patch('builtins.open', mock.mock_open(read_data=GEOM_DATA))
|
||||
def test_run(self):
|
||||
pol = Polarization("geom_file", "outfile", self.config)
|
||||
|
||||
pol.run()
|
||||
|
||||
self.assertIsNotNone(pol.crystal)
|
||||
self.assertEqual(len(pol.crystal), 2)
|
||||
self.assertEqual(len(pol.crystal[0]), 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user