Implements More Tests and Begins Dice Refactor Implementation

This commit is contained in:
2023-04-22 11:27:20 -03:00
parent 71744641ff
commit b869ee74fb
19 changed files with 719 additions and 297 deletions

View File

@@ -17,6 +17,7 @@ dacite = "*"
[dev-packages]
pyinstaller = "*"
coverage = "*"
[requires]
python_version = "3.10"
python_version = ">3.8"

149
Pipfile.lock generated
View File

@@ -1,11 +1,11 @@
{
"_meta": {
"hash": {
"sha256": "f68e7183744102bdc470014dfc368a947097de4d482f891b1c9b31d17160fd64"
"sha256": "9af00878e9f259614f72d3c11de93c16ede78176a30d8337c741be06c048c8a8"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.10"
"python_version": ">3.8"
},
"sources": [
{
@@ -41,12 +41,14 @@
},
"intel-openmp": {
"hashes": [
"sha256:1ebce47df0b5ddad77992a70689fd3185df25f47cf901dd8384fd6d05a974f81",
"sha256:77131c2cda75ace2060f6e9cdcc9f9c672ec838c4602fc544ce0858cfe8f416e",
"sha256:adfb32b0dde6b3a95ced62608b05a45a7cfad928054136ddbfe0563e16cbf33c"
"sha256:0ca275fd223bda7b835f3b30221ee462e934468738dcbb26741c57e795f09818",
"sha256:0e3166732d0a2105988e538baaffff1182fd5a23883da255b3bf62c187475b46",
"sha256:39308882e7bcdbd17e2d2b3be96e34ed475f60205bc90cb86694d0bcfc955bbc",
"sha256:523094cd2593d31c71ce2d6b2942389fa9d231dce9f8825bfec9e2fdc545e037",
"sha256:7bd67f60ca3da7dbe39ab2a296b5322f8e8248d59d7573068deeeb9b0f901895"
],
"index": "pypi",
"version": "==2023.0.0"
"version": "==2023.1.0"
},
"nptyping": {
"hashes": [
@@ -99,29 +101,29 @@
},
"pyinstaller": {
"hashes": [
"sha256:314fb883caf3cbf06adbea2b77671bb73c3481568e994af0467ea7e47eb64755",
"sha256:3b74f50a57b1413047042e47033480b7324b091f23dff790a4494af32b377d94",
"sha256:4f4d818588e2d8de4bf24ed018056c3de0c95898ad25719e12d68626161b4933",
"sha256:502a2166165a8e8c3d99c19272e923d2548bac2132424d78910ef9dd8bb11705",
"sha256:5c9632a20faecd6d79f0124afb31e6557414d19be271e572765b474f860f8d76",
"sha256:8d004699c5d71c704c14a5f81eec233faa4f87a3bf0ae68e222b87d63f5dd17e",
"sha256:a62ee598b137202ef2e99d8dbaee6bc7379a6565c3ddf0331decb41b98eff1a2",
"sha256:bacf236b5c2f8f674723a39daca399646dceb470881f842f52e393b9a67ff2f8",
"sha256:bf1f7b7e88b467d7aefcdb2bc9cbd2e856ca88c5ab232c0efe0848f146d3bd5f",
"sha256:ded780f0d3642d7bfc21d97b98d4ec4b41d2fe70c3f5c5d243868612f536e011",
"sha256:e68bcadf32edc1171ccb06117699a6a4f8e924b7c2c8812cfa00fd0186ade4ee",
"sha256:f9361eff44c7108c2312f39d85ed768c4ada7e0aa729046bbcef3ef3c1577d18"
"sha256:247b99c52dc3cf69eba905da30dbca0a8ea309e1058cab44658ac838d9b8f2f0",
"sha256:2d16641a495593d174504263b038a6d3d46b3b15a381ccb216cf6cce67723512",
"sha256:333b4ffda38d9c0a561c38429dd9848d37aa78f3b8ea8a6f2b2e69a60d523c02",
"sha256:6afc7aa4885ffd3e6121a8cf2138830099f874c18cb5869bed8c1a42db82d060",
"sha256:6ecc464bf56919bf2d6bff275f38d85ff08ae747b8ead3a0c26cf85573b3c723",
"sha256:7a1db833bb0302b66ae3ae337fbd5487699658ce869ca4d538b5359b8179e83a",
"sha256:85e39e36d03355423636907a26a9bfa06fdc93cb1086441b19d2d0ca448479fa",
"sha256:915a502802c751bafd92d568ac57468ec6cdf252b8308aa9a167bbc2c565ad2d",
"sha256:9e9a38f41f8280c8e29b294716992852281b41fbe64ba330ebab671efe27b26d",
"sha256:bb7de35cd209a0a0358aec761a273ae951d2161c03728f15d9a640d06a88e472",
"sha256:df97aaf1103a1c485aa3c9947792a86675e370f5ce9b436b4a84e34a4180c8d2",
"sha256:f677fbc151db1eb00ada94e86ed128e7b359cbd6bf3f6ea815afdde687692d46"
],
"index": "pypi",
"version": "==5.8.0"
"version": "==5.10.1"
},
"pyinstaller-hooks-contrib": {
"hashes": [
"sha256:29d052eb73e0ab8f137f11df8e73d464c1c6d4c3044d9dc8df2af44639d8bfbf",
"sha256:bd578781cd6a33ef713584bf3726f7cd60a3e656ec08a6cc7971e39990808cc0"
"sha256:7fb856a81fd06a717188a3175caa77e902035cc067b00b583c6409c62497b23f",
"sha256:e02c5f0ee3d4f5814588c2128caf5036c058ba764aaf24d957bb5311ad8690ad"
],
"markers": "python_version >= '3.7'",
"version": "==2023.0"
"version": "==2023.2"
},
"pyyaml": {
"hashes": [
@@ -249,11 +251,11 @@
},
"setuptools": {
"hashes": [
"sha256:e5fd0a713141a4a105412233c63dc4e17ba0090c8e8334594ac790ec97792330",
"sha256:f106dee1b506dee5102cc3f3e9e68137bbad6d47b616be7991714b0c62204251"
"sha256:6f0839fbdb7e3cfef1fc38d7954f5c1c26bf4eebb155a55c9bf8faf997b9fb67",
"sha256:bb16732e8eb928922eabaa022f881ae2b7cdcfaf9993ef1f5e841a96d32b8e0c"
],
"markers": "python_version >= '3.7'",
"version": "==67.4.0"
"version": "==67.7.1"
},
"typing": {
"hashes": [
@@ -280,39 +282,96 @@
],
"version": "==0.17.3"
},
"pyinstaller": {
"coverage": {
"hashes": [
"sha256:314fb883caf3cbf06adbea2b77671bb73c3481568e994af0467ea7e47eb64755",
"sha256:3b74f50a57b1413047042e47033480b7324b091f23dff790a4494af32b377d94",
"sha256:4f4d818588e2d8de4bf24ed018056c3de0c95898ad25719e12d68626161b4933",
"sha256:502a2166165a8e8c3d99c19272e923d2548bac2132424d78910ef9dd8bb11705",
"sha256:5c9632a20faecd6d79f0124afb31e6557414d19be271e572765b474f860f8d76",
"sha256:8d004699c5d71c704c14a5f81eec233faa4f87a3bf0ae68e222b87d63f5dd17e",
"sha256:a62ee598b137202ef2e99d8dbaee6bc7379a6565c3ddf0331decb41b98eff1a2",
"sha256:bacf236b5c2f8f674723a39daca399646dceb470881f842f52e393b9a67ff2f8",
"sha256:bf1f7b7e88b467d7aefcdb2bc9cbd2e856ca88c5ab232c0efe0848f146d3bd5f",
"sha256:ded780f0d3642d7bfc21d97b98d4ec4b41d2fe70c3f5c5d243868612f536e011",
"sha256:e68bcadf32edc1171ccb06117699a6a4f8e924b7c2c8812cfa00fd0186ade4ee",
"sha256:f9361eff44c7108c2312f39d85ed768c4ada7e0aa729046bbcef3ef3c1577d18"
"sha256:06ddd9c0249a0546997fdda5a30fbcb40f23926df0a874a60a8a185bc3a87d93",
"sha256:0743b0035d4b0e32bc1df5de70fba3059662ace5b9a2a86a9f894cfe66569013",
"sha256:0f3736a5d34e091b0a611964c6262fd68ca4363df56185902528f0b75dbb9c1f",
"sha256:1127b16220f7bfb3f1049ed4a62d26d81970a723544e8252db0efde853268e21",
"sha256:172db976ae6327ed4728e2507daf8a4de73c7cc89796483e0a9198fd2e47b462",
"sha256:182eb9ac3f2b4874a1f41b78b87db20b66da6b9cdc32737fbbf4fea0c35b23fc",
"sha256:1bb1e77a9a311346294621be905ea8a2c30d3ad371fc15bb72e98bfcfae532df",
"sha256:1fd78b911aea9cec3b7e1e2622c8018d51c0d2bbcf8faaf53c2497eb114911c1",
"sha256:20d1a2a76bb4eb00e4d36b9699f9b7aba93271c9c29220ad4c6a9581a0320235",
"sha256:21b154aba06df42e4b96fc915512ab39595105f6c483991287021ed95776d934",
"sha256:2c2e58e45fe53fab81f85474e5d4d226eeab0f27b45aa062856c89389da2f0d9",
"sha256:2c3b2803e730dc2797a017335827e9da6da0e84c745ce0f552e66400abdfb9a1",
"sha256:3146b8e16fa60427e03884301bf8209221f5761ac754ee6b267642a2fd354c48",
"sha256:344e714bd0fe921fc72d97404ebbdbf9127bac0ca1ff66d7b79efc143cf7c0c4",
"sha256:387065e420aed3c71b61af7e82c7b6bc1c592f7e3c7a66e9f78dd178699da4fe",
"sha256:3f04becd4fcda03c0160d0da9c8f0c246bc78f2f7af0feea1ec0930e7c93fa4a",
"sha256:4a42e1eff0ca9a7cb7dc9ecda41dfc7cbc17cb1d02117214be0561bd1134772b",
"sha256:4ea748802cc0de4de92ef8244dd84ffd793bd2e7be784cd8394d557a3c751e21",
"sha256:55416d7385774285b6e2a5feca0af9652f7f444a4fa3d29d8ab052fafef9d00d",
"sha256:5d0391fb4cfc171ce40437f67eb050a340fdbd0f9f49d6353a387f1b7f9dd4fa",
"sha256:63cdeaac4ae85a179a8d6bc09b77b564c096250d759eed343a89d91bce8b6367",
"sha256:72fcae5bcac3333a4cf3b8f34eec99cea1187acd55af723bcbd559adfdcb5535",
"sha256:7c4ed4e9f3b123aa403ab424430b426a1992e6f4c8fd3cb56ea520446e04d152",
"sha256:83957d349838a636e768251c7e9979e899a569794b44c3728eaebd11d848e58e",
"sha256:87ecc7c9a1a9f912e306997ffee020297ccb5ea388421fe62a2a02747e4d5539",
"sha256:8f69770f5ca1994cb32c38965e95f57504d3aea96b6c024624fdd5bb1aa494a1",
"sha256:8f6c930fd70d91ddee53194e93029e3ef2aabe26725aa3c2753df057e296b925",
"sha256:965ee3e782c7892befc25575fa171b521d33798132692df428a09efacaffe8d0",
"sha256:974bc90d6f6c1e59ceb1516ab00cf1cdfbb2e555795d49fa9571d611f449bcb2",
"sha256:981b4df72c93e3bc04478153df516d385317628bd9c10be699c93c26ddcca8ab",
"sha256:aa784405f0c640940595fa0f14064d8e84aff0b0f762fa18393e2760a2cf5841",
"sha256:ae7863a1d8db6a014b6f2ff9c1582ab1aad55a6d25bac19710a8df68921b6e30",
"sha256:aeae2aa38395b18106e552833f2a50c27ea0000122bde421c31d11ed7e6f9c91",
"sha256:b2317d5ed777bf5a033e83d4f1389fd4ef045763141d8f10eb09a7035cee774c",
"sha256:be19931a8dcbe6ab464f3339966856996b12a00f9fe53f346ab3be872d03e257",
"sha256:be9824c1c874b73b96288c6d3de793bf7f3a597770205068c6163ea1f326e8b9",
"sha256:c0045f8f23a5fb30b2eb3b8a83664d8dc4fb58faddf8155d7109166adb9f2040",
"sha256:c86bd45d1659b1ae3d0ba1909326b03598affbc9ed71520e0ff8c31a993ad911",
"sha256:ca0f34363e2634deffd390a0fef1aa99168ae9ed2af01af4a1f5865e362f8623",
"sha256:d298c2815fa4891edd9abe5ad6e6cb4207104c7dd9fd13aea3fdebf6f9b91259",
"sha256:d2a3a6146fe9319926e1d477842ca2a63fe99af5ae690b1f5c11e6af074a6b5c",
"sha256:dfd393094cd82ceb9b40df4c77976015a314b267d498268a076e940fe7be6b79",
"sha256:e58c0d41d336569d63d1b113bd573db8363bc4146f39444125b7f8060e4e04f5",
"sha256:ea3f5bc91d7d457da7d48c7a732beaf79d0c8131df3ab278e6bba6297e23c6c4",
"sha256:ea53151d87c52e98133eb8ac78f1206498c015849662ca8dc246255265d9c3c4",
"sha256:eb0edc3ce9760d2f21637766c3aa04822030e7451981ce569a1b3456b7053f22",
"sha256:f649dd53833b495c3ebd04d6eec58479454a1784987af8afb77540d6c1767abd",
"sha256:f760073fcf8f3d6933178d67754f4f2d4e924e321f4bb0dcef0424ca0215eba1",
"sha256:fa546d66639d69aa967bf08156eb8c9d0cd6f6de84be9e8c9819f52ad499c910",
"sha256:fd214917cabdd6f673a29d708574e9fbdb892cb77eb426d0eae3490d95ca7859",
"sha256:fff5aaa6becf2c6a1699ae6a39e2e6fb0672c2d42eca8eb0cafa91cf2e9bd312"
],
"index": "pypi",
"version": "==5.8.0"
"version": "==7.2.3"
},
"pyinstaller": {
"hashes": [
"sha256:247b99c52dc3cf69eba905da30dbca0a8ea309e1058cab44658ac838d9b8f2f0",
"sha256:2d16641a495593d174504263b038a6d3d46b3b15a381ccb216cf6cce67723512",
"sha256:333b4ffda38d9c0a561c38429dd9848d37aa78f3b8ea8a6f2b2e69a60d523c02",
"sha256:6afc7aa4885ffd3e6121a8cf2138830099f874c18cb5869bed8c1a42db82d060",
"sha256:6ecc464bf56919bf2d6bff275f38d85ff08ae747b8ead3a0c26cf85573b3c723",
"sha256:7a1db833bb0302b66ae3ae337fbd5487699658ce869ca4d538b5359b8179e83a",
"sha256:85e39e36d03355423636907a26a9bfa06fdc93cb1086441b19d2d0ca448479fa",
"sha256:915a502802c751bafd92d568ac57468ec6cdf252b8308aa9a167bbc2c565ad2d",
"sha256:9e9a38f41f8280c8e29b294716992852281b41fbe64ba330ebab671efe27b26d",
"sha256:bb7de35cd209a0a0358aec761a273ae951d2161c03728f15d9a640d06a88e472",
"sha256:df97aaf1103a1c485aa3c9947792a86675e370f5ce9b436b4a84e34a4180c8d2",
"sha256:f677fbc151db1eb00ada94e86ed128e7b359cbd6bf3f6ea815afdde687692d46"
],
"index": "pypi",
"version": "==5.10.1"
},
"pyinstaller-hooks-contrib": {
"hashes": [
"sha256:29d052eb73e0ab8f137f11df8e73d464c1c6d4c3044d9dc8df2af44639d8bfbf",
"sha256:bd578781cd6a33ef713584bf3726f7cd60a3e656ec08a6cc7971e39990808cc0"
"sha256:7fb856a81fd06a717188a3175caa77e902035cc067b00b583c6409c62497b23f",
"sha256:e02c5f0ee3d4f5814588c2128caf5036c058ba764aaf24d957bb5311ad8690ad"
],
"markers": "python_version >= '3.7'",
"version": "==2023.0"
"version": "==2023.2"
},
"setuptools": {
"hashes": [
"sha256:e5fd0a713141a4a105412233c63dc4e17ba0090c8e8334594ac790ec97792330",
"sha256:f106dee1b506dee5102cc3f3e9e68137bbad6d47b616be7991714b0c62204251"
"sha256:6f0839fbdb7e3cfef1fc38d7954f5c1c26bf4eebb155a55c9bf8faf997b9fb67",
"sha256:bb16732e8eb928922eabaa022f881ae2b7cdcfaf9993ef1f5e841a96d32b8e0c"
],
"markers": "python_version >= '3.7'",
"version": "==67.4.0"
"version": "==67.7.1"
}
}
}

View File

@@ -1,3 +1,4 @@
from diceplayer.shared.external.dice import Dice
from diceplayer.player import Player
from pathlib import Path
@@ -9,7 +10,8 @@ import sys
__VERSION = "v0.0.1"
if __name__ == "__main__":
def main():
"""
Read and store the arguments passed to the program
and set the usage and help messages
@@ -63,3 +65,6 @@ if __name__ == "__main__":
player = Player(args.infile)
player.start()
if __name__ == "__main__":
main()

View File

@@ -24,27 +24,27 @@ class DiceDTO(Dataclass):
def __post_init__(self):
if self.ljname is None:
if not isinstance(self.ljname, str):
raise ValueError(
"Error: 'ljname' keyword not specified in config file"
)
if self.outname is None:
if not isinstance(self.outname, str):
raise ValueError(
"Error: 'outname' keyword not specified in config file"
)
if self.dens is None:
if not isinstance(self.dens, float):
raise ValueError(
"Error: 'dens' keyword not specified in config file"
)
if self.nmol == 0:
if not isinstance(self.nmol, list):
raise ValueError(
"Error: 'nmol' keyword not defined appropriately in config file"
)
if self.nstep == 0:
if not isinstance(self.nstep, list):
raise ValueError(
"Error: 'nstep' keyword not defined appropriately in config file"
)

View File

@@ -0,0 +1,18 @@
from diceplayer.shared.environment.molecule import Molecule
from dataclasses import dataclass
from typing import List
@dataclass
class StepDTO:
nprocs: int = None
ncores: int = None
altsteps: int = None
switchcyc: int = None
opt: str = None
nmol: List[int] = None
molecule: List[Molecule] = None
charges: List[float] = None
position: List[float] = None

View File

@@ -79,14 +79,13 @@ class Molecule:
"""
Updated positions based on the center of mass of the molecule
"""
self.center_of_mass()
for atom in self.atom:
atom.rx -= self.com[0]
atom.ry -= self.com[1]
atom.rz -= self.com[2]
self.center_of_mass()
def charges_and_dipole(self) -> List[float]:
"""
Calculates the charges and dipole of the molecule atoms
@@ -119,16 +118,15 @@ class Molecule:
distances = []
dim = len(self.atom)
for atom1 in self.atom:
if atom1.na != ghost_number:
for atom2 in self.atom:
if atom2.na != ghost_number:
for index1, atom1 in enumerate(self.atom):
for index2, atom2 in enumerate(self.atom):
if index1 != index2:
dx = atom1.rx - atom2.rx
dy = atom1.ry - atom2.ry
dz = atom1.rz - atom2.rz
distances.append(math.sqrt(dx ** 2 + dy ** 2 + dz ** 2))
return np.array(distances).reshape(dim, dim)
return np.array(distances).reshape(dim, dim-1)
def inertia_tensor(self) -> NDArray[Shape["3, 3"], Float]:
"""
@@ -156,40 +154,6 @@ class Molecule:
return np.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]])
def axes(self) -> NDArray[Shape["3, 3"], Float]:
"""
Calculates the axes of the molecule
Returns:
NDArray[Shape["3, 3"], Float]: Returns the axes of molecule
"""
eixos = np.zeros(3)
if len(self.atom) == 2:
position1 = np.array([self.atom[0].rx, self.atom[0].ry, self.atom[0].rz])
position2 = np.array([self.atom[1].rx, self.atom[1].ry, self.atom[1].rz])
eixos = position2 - position1
eixos /= linalg.norm(eixos)
elif len(self.atom) > 2:
position1 = np.array([self.atom[0].rx, self.atom[0].ry, self.atom[0].rz])
position2 = np.array([self.atom[1].rx, self.atom[1].ry, self.atom[1].rz])
position3 = np.array([self.atom[2].rx, self.atom[2].ry, self.atom[2].rz])
v1 = position2 - position1
v2 = position3 - position1
v3 = np.cross(v1, v2)
v2 = np.cross(v1, v3)
v1 /= linalg.norm(v1)
v2 /= linalg.norm(v2)
v3 /= linalg.norm(v3)
eixos = np.array(
[[v1[0], v1[1], v1[2]], [v2[0], v2[1], v2[2]], [v3[0], v3[1], v3[2]]]
)
return eixos
def principal_axes(self) -> Tuple[np.ndarray, np.ndarray]:
"""
Calculates the principal axes of the molecule
@@ -201,7 +165,7 @@ class Molecule:
try:
evals, evecs = linalg.eigh(self.inertia_tensor())
except:
except ValueError:
raise RuntimeError("Error: diagonalization of inertia tensor did not converge")
return evals, evecs
@@ -221,38 +185,38 @@ class Molecule:
return position
def updateCharges(self, charges: List[float]) -> None:
def update_charges(self, charges: List[float]) -> None:
for i, atom in enumerate(self.atom):
atom.chg = charges[i]
def update_hessian(
self,
step: np.ndarray,
cur_gradient: np.ndarray,
old_gradient: np.ndarray,
hessian: np.ndarray,
) -> np.ndarray:
"""
Updates the Hessian of the molecule based on the current hessian, the current gradient and the previous gradient
Args:
step (np.ndarray): step value of the iteration
cur_gradient (np.ndarray): current gradient
old_gradient (np.ndarray): previous gradient
hessian (np.ndarray): current hessian
Returns:
np.ndarray: updated hessian of the molecule
"""
dif_gradient = cur_gradient - old_gradient
mat1 = 1 / np.dot(dif_gradient, step) * np.matmul(dif_gradient.T, dif_gradient)
mat2 = 1 / np.dot(step, np.matmul(hessian, step.T).T)
mat2 *= np.matmul(np.matmul(hessian, step.T), np.matmul(step, hessian))
return hessian + mat1 - mat2
# @staticmethod
# def update_hessian(
# step: np.ndarray,
# cur_gradient: np.ndarray,
# old_gradient: np.ndarray,
# hessian: np.ndarray,
# ) -> np.ndarray:
# """
# Updates the Hessian of the molecule based on the current hessian, the current gradient and the previous gradient
#
# Args:
# step (np.ndarray): step value of the iteration
# cur_gradient (np.ndarray): current gradient
# old_gradient (np.ndarray): previous gradient
# hessian (np.ndarray): current hessian
#
# Returns:
# np.ndarray: updated hessian of the molecule
# """
#
# dif_gradient = cur_gradient - old_gradient
#
# mat1 = 1 / np.dot(dif_gradient, step) * np.matmul(dif_gradient.T, dif_gradient)
# mat2 = 1 / np.dot(step, np.matmul(hessian, step.T).T)
# mat2 *= np.matmul(np.matmul(hessian, step.T), np.matmul(step, hessian))
#
# return hessian + mat1 - mat2
def sizes_of_molecule(self) -> List[float]:
"""
@@ -267,7 +231,6 @@ class Molecule:
z_list = []
for atom in self.atom:
if atom.na != ghost_number:
x_list.append(atom.rx)
y_list.append(atom.ry)
z_list.append(atom.rz)

View File

@@ -1,13 +1,12 @@
import math
from copy import deepcopy
from typing import List, Tuple, TextIO
import numpy as np
from numpy import linalg
from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.utils.misc import BOHR2ANG
from diceplayer.shared.utils.ptable import atomsymb
from diceplayer.shared.utils.misc import BOHR2ANG
from typing import List, Tuple, TextIO
from copy import deepcopy
from numpy import linalg
import numpy as np
import math
class System:
@@ -35,30 +34,14 @@ class System:
nmols (int): Number of molecules of the new type in the system
m (Molecule): The instance of the new type of molecule
"""
if isinstance(m, Molecule) is False:
raise TypeError("Error: molecule is not a Molecule instance")
self.molecule.append(m)
if isinstance(nmols, int) is False:
raise TypeError("Error: nmols is not an integer")
self.nmols.append(nmols)
def center_of_mass_distance(self, a: int, b: int) -> float:
"""
Calculates the distance between the center of mass of two molecules
Args:
a (Molecule): First Molecule Instance
b (Molecule): Second Molecule Instance
Returns:
float: module of the distance between the two center of masses
"""
com1 = self.molecule[a].center_of_mass()
com2 = self.molecule[b].center_of_mass()
dx = com1[0] - com2[0]
dy = com1[1] - com2[1]
dz = com1[2] - com2[2]
distance = math.sqrt(dx**2 + dy**2 + dz**2)
return distance
def rmsd_fit(self, p_index: int, r_index: int) -> Tuple[float, Molecule]:
projecting_mol = self.molecule[p_index]
@@ -135,6 +118,64 @@ class System:
return rmsd, projected_mol
# def center_of_mass_distance(self, a: int, b: int) -> float:
# """
# Calculates the distance between the center of mass of two molecules
#
# Args:
# a (Molecule): First Molecule Instance
# b (Molecule): Second Molecule Instance
#
# Returns:
# float: module of the distance between the two center of masses
# """
#
# com1 = self.molecule[a].center_of_mass()
# com2 = self.molecule[b].center_of_mass()
# dx = com1[0] - com2[0]
# dy = com1[1] - com2[1]
# dz = com1[2] - com2[2]
# distance = math.sqrt(dx**2 + dy**2 + dz**2)
#
# return distance
# def nearest_image(
# self,
# index_r: int,
# index_m: int,
# lx: float,
# ly: float,
# lz: float,
# criterium=None,
# ) -> Tuple[float, Molecule]:
#
# if criterium in None:
# criterium = "com"
#
# if criterium != "com" and criterium != "min":
# raise RuntimeError("Error in value passed to function nearest_image")
#
# min_dist = 1e20
#
# for i in range(-1, 2):
# for j in range(-1, 2):
# for k in range(-1, 2):
#
# tr_vector = [i * lx, j * ly, k * lz]
# self.add_molecule(self.molecule[index_m].translate(tr_vector))
#
# if criterium == "com":
# dist = self.center_of_mass_distance(index_r, -1)
# else:
# dist = self.minimum_distance(index_r, -1)
#
# if dist < min_dist:
# min_dist = dist
# nearestmol = deepcopy(self.molecule[-1])
#
# self.molecule.pop(-1)
#
# return min_dist, nearestmol
def update_molecule(self, position: np.ndarray, fh: TextIO) -> None:
"""Updates the position of the molecule in the Output file
@@ -158,43 +199,6 @@ class System:
fh.write("\nProjected new conformation of reference molecule with RMSD fit\n")
fh.write("RMSD = {:>8.5f} Angstrom\n".format(rmsd))
def nearest_image(
self,
index_r: int,
index_m: int,
lx: float,
ly: float,
lz: float,
criterium=None,
) -> Tuple[float, Molecule]:
if criterium in None:
criterium = "com"
if criterium != "com" and criterium != "min":
raise RuntimeError("Error in value passed to function nearest_image")
min_dist = 1e20
for i in range(-1, 2):
for j in range(-1, 2):
for k in range(-1, 2):
tr_vector = [i * lx, j * ly, k * lz]
self.add_molecule(self.molecule[index_m].translate(tr_vector))
if criterium == "com":
dist = self.center_of_mass_distance(index_r, -1)
else:
dist = self.minimum_distance(index_r, -1)
if dist < min_dist:
min_dist = dist
nearestmol = deepcopy(self.molecule[-1])
self.molecule.pop(-1)
return min_dist, nearestmol
def print_geom(self, cycle: int, fh: TextIO) -> None:
"""

View File

@@ -18,7 +18,7 @@ class External(ABC):
pass
@abstractmethod
def start(self):
def start(self, cycle: int):
pass
@abstractmethod

View File

@@ -0,0 +1 @@
from .__external import External

View File

@@ -1,9 +1,13 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from diceplayer.shared.external.__external import External
from diceplayer.shared.config.dice_dto import DiceDTO
from diceplayer.shared.external import External
from multiprocessing import Process, connection
from setproctitle import setproctitle
import sys
class Dice(External):
__slots__ = ['config', 'step']
def __init__(self, data: dict):
self.config: DiceDTO = self.set_config(data)
@@ -12,11 +16,38 @@ class Dice(External):
def set_config(data: dict) -> DiceDTO:
return DiceDTO.from_dict(data)
def configure(self):
pass
def configure(self, step: any):
self.step = step
def start(self):
pass
def start(self, cycle: int):
procs = [
Process(target=self._simulation_process, args=(cycle, proc))
for proc in range(1, self.config.ncores+1)
]
for proc in procs:
proc.start()
connection.wait(p.sentinel for p in procs)
def reset(self):
pass
del self.step
def _simulation_process(self, cycle: int, proc: int):
setproctitle(f"diceplayer-step{cycle:0d}-p{proc:0d}")
try:
self._make_proc_dir(cycle, proc)
self._make_dice_inputs(cycle, proc)
self._run_dice(cycle, proc)
except Exception as err:
sys.exit(err)
def _make_proc_dir(self, cycle, proc):
raise NotImplementedError
def _make_dice_inputs(self, cycle, proc):
raise NotImplementedError
def _run_dice(self, cycle, proc):
raise NotImplementedError

View File

@@ -1,6 +1,5 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from diceplayer.shared.config.gaussian_dto import GaussianDTO
from diceplayer.shared.external.__external import External
from diceplayer.shared.external import External
class Gaussian(External):

View File

View File

@@ -0,0 +1,89 @@
from diceplayer.shared.config.dice_dto import DiceDTO
import unittest
class TestDiceDto(unittest.TestCase):
def test_class_instantiation(self):
dice_dto = DiceDTO(
ljname='test',
outname='test',
ncores=1,
dens=1.0,
nmol=[1],
nstep=[1],
)
self.assertIsInstance(dice_dto, DiceDTO)
def test_validate_jname(self):
with self.assertRaises(ValueError) as ex:
DiceDTO(
ljname=None,
outname='test',
ncores=1,
dens=1.0,
nmol=[1],
nstep=[1],
)
self.assertEqual(ex.exception, "Error: 'ljname' keyword not specified in config file")
def test_validate_outname(self):
with self.assertRaises(ValueError) as ex:
DiceDTO(
ljname='test',
outname=None,
ncores=1,
dens=1.0,
nmol=[1],
nstep=[1],
)
self.assertEqual(ex.exception, "Error: 'outname' keyword not specified in config file")
def test_validate_dens(self):
with self.assertRaises(ValueError) as ex:
DiceDTO(
ljname='test',
outname='test',
ncores=1,
dens=None,
nmol=[1],
nstep=[1],
)
self.assertEqual(ex.exception, "Error: 'dens' keyword not specified in config file")
def test_validate_nmol(self):
with self.assertRaises(ValueError) as ex:
DiceDTO(
ljname='test',
outname='test',
ncores=1,
dens=1.0,
nmol=0,
nstep=[1],
)
self.assertEqual(ex.exception, "Error: 'nmol' keyword not defined appropriately in config file")
def test_validate_nstep(self):
with self.assertRaises(ValueError) as ex:
DiceDTO(
ljname='test',
outname='test',
ncores=1,
dens=1.0,
nmol=[1],
nstep=0,
)
self.assertEqual(ex.exception, "Error: 'nstep' keyword not defined appropriately in config file")
def test_from_dict(self):
dice_dto = DiceDTO.from_dict({
'ljname': 'test',
'outname': 'test',
'ncores': 1,
'dens': 1.0,
'nmol': [1],
'nstep': [1],
})
self.assertIsInstance(dice_dto, DiceDTO)

View File

@@ -1,61 +0,0 @@
from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.environment.atom import Atom
import numpy.testing as npt
import unittest
class TestMolecule(unittest.TestCase):
def test_class_instantiation(self):
mol = Molecule('test')
self.assertIsInstance(mol, Molecule)
def test_add_atom(self):
mol = Molecule('test')
mol.add_atom(
Atom(
lbl=1,
na=1,
rx=1.0,
ry=1.0,
rz=1.0,
chg=1.0,
eps=1.0,
sig=1.0,
)
)
self.assertEqual(len(mol.atom), 1)
npt.assert_equal(mol.com, [1., 1., 1.])
def test_center_of_mass(self):
mol = Molecule('test')
mol.add_atom(
Atom(
lbl=1,
na=1,
rx=1.0,
ry=1.0,
rz=1.0,
chg=1.0,
eps=1.0,
sig=1.0,
)
)
mol.add_atom(
Atom(
lbl=1,
na=1,
rx=0.0,
ry=0.0,
rz=0.0,
chg=1.0,
eps=1.0,
sig=1.0,
)
)
npt.assert_equal(mol.com, [.5, .5, .5])

View File

@@ -0,0 +1,147 @@
from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.environment.atom import Atom
import numpy.testing as npt
import unittest
class TestMolecule(unittest.TestCase):
def test_class_instantiation(self):
mol = Molecule('test')
self.assertIsInstance(mol, Molecule)
def test_add_atom(self):
mol = Molecule('test')
mol.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
)
self.assertEqual(len(mol.atom), 1)
npt.assert_equal(mol.com, [1., 1., 1.])
def test_center_of_mass(self):
mol = Molecule('test')
mol.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
)
mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
)
npt.assert_equal(mol.com, [.5, .5, .5])
def test_center_of_mass_to_origin(self):
mol = Molecule('test')
mol.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
)
mol.center_of_mass_to_origin()
npt.assert_equal(mol.com, [0, 0, 0])
def test_charges_and_dipole(self):
mol = Molecule('test')
mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
)
actual_charge_dipole_array = mol.charges_and_dipole()
expected_charge_dipole_array = [1.0, 0.0, 0.0, 0.0, 0.0]
npt.assert_equal(
actual_charge_dipole_array,
expected_charge_dipole_array
)
def test_distances_between_atoms(self):
mol = Molecule('test')
mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
)
mol.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
)
expected_distance_between_atoms = [[1.73205081], [1.73205081]]
actual_distance_between_atoms = mol.distances_between_atoms()
npt.assert_almost_equal(
expected_distance_between_atoms,
actual_distance_between_atoms
)
def test_inertia_tensor(self):
mol = Molecule('test')
mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
)
mol.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
)
expected_inertia_tensor = [[1.00790, -0.50395, -0.50395],
[-0.50395, 1.0079, -0.50395],
[-0.50395, -0.50395, 1.0079]]
actual_inertia_tensor = mol.inertia_tensor()
npt.assert_equal(
expected_inertia_tensor,
actual_inertia_tensor
)
def test_principal_axes(self):
mol = Molecule('test')
mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
)
expected_evals, expected_evecs = [0., 0., 0.], [[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]
evals, evecs = mol.principal_axes()
npt.assert_equal(expected_evals, evals)
npt.assert_equal(expected_evecs, evecs)
def test_read_position(self):
mol = Molecule('test')
mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
)
expected_position = mol.read_position()
actual_position = mol.read_position()
npt.assert_equal(
expected_position,
actual_position
)
def test_update_charges(self):
mol = Molecule('test')
mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
)
expected_charges = [2.]
mol.update_charges(expected_charges)
actual_charges = list(map(lambda a: a.chg, mol.atom))
npt.assert_equal(
expected_charges,
actual_charges
)

View File

@@ -0,0 +1,50 @@
from diceplayer.shared.environment.atom import Atom
from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.environment.system import System
import unittest
class TestSystem(unittest.TestCase):
def test_class_instantiation(self):
system = System()
self.assertIsInstance(system, System)
def test_add_type(self):
system = System()
system.add_type(0, Molecule('test'))
self.assertIsInstance(system.molecule, list)
self.assertIsInstance(system.nmols, list)
with self.assertRaises(TypeError) as ex:
system.add_type(0, 'test')
self.assertEqual(ex.exception, 'Error: molecule is not a Molecule instance')
with self.assertRaises(TypeError) as ex:
system.add_type('test', Molecule('test'))
self.assertEqual(ex.exception, 'Error: nmols is not an integer')
def test_center_of_mass_distance(self):
system = System()
a = Molecule('test')
a.add_atom(
Atom(lbl=0, na=1, rx=0, ry=0, rz=0, chg=0, eps=0, sig=0)
)
system.add_type(1, a)
b = Molecule('test')
b.add_atom(
Atom(lbl=0, na=1, rx=0, ry=0, rz=0, chg=0, eps=0, sig=0)
)
system.add_type(1, b)
self.assertIsInstance(system.center_of_mass_distance(0, 1), float)
if __name__ == '__main__':
unittest.main()

0
tests/shared/external/__init__.py vendored Normal file
View File

116
tests/shared/external/test_dice.py vendored Normal file
View File

@@ -0,0 +1,116 @@
from diceplayer.shared.external.dice import Dice
from unittest import mock
import unittest
class TestDice(unittest.TestCase):
def test_class_instantiation(self):
dice = Dice(
{
'ljname': 'test',
'outname': 'test',
'ncores': 1,
'dens': 1.0,
'nmol': [1],
'nstep': [1],
}
)
self.assertIsInstance(dice, Dice)
def test_configure(self):
dice = Dice(
{
'ljname': 'test',
'outname': 'test',
'ncores': 1,
'dens': 1.0,
'nmol': [1],
'nstep': [1],
}
)
self.assertFalse(hasattr(dice, 'step'))
dice.configure('test')
self.assertTrue(hasattr(dice, 'step'))
def test_reset(self):
dice = Dice(
{
'ljname': 'test',
'outname': 'test',
'ncores': 1,
'dens': 1.0,
'nmol': [1],
'nstep': [1],
}
)
dice.configure('test')
self.assertTrue(hasattr(dice, 'step'))
dice.reset()
self.assertFalse(hasattr(dice, 'step'))
@mock.patch('diceplayer.shared.external.dice.connection')
@mock.patch('diceplayer.shared.external.dice.Process')
def test_start(self, mock_process, mock_connection):
dice = Dice(
{
'ljname': 'test',
'outname': 'test',
'ncores': 1,
'dens': 1.0,
'nmol': [1],
'nstep': [1],
}
)
dice.start(1)
self.assertTrue(mock_process.called)
self.assertTrue(mock_connection.wait.called)
def test_simulation_process_raises_exception(self):
dice = Dice(
{
'ljname': 'test',
'outname': 'test',
'ncores': 1,
'dens': 1.0,
'nmol': [1],
'nstep': [1],
}
)
with self.assertRaises(SystemExit):
dice._simulation_process(1, 1)
@mock.patch('diceplayer.shared.external.dice.Dice._make_proc_dir')
@mock.patch('diceplayer.shared.external.dice.Dice._make_dice_inputs')
@mock.patch('diceplayer.shared.external.dice.Dice._run_dice')
def test_simulation_process(self, mock_run_dice, mock_make_dice_inputs, mock_make_proc_dir):
dice = Dice(
{
'ljname': 'test',
'outname': 'test',
'ncores': 1,
'dens': 1.0,
'nmol': [1],
'nstep': [1],
}
)
dice._simulation_process(1, 1)
self.assertTrue(dice._make_proc_dir.called)
self.assertTrue(dice._make_dice_inputs.called)
self.assertTrue(dice._run_dice.called)
if __name__ == '__main__':
unittest.main()