Read Potentials and Initial Testing

This commit is contained in:
2023-03-04 16:20:25 -03:00
parent 7a87204181
commit 71744641ff
35 changed files with 793 additions and 2836 deletions

View File

@@ -13,6 +13,7 @@ pyyaml = "*"
nptyping = "*"
intel-openmp = "*"
typing = "*"
dacite = "*"
[dev-packages]
pyinstaller = "*"

180
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "37db6602bae8a383e7907bd2bfb346daf1051cfb240564b5d23de92a0cdd7536"
"sha256": "f68e7183744102bdc470014dfc368a947097de4d482f891b1c9b31d17160fd64"
},
"pipfile-spec": 6,
"requires": {
@@ -31,58 +31,64 @@
"index": "pypi",
"version": "==1.4.0"
},
"intel-openmp": {
"dacite": {
"hashes": [
"sha256:22e09934d9f8f8b864ae68cab95bf43667f00d24e4675eb6d2a4ee089754c439",
"sha256:342c9e2b6e1500a9fb8d39828293ab5f9bb310b81fad7eba5c9d865001b95a7e",
"sha256:6ae4a878135ec08aa16dd97b6d72ac16bb92fad4c6ba40f28b3558d70b1f447a",
"sha256:77414289c14cb48d7f99926da69c9ced9e70c27feb825b0608f304f9d49844ae",
"sha256:c8b95fc493e2945b259153f7b0dd34a3d849e8e1e43b6c14ac04f613b3b45433"
"sha256:6257a5e505b61a8cafee7ef3ad08cf32ee9b885718f42395d017e0a9b4c6af65",
"sha256:f7b1205cc5d9b62835aac8cbc1e6e37c1da862359a401f1edbe2ae08fbdc6193"
],
"index": "pypi",
"version": "==2022.2.1"
"version": "==1.8.0"
},
"intel-openmp": {
"hashes": [
"sha256:1ebce47df0b5ddad77992a70689fd3185df25f47cf901dd8384fd6d05a974f81",
"sha256:77131c2cda75ace2060f6e9cdcc9f9c672ec838c4602fc544ce0858cfe8f416e",
"sha256:adfb32b0dde6b3a95ced62608b05a45a7cfad928054136ddbfe0563e16cbf33c"
],
"index": "pypi",
"version": "==2023.0.0"
},
"nptyping": {
"hashes": [
"sha256:23e8164b1e2c55e872f392ca7516b9b1b0cb400b03b70accaa63998b4106b0b3",
"sha256:57ba684ee5fc5eb681ee04270ee94adb879e4372ce6b640defa08ace8e1df295"
"sha256:764e51836faae33a7ae2e928af574cfb701355647accadcc89f2ad793630b7c8",
"sha256:e3d35b53af967e6fb407c3016ff9abae954d3a0568f7cc13a461084224e8e20a"
],
"index": "pypi",
"version": "==2.4.1"
"version": "==2.5.0"
},
"numpy": {
"hashes": [
"sha256:0fe563fc8ed9dc4474cbf70742673fc4391d70f4363f917599a7fa99f042d5a8",
"sha256:12ac457b63ec8ded85d85c1e17d85efd3c2b0967ca39560b307a35a6703a4735",
"sha256:2341f4ab6dba0834b685cce16dad5f9b6606ea8a00e6da154f5dbded70fdc4dd",
"sha256:296d17aed51161dbad3c67ed6d164e51fcd18dbcd5dd4f9d0a9c6055dce30810",
"sha256:488a66cb667359534bc70028d653ba1cf307bae88eab5929cd707c761ff037db",
"sha256:4d52914c88b4930dafb6c48ba5115a96cbab40f45740239d9f4159c4ba779962",
"sha256:5e13030f8793e9ee42f9c7d5777465a560eb78fa7e11b1c053427f2ccab90c79",
"sha256:61be02e3bf810b60ab74e81d6d0d36246dbfb644a462458bb53b595791251911",
"sha256:7607b598217745cc40f751da38ffd03512d33ec06f3523fb0b5f82e09f6f676d",
"sha256:7a70a7d3ce4c0e9284e92285cba91a4a3f5214d87ee0e95928f3614a256a1488",
"sha256:7ab46e4e7ec63c8a5e6dbf5c1b9e1c92ba23a7ebecc86c336cb7bf3bd2fb10e5",
"sha256:8981d9b5619569899666170c7c9748920f4a5005bf79c72c07d08c8a035757b0",
"sha256:8c053d7557a8f022ec823196d242464b6955a7e7e5015b719e76003f63f82d0f",
"sha256:926db372bc4ac1edf81cfb6c59e2a881606b409ddc0d0920b988174b2e2a767f",
"sha256:95d79ada05005f6f4f337d3bb9de8a7774f259341c70bc88047a1f7b96a4bcb2",
"sha256:95de7dc7dc47a312f6feddd3da2500826defdccbc41608d0031276a24181a2c0",
"sha256:a0882323e0ca4245eb0a3d0a74f88ce581cc33aedcfa396e415e5bba7bf05f68",
"sha256:a8365b942f9c1a7d0f0dc974747d99dd0a0cdfc5949a33119caf05cb314682d3",
"sha256:a8aae2fb3180940011b4862b2dd3756616841c53db9734b27bb93813cd79fce6",
"sha256:c237129f0e732885c9a6076a537e974160482eab8f10db6292e92154d4c67d71",
"sha256:c67b833dbccefe97cdd3f52798d430b9d3430396af7cdb2a0c32954c3ef73894",
"sha256:ce03305dd694c4873b9429274fd41fc7eb4e0e4dea07e0af97a933b079a5814f",
"sha256:d331afac87c92373826af83d2b2b435f57b17a5c74e6268b79355b970626e329",
"sha256:dada341ebb79619fe00a291185bba370c9803b1e1d7051610e01ed809ef3a4ba",
"sha256:ed2cc92af0efad20198638c69bb0fc2870a58dabfba6eb722c933b48556c686c",
"sha256:f260da502d7441a45695199b4e7fd8ca87db659ba1c78f2bbf31f934fe76ae0e",
"sha256:f2f390aa4da44454db40a1f0201401f9036e8d578a25f01a6e237cea238337ef",
"sha256:f76025acc8e2114bb664294a07ede0727aa75d63a06d2fae96bf29a81747e4a7"
"sha256:003a9f530e880cb2cd177cba1af7220b9aa42def9c4afc2a2fc3ee6be7eb2b22",
"sha256:150947adbdfeceec4e5926d956a06865c1c690f2fd902efede4ca6fe2e657c3f",
"sha256:2620e8592136e073bd12ee4536149380695fbe9ebeae845b81237f986479ffc9",
"sha256:2eabd64ddb96a1239791da78fa5f4e1693ae2dadc82a76bc76a14cbb2b966e96",
"sha256:4173bde9fa2a005c2c6e2ea8ac1618e2ed2c1c6ec8a7657237854d42094123a0",
"sha256:4199e7cfc307a778f72d293372736223e39ec9ac096ff0a2e64853b866a8e18a",
"sha256:4cecaed30dc14123020f77b03601559fff3e6cd0c048f8b5289f4eeabb0eb281",
"sha256:557d42778a6869c2162deb40ad82612645e21d79e11c1dc62c6e82a2220ffb04",
"sha256:63e45511ee4d9d976637d11e6c9864eae50e12dc9598f531c035265991910468",
"sha256:6524630f71631be2dabe0c541e7675db82651eb998496bbe16bc4f77f0772253",
"sha256:76807b4063f0002c8532cfeac47a3068a69561e9c8715efdad3c642eb27c0756",
"sha256:7de8fdde0003f4294655aa5d5f0a89c26b9f22c0a58790c38fae1ed392d44a5a",
"sha256:889b2cc88b837d86eda1b17008ebeb679d82875022200c6e8e4ce6cf549b7acb",
"sha256:92011118955724465fb6853def593cf397b4a1367495e0b59a7e69d40c4eb71d",
"sha256:97cf27e51fa078078c649a51d7ade3c92d9e709ba2bfb97493007103c741f1d0",
"sha256:9a23f8440561a633204a67fb44617ce2a299beecf3295f0d13c495518908e910",
"sha256:a51725a815a6188c662fb66fb32077709a9ca38053f0274640293a14fdd22978",
"sha256:a77d3e1163a7770164404607b7ba3967fb49b24782a6ef85d9b5f54126cc39e5",
"sha256:adbdce121896fd3a17a77ab0b0b5eedf05a9834a18699db6829a64e1dfccca7f",
"sha256:c29e6bd0ec49a44d7690ecb623a8eac5ab8a923bce0bea6293953992edf3a76a",
"sha256:c72a6b2f4af1adfe193f7beb91ddf708ff867a3f977ef2ec53c0ffb8283ab9f5",
"sha256:d0a2db9d20117bf523dde15858398e7c0858aadca7c0f088ac0d6edd360e9ad2",
"sha256:e3ab5d32784e843fc0dd3ab6dcafc67ef806e6b6828dc6af2f689be0eb4d781d",
"sha256:e428c4fbfa085f947b536706a2fc349245d7baa8334f0c5723c56a10595f9b95",
"sha256:e8d2859428712785e8a8b7d2b3ef0a1d1565892367b32f915c4a4df44d0e64f5",
"sha256:eef70b4fc1e872ebddc38cddacc87c19a3709c0e3e5d20bf3954c147b1dd941d",
"sha256:f64bb98ac59b3ea3bf74b02f13836eb2e24e48e0ab0145bbda646295769bd780",
"sha256:f9006288bcf4895917d02583cf3411f98631275bc67cce355a7f39f8c14338fa"
],
"index": "pypi",
"version": "==1.23.4"
"version": "==1.24.2"
},
"pickle5": {
"hashes": [
@@ -93,28 +99,29 @@
},
"pyinstaller": {
"hashes": [
"sha256:04ecf805bde2ef25b8e3642410871e6747c22fa7254107f155b8cd179c2a13b6",
"sha256:05df5d2b9ca645cc6ef61d8a85451d2aabe5501997f1f50cd94306fd6bc0485d",
"sha256:0d167d57036219914188f1400427dd297b975707e78c32a5511191e607be920a",
"sha256:181856ade585b090379ae26b7017dc2c30620e36e3a804b381417a6dc3b2a82b",
"sha256:1b1e3b37a22fb36555d917f0c3dfb998159ff4af6d8fa7cc0074d630c6fe81ad",
"sha256:32727232f446aa96e394f01b0c35b3de0dc3513c6ba3e26d1ef64c57edb1e9e5",
"sha256:77888f52b61089caa0bee70809bbce9e9b1c613c88b6cb0742ff2a45f1511cbb",
"sha256:865025b6809d777bb0f66d8f8ab50cc97dc3dbe0ff09a1ef1f2fd646432714fc",
"sha256:d888db9afedff290d362ee296d30eb339abeba707ca1565916ce1cd5947131c3",
"sha256:e026adc92c60158741d0bfca27eefaa2414801f61328cb84d0c88241fe8c2087",
"sha256:eb083c25f711769af0898852ea30dcb727ba43990bbdf9ffbaa9c77a7bd0d720"
"sha256:314fb883caf3cbf06adbea2b77671bb73c3481568e994af0467ea7e47eb64755",
"sha256:3b74f50a57b1413047042e47033480b7324b091f23dff790a4494af32b377d94",
"sha256:4f4d818588e2d8de4bf24ed018056c3de0c95898ad25719e12d68626161b4933",
"sha256:502a2166165a8e8c3d99c19272e923d2548bac2132424d78910ef9dd8bb11705",
"sha256:5c9632a20faecd6d79f0124afb31e6557414d19be271e572765b474f860f8d76",
"sha256:8d004699c5d71c704c14a5f81eec233faa4f87a3bf0ae68e222b87d63f5dd17e",
"sha256:a62ee598b137202ef2e99d8dbaee6bc7379a6565c3ddf0331decb41b98eff1a2",
"sha256:bacf236b5c2f8f674723a39daca399646dceb470881f842f52e393b9a67ff2f8",
"sha256:bf1f7b7e88b467d7aefcdb2bc9cbd2e856ca88c5ab232c0efe0848f146d3bd5f",
"sha256:ded780f0d3642d7bfc21d97b98d4ec4b41d2fe70c3f5c5d243868612f536e011",
"sha256:e68bcadf32edc1171ccb06117699a6a4f8e924b7c2c8812cfa00fd0186ade4ee",
"sha256:f9361eff44c7108c2312f39d85ed768c4ada7e0aa729046bbcef3ef3c1577d18"
],
"index": "pypi",
"version": "==5.6.2"
"version": "==5.8.0"
},
"pyinstaller-hooks-contrib": {
"hashes": [
"sha256:91ecb30db757a8db8b6661d91d5df99e0998245f05f5cfaade0550922c7030a3",
"sha256:e06d0881e599d94dc39c6ed1917f0ad9b1858a2478b9892faac18bd48bcdc2de"
"sha256:29d052eb73e0ab8f137f11df8e73d464c1c6d4c3044d9dc8df2af44639d8bfbf",
"sha256:bd578781cd6a33ef713584bf3726f7cd60a3e656ec08a6cc7971e39990808cc0"
],
"markers": "python_version >= '3.7'",
"version": "==2022.13"
"version": "==2023.0"
},
"pyyaml": {
"hashes": [
@@ -172,13 +179,18 @@
"sha256:1ff863a20d1ff6ba2c24e22436a3daa3cd80be1dfb26891aae73f61b54b04aca",
"sha256:265ecbe2c6eafe82e104f994ddd7c811520acdd0647b73f65c24f51374cf9494",
"sha256:288943dec88e178bb2fd868adf491197cc0fc8b6810416b1c6775e686bab87fe",
"sha256:2a97d51c17d438cf5be284775a322d57b7ca9505bb7e118c28b1824ecaf8aeaa",
"sha256:2e3ac25bfc4a0f29d2409650c7532d5ddfdbf29f16f8a256fc31c47d0dc05172",
"sha256:2fbd8187948284293f43533c150cd69a0e4192c83c377da837dbcd29f6b83084",
"sha256:37ece938110cab2bb3957e3910af8152ca15f2b6efdf4f2612e3f6b7e5459b80",
"sha256:4058564195b975ddc3f0462375c533cce310ccdd41b80ac9aed641c296c3eff4",
"sha256:4749a2b0c9ac52f864d13cee94546606f92b981b50e46226f7f830a56a9dc8e1",
"sha256:4bba3be4c1fabf170595b71f3af46c6d482fbe7d9e0563999b49999a31876f77",
"sha256:4d8938249a7cea45ab7e1e48b77685d0f2bab1ebfa9dde23e94ab97968996a7c",
"sha256:5194b4969f82ea842a4f6af2f82cd16ebdc3f1771fb2771796e6add9835c1973",
"sha256:55ce1e9925ce1765865442ede9dca0ba9bde10593fcd570b1f0fa25d3ec6b31c",
"sha256:570d255fd99c7f14d8f91363c3ea96bd54f8742275796bca67e1414aeca7d8c3",
"sha256:587c7d6780109fbd8a627758063d08ab0421377c0853780e5c356873cdf0f077",
"sha256:589be87172b238f839e19f146b9ea47c71e413e951ef0dc6db4218ddacf3c202",
"sha256:5b932c3041aa924163f4aab970c2f0e6b4d9d773f4d50326e0ea1cd69240e5c5",
"sha256:5fb4f769c02f63fac90989711a3fee83919f47ae9afd4758ced5d86596318c65",
@@ -191,12 +203,15 @@
"sha256:7f0bed90a216ef28b9d227d8d73e28a8c9b88c0f48a082d13ab3fa83c581488f",
"sha256:7f2719a398e1a2c01c2a63bf30377a34d0b6ef61946ab9cf4d550733af8f1ef1",
"sha256:7fe9df7aeb8c64db6c34fc3b13271a363475d77bc157d3f00275a53910cb1989",
"sha256:88486e6cce2a18a033013d17b30a594f1c5cb42520c49c19e6ade40b864bb7ff",
"sha256:8e4f8f12258a8739c565292a551c3db62cca4ed4f6b6126664e2381acb4931bf",
"sha256:8ff3c8cb26afaed25e8bca7b9dd0c1e36de71f35a3a0706b5c0d5172587a3827",
"sha256:9124bedd8006b0e04d4e8a71a0945da9b67e7a4ab88fdad7b1440dc5b6122c42",
"sha256:92c626edc66169a1b09e9541b9c0c9f10488447d8a2b1d87c8f0672e771bc927",
"sha256:a149a5f7f2c5a065d4e63cb0d7a4b6d3b66e6e80f12e3f8827c4f63974cbf122",
"sha256:a47d97a75fd2d10c37410b180f67a5835cb1d8fdea2648fd7f359d4277f180b9",
"sha256:a499fff50387c1520c085a07578a000123f519e5f3eee61dd68e1d301659651f",
"sha256:a8e0881568c5e6beff91ef73c0ec8ac2a9d3ecc9edd6bd83c31ca34f770910c4",
"sha256:ab45146c71ca6592c9cc8b354a2cc9cc4843c33efcbe1d245d7d37ce9696552d",
"sha256:b2c9cb2705fc84cb8798f1ba74194f4c080aaef19d9dae843591c09b97678e98",
"sha256:b34baef93bfb20a8ecb930e395ccd2ae3268050d8cf4fe187de5e2bd806fd796",
@@ -206,7 +221,10 @@
"sha256:c2c46200656280a064073447ebd363937562debef329482fd7e570c8d498f806",
"sha256:c8a09d570b39517de10ee5b718730e171251ce63bbb890c430c725c8c53d4484",
"sha256:c91b9bc8985d00239f7dc08a49927a7ca1ca8a6af2c3890feec3ed9665b6f91e",
"sha256:ca58cd260ea02759238d994cfae844fc8b1e206c684beb8f38877dcab8451dfc",
"sha256:d7d17c8bd073cbf8d141993db45145a70b307385b69171d6b54bcf23e5d644de",
"sha256:dad42e676c5261eb50fdb16bdf3e2771cf8f99a79ef69ba88729aeb3472d8575",
"sha256:db684d6bbb735a80bcbc3737856385b55d53f8a44ce9b46e9a5682c5133a9bf7",
"sha256:de3a540cd1817ede31f530d20e6a4935bbc1b145fd8f8cf393903b1e02f1ae76",
"sha256:e00c9d5c541a2713ba0e657e0303bf96ddddc412ef4761676adc35df35d7c246",
"sha256:e1aafc91cbdacc9e5fe712c52077369168e6b6c346f3a9d51bf600b53eae56bb",
@@ -216,6 +234,7 @@
"sha256:e5c50e164cd2459bc5137c15288a9ef57160fd5cbf293265ea3c45efe7870865",
"sha256:e8579a43eafd246e285eb3a5b939e7158073d5087aacdd2308f23200eac2458b",
"sha256:e85e50b9c67854f89635a86247412f3ad66b132a4d8534ac017547197c88f27d",
"sha256:e932089c35a396dc31a5a1fc49889dd559548d14cb2237adae260382a090382e",
"sha256:f0452282258dfcc01697026a8841258dd2057c4438b43914b611bccbcd048f10",
"sha256:f4bfc89bd33ebb8e4c0e9846a09b1f5a4a86f5cb7a317e75cc42fee1131b4f4f",
"sha256:fa2f50678f04fda7a75d0fe5dd02bbdd3b13cbe6ed4cf626e4472a7ccf47ae94",
@@ -230,11 +249,11 @@
},
"setuptools": {
"hashes": [
"sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31",
"sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"
"sha256:e5fd0a713141a4a105412233c63dc4e17ba0090c8e8334594ac790ec97792330",
"sha256:f106dee1b506dee5102cc3f3e9e68137bbad6d47b616be7991714b0c62204251"
],
"markers": "python_version >= '3.7'",
"version": "==65.5.1"
"version": "==67.4.0"
},
"typing": {
"hashes": [
@@ -243,6 +262,14 @@
],
"index": "pypi",
"version": "==3.7.4.3"
},
"typing-extensions": {
"hashes": [
"sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb",
"sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"
],
"markers": "python_version < '3.10'",
"version": "==4.5.0"
}
},
"develop": {
@@ -255,36 +282,37 @@
},
"pyinstaller": {
"hashes": [
"sha256:04ecf805bde2ef25b8e3642410871e6747c22fa7254107f155b8cd179c2a13b6",
"sha256:05df5d2b9ca645cc6ef61d8a85451d2aabe5501997f1f50cd94306fd6bc0485d",
"sha256:0d167d57036219914188f1400427dd297b975707e78c32a5511191e607be920a",
"sha256:181856ade585b090379ae26b7017dc2c30620e36e3a804b381417a6dc3b2a82b",
"sha256:1b1e3b37a22fb36555d917f0c3dfb998159ff4af6d8fa7cc0074d630c6fe81ad",
"sha256:32727232f446aa96e394f01b0c35b3de0dc3513c6ba3e26d1ef64c57edb1e9e5",
"sha256:77888f52b61089caa0bee70809bbce9e9b1c613c88b6cb0742ff2a45f1511cbb",
"sha256:865025b6809d777bb0f66d8f8ab50cc97dc3dbe0ff09a1ef1f2fd646432714fc",
"sha256:d888db9afedff290d362ee296d30eb339abeba707ca1565916ce1cd5947131c3",
"sha256:e026adc92c60158741d0bfca27eefaa2414801f61328cb84d0c88241fe8c2087",
"sha256:eb083c25f711769af0898852ea30dcb727ba43990bbdf9ffbaa9c77a7bd0d720"
"sha256:314fb883caf3cbf06adbea2b77671bb73c3481568e994af0467ea7e47eb64755",
"sha256:3b74f50a57b1413047042e47033480b7324b091f23dff790a4494af32b377d94",
"sha256:4f4d818588e2d8de4bf24ed018056c3de0c95898ad25719e12d68626161b4933",
"sha256:502a2166165a8e8c3d99c19272e923d2548bac2132424d78910ef9dd8bb11705",
"sha256:5c9632a20faecd6d79f0124afb31e6557414d19be271e572765b474f860f8d76",
"sha256:8d004699c5d71c704c14a5f81eec233faa4f87a3bf0ae68e222b87d63f5dd17e",
"sha256:a62ee598b137202ef2e99d8dbaee6bc7379a6565c3ddf0331decb41b98eff1a2",
"sha256:bacf236b5c2f8f674723a39daca399646dceb470881f842f52e393b9a67ff2f8",
"sha256:bf1f7b7e88b467d7aefcdb2bc9cbd2e856ca88c5ab232c0efe0848f146d3bd5f",
"sha256:ded780f0d3642d7bfc21d97b98d4ec4b41d2fe70c3f5c5d243868612f536e011",
"sha256:e68bcadf32edc1171ccb06117699a6a4f8e924b7c2c8812cfa00fd0186ade4ee",
"sha256:f9361eff44c7108c2312f39d85ed768c4ada7e0aa729046bbcef3ef3c1577d18"
],
"index": "pypi",
"version": "==5.6.2"
"version": "==5.8.0"
},
"pyinstaller-hooks-contrib": {
"hashes": [
"sha256:91ecb30db757a8db8b6661d91d5df99e0998245f05f5cfaade0550922c7030a3",
"sha256:e06d0881e599d94dc39c6ed1917f0ad9b1858a2478b9892faac18bd48bcdc2de"
"sha256:29d052eb73e0ab8f137f11df8e73d464c1c6d4c3044d9dc8df2af44639d8bfbf",
"sha256:bd578781cd6a33ef713584bf3726f7cd60a3e656ec08a6cc7971e39990808cc0"
],
"markers": "python_version >= '3.7'",
"version": "==2022.13"
"version": "==2023.0"
},
"setuptools": {
"hashes": [
"sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31",
"sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"
"sha256:e5fd0a713141a4a105412233c63dc4e17ba0090c8e8334594ac790ec97792330",
"sha256:f106dee1b506dee5102cc3f3e9e68137bbad6d47b616be7991714b0c62204251"
],
"markers": "python_version >= '3.7'",
"version": "==65.5.1"
"version": "==67.4.0"
}
}
}

View File

@@ -13,8 +13,8 @@ dice:
dens: 0.75
nstep: [2000, 3000]
isave: 1000
ljname: 'phb.ljc'
outname: 'phb'
ljname: 'phb.ljc'
randominit: 'always'
gaussian:

View File

@@ -1,753 +0,0 @@
import os
import shutil
import subprocess
import sys
from multiprocessing import Process, connection
from typing import Final, List, TextIO
import setproctitle
from diceplayer.DPpack.Utils.Misc import *
from diceplayer.DPpack.Utils.PTable import *
from diceplayer.DPpack.Utils.StepDTO import StepDTO
from diceplayer.DPpack.Utils.Validations import NotNull
from numpy import random
DICE_END_FLAG: Final[str] = "End of simulation"
DICE_FLAG_LINE: Final[int] = -2
UMAANG3_TO_GCM3: Final[float] = 1.6605
MAX_SEED: Final[int] = 4294967295
class Dice:
title = "Diceplayer run"
progname = "dice"
nprocs: int = None
randominit = "first"
combrule = "*"
temp = 300.0
press = 1.0
isave = 1000
dens = None
ljname = None
outname = None
nmol: List[int] = None
nstep: List[int] = None
upbuf = 360
def __init__(self, infile: TextIO, outfile: TextIO) -> None:
self.infile = infile
self.outfile = outfile
@NotNull(requiredArgs=["ncores", "nmol", "dens", "nstep", "ljname", "outname"])
def updateKeywords(self, **data):
self.__dict__.update(**data)
def __new_density(self, cycle: int, proc: int) -> float:
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle - 1)
proc_dir = "p{:02d}".format(proc)
path = sim_dir + os.sep + step_dir + os.sep + proc_dir
file = path + os.sep + "last.xyz"
if not os.path.isfile(file):
sys.exit(
"Error: cannot find the xyz file {} in main directory".format(file)
)
try:
with open(file) as fh:
xyzfile = fh.readlines()
except:
sys.exit("Error: cannot open file {}".format(file))
box = xyzfile[1].split()
volume = float(box[-3]) * float(box[-2]) * float(box[-1])
total_mass = 0
for i in range(len(self.step.molecule)):
total_mass += self.step.molecule[i].total_mass * self.step.nmol[i]
density = (total_mass / volume) * UMAANG3_TO_GCM3
return density
def __print_last_config(self, cycle: int, proc: int) -> None:
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle)
proc_dir = "p{:02d}".format(proc)
path = sim_dir + os.sep + step_dir + os.sep + proc_dir
file = path + os.sep + "phb.xyz"
if not os.path.isfile(file):
sys.exit("Error: cannot find the xyz file {}".format(file))
try:
with open(file) as fh:
xyzfile = fh.readlines()
except:
sys.exit("Error: cannot open file {}".format(file))
nsites = len(self.step.molecule[0].atom) * self.step.nmol[0]
for i in range(1, len(self.step.nmol)):
nsites += self.step.nmol[i] * len(self.step.molecule[i].atom)
nsites += 2
nsites *= -1
xyzfile = xyzfile[nsites:]
file = path + os.sep + "last.xyz"
fh = open(file, "w")
for line in xyzfile:
fh.write(line)
def __make_dice_inputs(self, cycle: int, proc: int) -> None:
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle)
proc_dir = "p{:02d}".format(proc)
path = sim_dir + os.sep + step_dir + os.sep + proc_dir
num = time.time()
num = (num - int(num)) * 1e6
num = int((num - int(num)) * 1e6)
random.seed((os.getpid() * num) % (MAX_SEED + 1))
if self.randominit == "first" and cycle > self.step.initcyc:
last_step_dir = "step{:02d}".format(cycle - 1)
last_path = sim_dir + os.sep + last_step_dir + os.sep + proc_dir
xyzfile = last_path + os.sep + "last.xyz"
self.__make_init_file(path, xyzfile)
if len(self.nstep) == 2:
self.__make_nvt_ter(cycle, path)
self.__make_nvt_eq(path)
elif len(self.nstep) == 3:
if self.randominit == "first" and cycle > self.step.initcyc:
self.dens = self.__new_density(cycle, proc)
else:
self.__make_nvt_ter(cycle, path)
self.__make_npt_ter(cycle, path)
self.__make_npt_eq(path)
else:
sys.exit("Error: bad number of entries for 'nstep'")
self.__make_potential(path)
def __make_nvt_ter(self, cycle: int, path: str) -> None:
file = path + os.sep + "NVT.ter"
try:
fh = open(file, "w")
except:
sys.exit("Error: cannot open file {}".format(file))
fh.write("title = {} - NVT Thermalization\n".format(self.title))
fh.write("ncores = {}\n".format(self.ncores))
fh.write("ljname = {}\n".format(self.ljname))
fh.write("outname = {}\n".format(self.outname))
string = " ".join(str(x) for x in self.nmol)
fh.write("nmol = {}\n".format(string))
fh.write("dens = {}\n".format(self.dens))
fh.write("temp = {}\n".format(self.temp))
if self.randominit == "first" and cycle > self.step.initcyc:
fh.write("init = yesreadxyz\n")
fh.write("nstep = {}\n".format(self.step.altsteps))
else:
fh.write("init = yes\n")
fh.write("nstep = {}\n".format(self.nstep[0]))
fh.write("vstep = 0\n")
fh.write("mstop = 1\n")
fh.write("accum = no\n")
fh.write("iprint = 1\n")
fh.write("isave = 0\n")
fh.write("irdf = 0\n")
seed = int(1e6 * random.random())
fh.write("seed = {}\n".format(seed))
fh.write("upbuf = {}".format(self.upbuf))
fh.close()
def __make_nvt_eq(self, path: str) -> None:
file = path + os.sep + "NVT.eq"
try:
fh = open(file, "w")
except:
sys.exit("Error: cannot open file {}".format(file))
fh.write("title = {} - NVT Production\n".format(self.title))
fh.write("ncores = {}\n".format(self.ncores))
fh.write("ljname = {}\n".format(self.ljname))
fh.write("outname = {}\n".format(self.outname))
string = " ".join(str(x) for x in self.nmol)
fh.write("nmol = {}\n".format(string))
fh.write("dens = {}\n".format(self.dens))
fh.write("temp = {}\n".format(self.temp))
fh.write("init = no\n")
fh.write("nstep = {}\n".format(self.nstep[1]))
fh.write("vstep = 0\n")
fh.write("mstop = 1\n")
fh.write("accum = no\n")
fh.write("iprint = 1\n")
fh.write("isave = {}\n".format(self.isave))
fh.write("irdf = {}\n".format(10 * self.step.nprocs))
seed = int(1e6 * random.random())
fh.write("seed = {}\n".format(seed))
fh.close()
def __make_npt_ter(self, cycle: int, path: str) -> None:
file = path + os.sep + "NPT.ter"
try:
fh = open(file, "w")
except:
sys.exit("Error: cannot open file {}".format(file))
fh.write("title = {} - NPT Thermalization\n".format(self.title))
fh.write("ncores = {}\n".format(self.ncores))
fh.write("ljname = {}\n".format(self.ljname))
fh.write("outname = {}\n".format(self.outname))
string = " ".join(str(x) for x in self.nmol)
fh.write("nmol = {}\n".format(string))
fh.write("press = {}\n".format(self.press))
fh.write("temp = {}\n".format(self.temp))
if self.randominit == "first" and cycle > self.step.initcyc:
fh.write("init = yesreadxyz\n")
fh.write("dens = {:<8.4f}\n".format(self.dens))
fh.write("vstep = {}\n".format(int(self.step.altsteps / 5)))
else:
fh.write("init = no\n")
fh.write("vstep = {}\n".format(int(self.nstep[1] / 5)))
fh.write("nstep = 5\n")
fh.write("mstop = 1\n")
fh.write("accum = no\n")
fh.write("iprint = 1\n")
fh.write("isave = 0\n")
fh.write("irdf = 0\n")
seed = int(1e6 * random.random())
fh.write("seed = {}\n".format(seed))
fh.close()
def __make_npt_eq(self, path: str) -> None:
file = path + os.sep + "NPT.eq"
try:
fh = open(file, "w")
except:
sys.exit("Error: cannot open file {}".format(file))
fh.write("title = {} - NPT Production\n".format(self.title))
fh.write("ncores = {}\n".format(self.ncores))
fh.write("ljname = {}\n".format(self.ljname))
fh.write("outname = {}\n".format(self.outname))
string = " ".join(str(x) for x in self.nmol)
fh.write("nmol = {}\n".format(string))
fh.write("press = {}\n".format(self.press))
fh.write("temp = {}\n".format(self.temp))
fh.write("nstep = 5\n")
fh.write("vstep = {}\n".format(int(self.nstep[2] / 5)))
fh.write("init = no\n")
fh.write("mstop = 1\n")
fh.write("accum = no\n")
fh.write("iprint = 1\n")
fh.write("isave = {}\n".format(self.isave))
fh.write("irdf = {}\n".format(10 * self.step.nprocs))
seed = int(1e6 * random.random())
fh.write("seed = {}\n".format(seed))
fh.close()
def __make_init_file(self, path: str, file: TextIO) -> None:
if not os.path.isfile(file):
sys.exit(
"Error: cannot find the xyz file {} in main directory".format(file)
)
try:
with open(file) as fh:
xyzfile = fh.readlines()
except:
sys.exit("Error: cannot open file {}".format(file))
nsites_mm = 0
for i in range(1, len(self.step.nmol)):
nsites_mm += self.step.nmol[i] * len(self.step.molecule[i].atom)
nsites_mm *= -1
xyzfile = xyzfile[nsites_mm:]
file = path + os.sep + self.outname + ".xy"
try:
fh = open(file, "w", 1)
except:
sys.exit("Error: cannot open file {}".format(file))
for atom in self.step.molecule[0].atom:
fh.write(
"{:>10.6f} {:>10.6f} {:>10.6f}\n".format(atom.rx, atom.ry, atom.rz)
)
for line in xyzfile:
atom = line.split()
rx = float(atom[1])
ry = float(atom[2])
rz = float(atom[3])
fh.write("{:>10.6f} {:>10.6f} {:>10.6f}\n".format(rx, ry, rz))
fh.write("$end")
fh.close()
def __make_potential(self, path: str) -> None:
fstr = "{:<3d} {:>3d} {:>10.5f} {:>10.5f} {:>10.5f} {:>10.6f} {:>9.5f} {:>7.4f}\n"
file = path + os.sep + self.ljname
try:
fh = open(file, "w")
except:
sys.exit("Error: cannot open file {}".format(file))
fh.write("{}\n".format(self.combrule))
fh.write("{}\n".format(len(self.step.nmol)))
nsites_qm = (
len(self.step.molecule[0].atom)
+ len(self.step.molecule[0].ghost_atoms)
+ len(self.step.molecule[0].lp_atoms)
)
fh.write("{} {}\n".format(nsites_qm, self.step.molecule[0].molname))
for atom in self.step.molecule[0].atom:
fh.write(
fstr.format(
atom.lbl,
atom.na,
atom.rx,
atom.ry,
atom.rz,
atom.chg,
atom.eps,
atom.sig,
)
)
ghost_label = self.step.molecule[0].atom[-1].lbl + 1
for i in self.step.molecule[0].ghost_atoms:
fh.write(
fstr.format(
ghost_label,
ghost_number,
self.step.molecule[0].atom[i].rx,
self.step.molecule[0].atom[i].ry,
self.step.molecule[0].atom[i].rz,
self.step.molecule[0].atom[i].chg,
0,
0,
)
)
ghost_label += 1
for lp in self.step.molecule[0].lp_atoms:
fh.write(
fstr.format(
ghost_label,
ghost_number,
lp["rx"],
lp["ry"],
lp["rz"],
lp["chg"],
0,
0,
)
)
for mol in self.step.molecule[1:]:
fh.write("{} {}\n".format(len(mol.atom), mol.molname))
for atom in mol.atom:
fh.write(
fstr.format(
atom.lbl,
atom.na,
atom.rx,
atom.ry,
atom.rz,
atom.chg,
atom.eps,
atom.sig,
)
)
def __make_proc_dir(self, cycle: int, proc: int) -> None:
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle)
proc_dir = "p{:02d}".format(proc)
path = sim_dir + os.sep + step_dir + os.sep + proc_dir
try:
os.makedirs(path)
except:
sys.exit("Error: cannot make directory {}".format(path))
def __run_dice(self, cycle: int, proc: int, fh: str) -> None:
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle)
proc_dir = "p{:02d}".format(proc)
try:
fh.write(
"Simulation process {} initiated with pid {}\n".format(
sim_dir + os.sep + step_dir + os.sep + proc_dir, os.getpid()
)
)
except Exception as err:
print("I/O error({0}): {1}".format(err))
path = sim_dir + os.sep + step_dir + os.sep + proc_dir
working_dir = os.getcwd()
os.chdir(path)
if len(self.nstep) == 2:
if self.randominit == "first" and cycle > self.step.initcyc:
string_tmp = "previous"
else:
string_tmp = "random"
string = "(from " + string_tmp + " configuration)"
fh.write(
"p{:02d}> NVT thermalization finished {} on {}\n".format(
proc, string, date_time()
)
)
infh = open("NVT.ter")
outfh = open("NVT.ter.out", "w")
if shutil.which("bash") != None:
exit_status = subprocess.call(
[
"bash",
"-c",
"exec -a dice-step{}-p{} {} < {} > {}".format(
cycle, proc, self.progname, infh.name, outfh.name
),
]
)
else:
exit_status = subprocess.call(
self.progname, stin=infh.name, stout=outfh.name
)
infh.close()
outfh.close()
if os.getppid() == 1:
sys.exit()
if exit_status != 0:
sys.exit(
"Dice process step{:02d}-p{:02d} did not exit properly".format(
cycle, proc
)
)
else:
outfh = open("NVT.ter.out")
flag = outfh.readlines()[DICE_FLAG_LINE].strip()
outfh.close()
if flag != DICE_END_FLAG:
sys.exit(
"Dice process step{:02d}-p{:02d} did not exit properly".format(
cycle, proc
)
)
fh.write(
"p{:02d}> NVT production initiated on {}\n".format(proc, date_time())
)
infh = open("NVT.eq")
outfh = open("NVT.eq.out", "w")
if shutil.which("bash") != None:
exit_status = subprocess.call(
[
"bash",
"-c",
"exec -a dice-step{}-p{} {} < {} > {}".format(
cycle, proc, self.progname, infh.name, outfh.name
),
]
)
else:
exit_status = subprocess.call(
self.progname, stin=infh.name, stout=outfh.name
)
infh.close()
outfh.close()
if os.getppid() == 1:
sys.exit()
if exit_status != 0:
sys.exit(
"Dice process step{:02d}-p{:02d} did not exit properly".format(
cycle, proc
)
)
else:
outfh = open("NVT.eq.out")
flag = outfh.readlines()[DICE_FLAG_LINE].strip()
outfh.close()
if flag != DICE_END_FLAG:
sys.exit(
"Dice process step{:02d}-p{:02d} did not exit properly".format(
cycle, proc
)
)
fh.write(
"p{:02d}> ----- NVT production finished on {}\n".format(
proc, date_time()
)
)
elif len(self.nstep) == 3:
if (
self.randominit == "always"
or (self.randominit == "first" and cycle == 1)
or self.continued
):
string = "(from random configuration)"
fh.write(
"p{:02d}> NVT thermalization initiated {} on {}\n".format(
proc, string, date_time()
)
)
infh = open("NVT.ter")
outfh = open("NVT.ter.out", "w")
if shutil.which("bash") != None:
exit_status = subprocess.call(
[
"bash",
"-c",
"exec -a dice-step{}-p{} {} < {} > {}".format(
cycle, proc, self.progname, infh.name, outfh.name
),
]
)
else:
exit_status = subprocess.call(
self.progname, stin=infh.name, stout=outfh.name
)
infh.close()
outfh.close()
if os.getppid() == 1:
sys.exit()
if exit_status != 0:
sys.exit(
"Dice process step{:02d}-p{:02d} did not exit properly".format(
cycle, proc
)
)
else:
outfh = open("NVT.ter.out")
flag = outfh.readlines()[DICE_FLAG_LINE].strip()
outfh.close()
if flag != DICE_END_FLAG:
sys.exit(
"Dice process step{:02d}-p{:02d} did not exit properly".format(
cycle, proc
)
)
if not self.randominit == "always" or (
(self.randominit == "first" and cycle > self.step.initcyc)
):
string = " (from previous configuration) "
else:
string = " "
fh.write(
"p{:02d}> NPT thermalization finished {} on {}\n".format(
proc, string, date_time()
)
)
infh = open("NPT.ter")
outfh = open("NPT.ter.out", "w")
if shutil.which("bash") != None:
exit_status = subprocess.call(
[
"bash",
"-c",
"exec -a dice-step{}-p{} {} < {} > {}".format(
cycle, proc, self.progname, infh.name, outfh.name
),
]
)
else:
exit_status = subprocess.call(
self.progname, stin=infh.name, stout=outfh.name
)
infh.close()
outfh.close()
if os.getppid() == 1:
sys.exit()
if exit_status != 0:
sys.exit(
"Dice process step{:02d}-p{:02d} did not exit properly".format(
cycle, proc
)
)
else:
outfh = open("NPT.ter.out")
flag = outfh.readlines()[DICE_FLAG_LINE].strip()
outfh.close()
if flag != DICE_END_FLAG:
sys.exit(
"Dice process step{:02d}-p{:02d} did not exit properly".format(
cycle, proc
)
)
fh.write(
"p{:02d}> NPT production initiated on {}\n".format(proc, date_time())
)
infh = open("NPT.eq")
outfh = open("NPT.eq.out", "w")
if shutil.which("bash") != None:
exit_status = subprocess.call(
[
"bash",
"-c",
"exec -a dice-step{}-p{} {} < {} > {}".format(
cycle, proc, self.progname, infh.name, outfh.name
),
]
)
else:
exit_status = subprocess.call(
self.progname, stin=infh.name, stout=outfh.name
)
infh.close()
outfh.close()
if os.getppid() == 1:
sys.exit()
if exit_status != 0:
sys.exit(
"Dice process step{:02d}-p{:02d} did not exit properly".format(
cycle, proc
)
)
else:
outfh = open("NPT.eq.out")
flag = outfh.readlines()[DICE_FLAG_LINE].strip()
outfh.close()
if flag != DICE_END_FLAG:
sys.exit(
"Dice process step{:02d}-p{:02d} did not exit properly".format(
cycle, proc
)
)
fh.write(
"p{:02d}> ----- NPT production finished on {}\n".format(
proc, date_time()
)
)
os.chdir(working_dir)
def __simulation_process(self, cycle: int, proc: int):
setproctitle.setproctitle("diceplayer-step{:0d}-p{:0d}".format(cycle, proc))
try:
self.__make_proc_dir(cycle, proc)
self.__make_dice_inputs(cycle, proc)
self.__run_dice(cycle, proc, self.outfile)
except Exception as err:
sys.exit(err)
def configure(self, step: StepDTO):
self.step = step
def start(self, cycle: int) -> None:
procs = []
sentinels = []
for proc in range(1, self.step.nprocs + 1):
p = Process(target=self.__simulation_process, args=(cycle, proc))
p.start()
procs.append(p)
sentinels.append(p.sentinel)
while procs:
finished = connection.wait(sentinels)
for proc_sentinel in finished:
i = sentinels.index(proc_sentinel)
status = procs[i].exitcode
procs.pop(i)
sentinels.pop(i)
if status != 0:
for p in procs:
p.terminate()
sys.exit(status)
for proc in range(1, self.step.nprocs + 1):
self.__print_last_config(cycle, proc)
def reset(self):
del self.step

View File

@@ -1,595 +0,0 @@
from ast import keyword
from asyncore import read
import os
import shutil
import subprocess
import sys
import textwrap
from typing import Dict, List, TextIO
import numpy as np
from diceplayer.DPpack.Environment.Atom import Atom
from diceplayer.DPpack.Environment.Molecule import Molecule
from diceplayer.DPpack.Utils.Misc import *
from diceplayer.DPpack.Utils.PTable import *
from diceplayer.DPpack.Utils.StepDTO import StepDTO
from diceplayer.DPpack.Utils.Validations import NotNull
class Gaussian:
mem = None
chgmult = [0, 1]
gmiddle = None # In each case, if a filename is given, its content will be
gbottom = None # inserted in the gaussian input
pop = "chelpg"
keywords = ""
def __init__(self) -> None:
pass
@NotNull(requiredArgs=["qmprog","level"])
def updateKeywords(self, **data):
self.__dict__.update(**data)
self.checkKeywords()
def checkKeywords(self):
if self.pop not in ["chelpg", "mk", "nbo"]:
self.pop = "chelpg"
def run_formchk(self, cycle: int, fh: TextIO):
simdir = "simfiles"
stepdir = "step{:02d}".format(cycle)
path = simdir + os.sep + stepdir + os.sep + "qm"
work_dir = os.getcwd()
os.chdir(path)
fh.write("Formatting the checkpoint file... \n")
exit_status = subprocess.call(["formchk", "asec.chk"], stdout=fh)
fh.write("Done\n")
os.chdir(work_dir)
def readChargesFromFchk(self, file: str, fh: TextIO) -> List[float]:
try:
with open(file) as fchk:
fchkfile = fchk.readlines()
except:
sys.exit("Error: cannot open file {}".format(file))
if self.pop in ["chelpg", "mk"]:
CHARGE_FLAG = "ESP Charges"
else:
CHARGE_FLAG = "ESP Charges"
start = fchkfile.pop(0).strip()
while start.find(CHARGE_FLAG) != 0: # expression in begining of line
start = fchkfile.pop(0).strip()
charges: List[float] = []
while len(charges) < len(self.step.molecule[0].atom):
charges.extend([float(x) for x in fchkfile.pop(0).split()])
return charges
def read_forces_fchk(self, file: str, fh: TextIO) -> np.ndarray:
forces = []
try:
with open(file) as tmpfh:
fchkfile = tmpfh.readlines()
except:
sys.exit("Error: cannot open file {}".format(file))
start = fchkfile.pop(0).strip()
while start.find("Cartesian Gradient") != 0: # expression in begining of line
start = fchkfile.pop(0).strip()
degrees = 3 * len(self.step.molecule[0].atom)
count = 0
while len(forces) < degrees:
values = fchkfile.pop(0).split()
forces.extend([float(x) for x in values])
count += len(values)
if count >= degrees:
forces = forces[:degrees]
break
gradient = np.array(forces)
fh.write("\nGradient read from file {}:\n".format(file))
fh.write(
"-----------------------------------------------------------------------\n"
"Center Atomic Forces (Hartree/Bohr)\n"
"Number Number X Y Z\n"
"-----------------------------------------------------------------------\n"
)
for i in range(len(self.step.molecule[0].atom)):
fh.write(
" {:>5d} {:>3d} {:>14.9f} {:>14.9f} {:>14.9f}\n".format(
i + 1,
self.step.molecule[0].atom[i].na,
forces.pop(0),
forces.pop(0),
forces.pop(0),
)
)
fh.write(
"-----------------------------------------------------------------------\n"
)
force_max = np.amax(np.absolute(gradient))
force_rms = np.sqrt(np.mean(np.square(gradient)))
fh.write(
" Max Force = {:>14.9f} RMS Force = {:>14.9f}\n\n".format(
force_max, force_rms
)
)
return gradient
def read_hessian_fchk(self, file: str) -> np.ndarray:
force_const = []
try:
with open(file) as tmpfh:
fchkfile = tmpfh.readlines()
except:
sys.exit("Error: cannot open file {}".format(file))
start = fchkfile.pop(0).strip()
while start.find("Cartesian Force Constants") != 0:
start = fchkfile.pop(0).strip()
degrees = 3 * len(self.step.molecule[0].atom)
last = round(degrees * (degrees + 1) / 2)
count = 0
while len(force_const) < last:
value = fchkfile.pop(0).split()
force_const.extend([float(x) for x in value])
# while len(force_const) < last:
# values = fchkfile.pop(0).split()
# force_const.extend([ float(x) for x in values ])
# count += len(values)
# if count >= last:
# force_const = force_const[:last]
# break
hessian = np.zeros((degrees, degrees))
for i in range(degrees):
for j in range(i + 1):
hessian[i, j] = force_const.pop(0)
hessian[j, i] = hessian[i, j]
return hessian
def read_hessian_log(self, file: str) -> np.ndarray:
try:
with open(file) as tmpfh:
logfile = tmpfh.readlines()
except:
sys.exit("Error: cannot open file {}".format(file))
start = logfile.pop(0).strip()
while start.find("The second derivative matrix:") != 0:
start = logfile.pop(0).strip()
degrees = 3 * len(self.step.molecule[0].atom)
hessian = np.zeros((degrees, degrees))
k = 0
while k < degrees:
logfile.pop(0)
for i in range(k, degrees):
values = logfile.pop(0).split()[1:]
for j in range(k, min(i + 1, k + 5)):
hessian[i, j] = float(values.pop(0))
hessian[j, i] = hessian[i, j]
k += 5
return hessian
def print_grad_hessian(
self, cycle: int, cur_gradient: np.ndarray, hessian: np.ndarray
) -> None:
try:
fh = open("grad_hessian.dat", "w")
except:
sys.exit("Error: cannot open file grad_hessian.dat")
fh.write("Optimization cycle: {}\n".format(cycle))
fh.write("Cartesian Gradient\n")
degrees = 3 * len(self.step.molecule[0].atom)
for i in range(degrees):
fh.write(" {:>11.8g}".format(cur_gradient[i]))
if (i + 1) % 5 == 0 or i == degrees - 1:
fh.write("\n")
fh.write("Cartesian Force Constants\n")
n = int(np.sqrt(2 * degrees))
last = degrees * (degrees + 1) / 2
count = 0
for i in range(n):
for j in range(i + 1):
count += 1
fh.write(" {:>11.8g}".format(hessian[i, j]))
if count % 5 == 0 or count == last:
fh.write("\n")
fh.close()
# Change the name to make_gaussian_input
def make_gaussian_input(self, cycle: int, asec_charges: List[Dict]) -> None:
simdir = "simfiles"
stepdir = "step{:02d}".format(cycle)
path = simdir + os.sep + stepdir + os.sep + "qm"
file = path + os.sep + "asec.gjf"
try:
fh = open(file, "w")
except:
sys.exit("Error: cannot open file {}".format(file))
fh.write("%Chk=asec.chk\n")
if self.mem != None:
fh.write("%Mem={}MB\n".format(self.mem))
fh.write("%Nprocs={}\n".format(self.step.nprocs * self.step.ncores))
kword_line = "#P " + str(self.level)
if self.keywords != "":
kword_line += " " + self.keywords
if self.step.opt == "yes":
kword_line += " Force"
# kword_line += " Charge"
kword_line += " NoSymm"
kword_line += " Pop={} Density=Current".format(self.pop)
if cycle > 1:
kword_line += " Guess=Read"
fh.write(textwrap.fill(kword_line, 90))
fh.write("\n")
fh.write("\nForce calculation - Cycle number {}\n".format(cycle))
fh.write("\n")
fh.write("{},{}\n".format(self.chgmult[0], self.chgmult[1]))
for atom in self.step.molecule[0].atom:
symbol = atomsymb[atom.na]
fh.write(
"{:<2s} {:>10.5f} {:>10.5f} {:>10.5f}\n".format(
symbol, atom.rx, atom.ry, atom.rz
)
)
fh.write("\n")
for charge in asec_charges:
fh.write(
"{:>10.5f} {:>10.5f} {:>10.5f} {:>11.8f}\n".format(
charge['rx'], charge['ry'], charge['rz'], charge['chg']
)
)
fh.write("\n")
fh.close()
def read_charges(self, file: str, fh: TextIO) -> None:
try:
with open(file) as tmpfh:
glogfile = tmpfh.readlines()
except:
sys.exit("Error: cannot open file {}".format(file))
start = glogfile.pop(0).strip()
while start != "Fitting point charges to electrostatic potential":
start = glogfile.pop(0).strip()
glogfile = glogfile[3:] # Consume 3 more lines
fh.write("\nAtomic charges:\n")
fh.write("------------------------------------\n")
for atom in self.step.molecule[0].atom:
line = glogfile.pop(0).split()
atom_str = line[1]
charge = float(line[2])
atom.chg = charge
fh.write(" {:<2s} {:>10.6f}\n".format(atom_str, charge))
# if self.pop == "chelpg":
# for ghost in ghost_atoms:
# line = glogfile.pop(0).split()
# atom_str = line[1]
# charge = float(line[2])
# ghost['chg'] = charge
# fh.write(" {:<2s} {:>10.6f}\n".format(atom_str, charge))
# for lp in lp_atoms:
# line = glogfile.pop(0).split()
# atom_str = line[1]
# charge = float(line[2])
# lp['chg'] = charge
# fh.write(" {:<2s} {:>10.6f}\n".format(atom_str, charge))
fh.write("------------------------------------\n")
def executeOptimizationRoutine(self, cycle: int, outfile: TextIO, readhessian: str):
try:
gradient
old_gradient = gradient
except:
pass
gradient = self.read_forces_fchk(file, outfile)
# If 1st step, read the hessian
if cycle == 1:
if readhessian == "yes":
file = "grad_hessian.dat"
outfile.write(
"\nReading the hessian matrix from file {}\n".format(file)
)
hessian = self.read_hessian_log(file)
else:
file = (
"simfiles"
+ os.sep
+ "step01"
+ os.sep
+ "qm"
+ os.sep
+ "asec.fchk"
)
outfile.write(
"\nReading the hessian matrix from file {}\n".format(file)
)
hessian = self.read_hessian_fchk(file)
# From 2nd step on, update the hessian
else:
outfile.write("\nUpdating the hessian matrix using the BFGS method... ")
hessian = self.step.molecule[0].update_hessian(
step, gradient, old_gradient, hessian
)
outfile.write("Done\n")
# Save gradient and hessian
self.print_grad_hessian(cycle, gradient, hessian)
# Calculate the step and update the position
step = self.calculate_step(cycle, gradient, hessian)
position += step
## If needed, calculate the charges
if cycle < self.step.switchcyc:
# internal.gaussian.make_charge_input(cycle, asec_charges)
self.run_gaussian(cycle, "charge", outfile)
file = (
"simfiles"
+ os.sep
+ "step{:02d}".format(cycle)
+ os.sep
+ "qm"
+ os.sep
+ "asec2.log"
)
self.read_charges(file, outfile)
else:
file = (
"simfiles"
+ os.sep
+ "step{:02d}".format(cycle)
+ os.sep
+ "qm"
+ os.sep
+ "asec.log"
)
self.read_charges(file, outfile)
self.outfile.write("\nNew values for molecule type 1:\n\n")
self.step.molecule[0].print_mol_info(outfile)
def run_gaussian(self, cycle: int, type: str, fh: TextIO) -> None:
simdir = "simfiles"
stepdir = "step{:02d}".format(cycle)
path = simdir + os.sep + stepdir + os.sep + "qm"
work_dir = os.getcwd()
os.chdir(path)
# if type == "force":
# infile = "asec.gjf"
# elif type == "charge":
# infile = "asec2.gjf"
infile = "asec.gjf"
fh.write(
"\nCalculation of {}s initiated with Gaussian on {}\n".format(
type, date_time()
)
)
if shutil.which("bash") != None:
exit_status = subprocess.call(
[
"bash",
"-c",
"exec -a {}-step{} {} {}".format(
self.qmprog, cycle, self.qmprog, infile
),
]
)
else:
exit_status = subprocess.call([self.qmprog, infile])
if exit_status != 0:
sys.exit("Gaussian process did not exit properly")
fh.write("Calculation of {}s finished on {}\n".format(type, date_time()))
os.chdir(work_dir)
# def calculate_step(
# self, cycle: int, gradient: np.ndarray, hessian: np.ndarray
# ) -> np.ndarray:
# invhessian = np.linalg.inv(hessian)
# pre_step = -1 * np.matmul(invhessian, gradient.T).T
# maxstep = np.amax(np.absolute(pre_step))
# factor = min(1, self.player.maxstep / maxstep)
# step = factor * pre_step
# self.outfile.write("\nCalculated step-{}:\n".format(cycle))
# pre_step_list = pre_step.tolist()
# self.outfile.write(
# "-----------------------------------------------------------------------\n"
# "Center Atomic Step (Bohr)\n"
# "Number Number X Y Z\n"
# "-----------------------------------------------------------------------\n"
# )
# for i in range(len(self.system.molecule[0].atom)):
# self.outfile.write(
# " {:>5d} {:>3d} {:>14.9f} {:>14.9f} {:>14.9f}\n".format(
# i + 1,
# self.system.molecule[0].atom[i].na,
# pre_step_list.pop(0),
# pre_step_list.pop(0),
# pre_step_list.pop(0),
# )
# )
# self.outfile.write(
# "-----------------------------------------------------------------------\n"
# )
# self.outfile.write("Maximum step is {:>11.6}\n".format(maxstep))
# self.outfile.write("Scaling factor = {:>6.4f}\n".format(factor))
# self.outfile.write("\nFinal step (Bohr):\n")
# step_list = step.tolist()
# self.outfile.write(
# "-----------------------------------------------------------------------\n"
# "Center Atomic Step (Bohr)\n"
# "Number Number X Y Z\n"
# "-----------------------------------------------------------------------\n"
# )
# for i in range(len(self.system.molecule[0].atom)):
# self.outfile.write(
# " {:>5d} {:>3d} {:>14.9f} {:>14.9f} {:>14.9f}\n".format(
# i + 1,
# self.system.molecule[0].atom[i].na,
# step_list.pop(0),
# step_list.pop(0),
# step_list.pop(0),
# )
# )
# self.outfile.write(
# "-----------------------------------------------------------------------\n"
# )
# step_max = np.amax(np.absolute(step))
# step_rms = np.sqrt(np.mean(np.square(step)))
# self.outfile.write(
# " Max Step = {:>14.9f} RMS Step = {:>14.9f}\n\n".format(
# step_max, step_rms
# )
# )
# return step
def configure(self, step: StepDTO):
self.step = step
def start(self, cycle: int, outfile: TextIO, asec_charges: List[Dict], readhessian: str) -> StepDTO:
make_qm_dir(cycle)
if cycle > 1:
src = (
"simfiles"
+ os.sep
+ "step{:02d}".format(cycle - 1)
+ os.sep
+ "qm"
+ os.sep
+ "asec.chk"
)
dst = (
"simfiles"
+ os.sep
+ "step{:02d}".format(cycle)
+ os.sep
+ "qm"
+ os.sep
+ "asec.chk"
)
shutil.copyfile(src, dst)
self.make_gaussian_input(cycle, asec_charges)
self.run_gaussian(cycle, "force", outfile)
self.run_formchk(cycle, outfile)
## Read the gradient
file = (
"simfiles"
+ os.sep
+ "step{:02d}".format(cycle)
+ os.sep
+ "qm"
+ os.sep
+ "asec.fchk"
)
if self.step.opt:
pass
# position = self.executeOptimizationRoutine(cycle, outfile, readhessian)
# self.step.position = position
else:
charges = self.readChargesFromFchk(file, outfile)
self.step.charges = charges
return self.step
def reset(self):
del self.step

View File

@@ -1,801 +0,0 @@
import os
import shutil
import sys
import textwrap
from typing import Dict, List, TextIO
import yaml
from diceplayer.DPpack.Environment.Atom import Atom
from diceplayer.DPpack.Environment.Molecule import Molecule
from diceplayer.DPpack.Environment.System import System
from diceplayer.DPpack.External.Dice import Dice
from diceplayer.DPpack.External.Gaussian import Gaussian
from diceplayer.DPpack.Utils.Misc import *
from diceplayer.DPpack.Utils.PTable import *
from diceplayer.DPpack.Utils.StepDTO import StepDTO
from diceplayer.DPpack.Utils.Validations import NotNull
env = ["OMP_STACKSIZE"]
class Player:
maxcyc = None
opt = None
nprocs = None
qmprog = None
lps = None
ghosts = None
altsteps = None
combrule = None
switchcyc = 3
maxstep = 0.3
freq = "no"
readhessian = "no"
vdwforces = "no"
tol_factor = 1.2
TOL_RMS_FORCE = 3e-4
TOL_MAX_FORCE = 4.5e-4
TOL_RMS_STEP = 1.2e-3
TOL_MAX_SET = 1.8e-3
TRUST_RADIUS = None
continued: bool = False
def __init__(self, infile: TextIO, outfile: TextIO) -> None:
self.infile = infile
self.outfile = outfile
self.system = System()
self.dice = Dice(infile, outfile)
self.dice_keywords = [
a
for a in dir(self.dice)
if not a.startswith("__") and not callable(getattr(self.dice, a))
]
self.gaussian = Gaussian()
self.gaussian_keywords = [
a
for a in dir(self.gaussian)
if not a.startswith("__") and not callable(getattr(self.gaussian, a))
]
@NotNull(
requiredArgs=["maxcyc", "opt", "nprocs", "qmprog", "altsteps"]
)
def updateKeywords(self, **data):
self.__dict__.update(**data)
def read_keywords(self) -> None:
with self.infile as f:
data = yaml.load(f, Loader=yaml.SafeLoader)
self.updateKeywords(**data.get("diceplayer"))
self.dice.updateKeywords(**data.get("dice"))
self.gaussian.updateKeywords(**data.get("gaussian"))
def check_keywords(self) -> None:
min_steps = 20000
if self.dice.ljname == None:
sys.exit(
"Error: 'ljname' keyword not specified in file {}".format(self.infile)
)
if self.dice.outname == None:
sys.exit(
"Error: 'outname' keyword not specified in file {}".format(self.infile)
)
if self.dice.dens == None:
sys.exit(
"Error: 'dens' keyword not specified in file {}".format(self.infile)
)
if self.dice.nmol == 0:
sys.exit(
"Error: 'nmol' keyword not defined appropriately in file {}".format(
self.infile
)
)
if self.dice.nstep == 0:
sys.exit(
"Error: 'nstep' keyword not defined appropriately in file {}".format(
self.infile
)
)
# Check only if QM program is Gaussian:
if self.qmprog in ("g03", "g09", "g16"):
if self.gaussian.level == None:
sys.exit(
"Error: 'level' keyword not specified in file {}".format(
self.infile
)
)
if self.gaussian.gmiddle != None:
if not os.path.isfile(self.gaussian.gmiddle):
sys.exit("Error: file {} not found".format(self.gaussian.gmiddle))
if self.gaussian.gbottom != None:
if not os.path.isfile(self.gaussian.gbottom):
sys.exit("Error: file {} not found".format(self.gaussian.gbottom))
if self.gaussian.pop != "chelpg" and (
self.ghosts == "yes" or self.lps == "yes"
):
sys.exit(
"Error: ghost atoms or lone pairs only available with 'pop = chelpg')"
)
# Check only if QM program is Molcas:
# if self.qmprog == "molcas":
# if self.molcas.mbottom == None:
# sys.exit("Error: 'mbottom' keyword not specified in file {}".format(self.infile))
# else:
# if not os.path.isfile(self.molcas.mbottom):
# sys.exit("Error: file {} not found".format(self.molcas.mbottom))
# if self.molcas.basis == None:
# sys.exit("Error: 'basis' keyword not specified in file {}".format(self.infile))
if self.altsteps != 0:
# Verifica se tem mais de 1 molecula QM
# (No futuro usar o RMSD fit para poder substituir todas as moleculas QM
# no arquivo outname.xy - Need to change the __make_init_file!!)
if self.dice.nmol[0] > 1:
sys.exit(
"Error: altsteps > 0 only possible with 1 QM molecule (nmol = 1 n2 n3 n4)"
)
# if not zero, altsteps cannot be less than min_steps
self.altsteps = max(min_steps, self.altsteps)
# altsteps value is always the nearest multiple of 1000
self.altsteps = round(self.altsteps / 1000) * 1000
for i in range(len(self.dice.nstep)):
# nstep can never be less than min_steps
self.dice.nstep[i] = max(min_steps, self.dice.nstep[i])
# nstep values are always the nearest multiple of 1000
self.dice.nstep[i] = round(self.dice.nstep[i] / 1000) * 1000
# isave must be between 100 and 2000
self.dice.isave = max(100, self.dice.isave)
self.dice.isave = min(2000, self.dice.isave)
# isave value is always the nearest multiple of 100
self.dice.isave = round(self.dice.isave / 100) * 100
def print_keywords(self) -> None:
self.outfile.write(
"##########################################################################################\n"
"############# Welcome to DICEPLAYER version 1.0 #############\n"
"##########################################################################################\n"
"\n"
)
self.outfile.write("Your python version is {}\n".format(sys.version))
self.outfile.write("\n")
self.outfile.write("Program started on {}\n".format(weekday_date_time()))
self.outfile.write("\n")
self.outfile.write("Environment variables:\n")
for var in env:
self.outfile.write(
"{} = {}\n".format(
var, (os.environ[var] if var in os.environ else "Not set")
)
)
self.outfile.write(
"\n==========================================================================================\n"
" CONTROL variables being used in this run:\n"
"------------------------------------------------------------------------------------------\n"
"\n"
)
self.outfile.write("\n")
self.outfile.write(
"------------------------------------------------------------------------------------------\n"
" DICE variables being used in this run:\n"
"------------------------------------------------------------------------------------------\n"
"\n"
)
for key in sorted(self.dice_keywords):
if getattr(self.dice, key) != None:
if isinstance(getattr(self.dice, key), list):
string = " ".join(str(x) for x in getattr(self.dice, key))
self.outfile.write("{} = {}\n".format(key, string))
else:
self.outfile.write("{} = {}\n".format(key, getattr(self.dice, key)))
self.outfile.write("\n")
if self.qmprog in ("g03", "g09", "g16"):
self.outfile.write(
"------------------------------------------------------------------------------------------\n"
" GAUSSIAN variables being used in this run:\n"
"------------------------------------------------------------------------------------------\n"
"\n"
)
for key in sorted(self.gaussian_keywords):
if getattr(self.gaussian, key) != None:
if isinstance(getattr(self.gaussian, key), list):
string = " ".join(str(x) for x in getattr(self.gaussian, key))
self.outfile.write("{} = {}\n".format(key, string))
else:
self.outfile.write(
"{} = {}\n".format(key, getattr(self.gaussian, key))
)
self.outfile.write("\n")
# elif self.qmprog == "molcas":
# self.outfile.write("------------------------------------------------------------------------------------------\n"
# " MOLCAS variables being used in this run:\n"
# "------------------------------------------------------------------------------------------\n"
# "\n")
# for key in sorted(molcas):
# if molcas[key] != None:
# if isinstance(molcas[key], list):
# string = " ".join(str(x) for x in molcas[key])
# self.outfile.write("{} = {}\n".format(key, string))
# else:
# self.outfile.write("{} = {}\n".format(key, molcas[key]))
# self.outfile.write("\n")
def read_potential(self) -> None: # Deve ser atualizado para o uso de
try:
with open(self.dice.ljname) as file:
ljfile = file.readlines()
except EnvironmentError as err:
sys.exit(err)
combrule = ljfile.pop(0).split()[0]
if combrule not in ("*", "+"):
sys.exit(
"Error: expected a '*' or a '+' sign in 1st line of file {}".format(
self.dice.ljname
)
)
self.dice.combrule = combrule
ntypes = ljfile.pop(0).split()[0]
if not ntypes.isdigit():
sys.exit(
"Error: expected an integer in the 2nd line of file {}".format(
self.dice.ljname
)
)
ntypes = int(ntypes)
if ntypes != len(self.dice.nmol):
sys.exit(
"Error: number of molecule types in file {} must match that of 'nmol' keyword in file {}".format(
self.dice.ljname, self.infile
)
)
line = 2
for i in range(ntypes):
line += 1
nsites, molname = ljfile.pop(0).split()[:2]
if not nsites.isdigit():
sys.exit(
"Error: expected an integer in line {} of file {}".format(
line, self.dice.ljname
)
)
if molname is None:
sys.exit(
"Error: expected a molecule name in line {} of file {}".format(
line, self.dice.ljname
)
)
nsites = int(nsites)
self.system.add_type(nsites, Molecule(molname))
for j in range(nsites):
line += 1
new_atom = ljfile.pop(0).split()
if len(new_atom) < 8:
sys.exit(
"Error: expected at least 8 fields in line {} of file {}".format(
line, self.dice.ljname
)
)
if not new_atom[0].isdigit():
sys.exit(
"Error: expected an integer in field 1, line {} of file {}".format(
line, self.dice.ljname
)
)
lbl = int(new_atom[0])
if not new_atom[1].isdigit():
sys.exit(
"Error: expected an integer in field 2, line {} of file {}".format(
line, self.dice.ljname
)
)
atnumber = int(new_atom[1])
if (
atnumber == ghost_number and i == 0
): # Ghost atom not allowed in the QM molecule
sys.exit(
"Error: found a ghost atom in line {} of file {}".format(
line, self.dice.ljname
)
)
na = atnumber
try:
rx = float(new_atom[2])
except:
sys.exit(
"Error: expected a float in field 3, line {} of file {}".format(
line, self.dice.ljname
)
)
try:
ry = float(new_atom[3])
except:
sys.exit(
"Error: expected a float in field 4, line {} of file {}".format(
line, self.dice.ljname
)
)
try:
rz = float(new_atom[4])
except:
sys.exit(
"Error: expected a float in field 5, line {} of file {}".format(
line, self.dice.ljname
)
)
try:
chg = float(new_atom[5])
except:
sys.exit(
"Error: expected a float in field 6, line {} of file {}".format(
line, self.dice.ljname
)
)
try:
eps = float(new_atom[6])
except:
sys.exit(
"Error: expected a float in field 7, line {} of file {}".format(
line, self.dice.ljname
)
)
try:
sig = float(new_atom[7])
except:
sys.exit(
"Error: expected a float in field 8, line {} of file {}".format(
line, self.dice.ljname
)
)
mass = atommass[na]
if len(new_atom) > 8:
masskey, mass = new_atom[8].partition("=")[::2]
if masskey.lower() == "mass" and len(mass) != 0:
try:
new_mass = float(mass)
if new_mass > 0:
mass = new_mass
except:
sys.exit(
"Error: expected a positive float after 'mass=' in field 9, line {} of file {}".format(
line, self.dice.ljname
)
)
self.system.molecule[i].add_atom(
Atom(lbl, na, rx, ry, rz, chg, eps, sig)
)
to_delete = ["lbl", "na", "rx", "ry", "rz", "chg", "eps", "sig", "mass"]
for _var in to_delete:
if _var in locals() or _var in globals():
exec(f"del {_var}")
def print_potential(self) -> None:
formatstr = "{:<3d} {:>3d} {:>10.5f} {:>10.5f} {:>10.5f} {:>10.6f} {:>9.5f} {:>7.4f} {:>9.4f}\n"
self.outfile.write(
"\n"
"==========================================================================================\n"
)
self.outfile.write(
" Potential parameters from file {}:\n".format(
self.dice.ljname
)
)
self.outfile.write(
"------------------------------------------------------------------------------------------\n"
"\n"
)
self.outfile.write("Combination rule: {}\n".format(self.dice.combrule))
self.outfile.write(
"Types of molecules: {}\n\n".format(len(self.system.molecule))
)
i = 0
for mol in self.system.molecule:
i += 1
self.outfile.write(
"{} atoms in molecule type {}:\n".format(len(mol.atom), i)
)
self.outfile.write(
"---------------------------------------------------------------------------------\n"
"Lbl AN X Y Z Charge Epsilon Sigma Mass\n"
)
self.outfile.write(
"---------------------------------------------------------------------------------\n"
)
for atom in mol.atom:
self.outfile.write(
formatstr.format(
atom.lbl,
atom.na,
atom.rx,
atom.ry,
atom.rz,
atom.chg,
atom.eps,
atom.sig,
atom.mass,
)
)
self.outfile.write("\n")
if self.ghosts == "yes" or self.lps == "yes":
self.outfile.write(
"\n"
"------------------------------------------------------------------------------------------\n"
" Aditional potential parameters:\n"
"------------------------------------------------------------------------------------------\n"
)
# if player['ghosts'] == "yes":
# self.outfile.write("\n")
# self.outfile.write("{} ghost atoms appended to molecule type 1 at:\n".format(len(ghost_types)))
# self.outfile.write("---------------------------------------------------------------------------------\n")
# atoms_string = ""
# for ghost in ghost_types:
# for atom in ghost['numbers']:
# atom_sym = atomsymb[ molecules[0][atom - 1]['na'] ].strip()
# atoms_string += "{}{} ".format(atom_sym,atom)
# if ghost['type'] == "g":
# self.outfile.write(textwrap.fill("* Geometric center of atoms {}".format(atoms_string), 80))
# elif ghost['type'] == "m":
# self.outfile.write(textwrap.fill("* Center of mass of atoms {}".format(atoms_string), 80))
# elif ghost['type'] == "z":
# self.outfile.write(textwrap.fill("* Center of atomic number of atoms {}".format(atoms_string), 80))
# self.outfile.write("\n")
# if player['lps'] == 'yes':
# self.outfile.write("\n")
# self.outfile.write("{} lone pairs appended to molecule type 1:\n".format(len(lp_types)))
# self.outfile.write("---------------------------------------------------------------------------------\n")
# for lp in lp_types:
# # LP type 1 or 2
# if lp['type'] in (1, 2):
# atom1_num = lp['numbers'][0]
# atom1_sym = atomsymb[ molecules[0][atom1_num - 1]['na'] ].strip()
# atom2_num = lp['numbers'][1]
# atom2_sym = atomsymb[ molecules[0][atom2_num - 1]['na'] ].strip()
# atom3_num = lp['numbers'][2]
# atom3_sym = atomsymb[ molecules[0][atom3_num - 1]['na'] ].strip()
# self.outfile.write(textwrap.fill(
# "* Type {} on atom {}{} with {}{} {}{}. Alpha = {:<5.1f} Deg and D = {:<4.2f} Angs".format(
# lp['type'], atom1_sym, atom1_num, atom2_sym, atom2_num, atom3_sym, atom3_num, lp['alpha'],
# lp['dist']), 86))
# self.outfile.write("\n")
# # Other LP types
self.outfile.write(
"\n"
"==========================================================================================\n"
)
def check_executables(self) -> None:
self.outfile.write("\n")
self.outfile.write(90 * "=")
self.outfile.write("\n\n")
dice_path = shutil.which(self.dice.progname)
if dice_path != None:
self.outfile.write(
"Program {} found at {}\n".format(self.dice.progname, dice_path)
)
self.dice.path = dice_path
else:
sys.exit("Error: cannot find dice executable")
qmprog_path = shutil.which(self.gaussian.qmprog)
if qmprog_path != None:
self.outfile.write(
"Program {} found at {}\n".format(self.gaussian.qmprog, qmprog_path)
)
self.gaussian.path = qmprog_path
else:
sys.exit("Error: cannot find {} executable".format(self.gaussian.qmprog))
if self.gaussian.qmprog in ("g03", "g09", "g16"):
formchk_path = shutil.which("formchk")
if formchk_path != None:
self.outfile.write("Program formchk found at {}\n".format(formchk_path))
else:
sys.exit("Error: cannot find formchk executable")
def dice_start(self, cycle: int):
self.dice.configure(
StepDTO(
initcyc=self.initcyc,
nprocs=self.nprocs,
altsteps=self.altsteps,
nmol=self.system.nmols,
molecule=self.system.molecule,
)
)
self.dice.start(cycle)
self.dice.reset()
def gaussian_start(self, cycle: int, geomsfh: TextIO):
self.gaussian.configure(
StepDTO(
initcyc=self.initcyc,
nprocs=self.nprocs,
ncores=self.dice.ncores,
altsteps=self.altsteps,
switchcyc=self.switchcyc,
opt=self.opt,
nmol=self.system.nmols,
molecule=self.system.molecule
)
)
# Make ASEC
self.outfile.write("\nBuilding the ASEC and vdW meanfields... ")
asec_charges = self.populate_asec_vdw(cycle)
step = self.gaussian.start(cycle, self.outfile, asec_charges, self.readhessian)
if self.opt:
position = step.position
## Update the geometry of the reference molecule
self.system.update_molecule(position, self.outfile)
## Print new geometry in geoms.xyz
self.system.print_geom(cycle, geomsfh)
else:
charges = step.charges
self.system.molecule[0].updateCharges(charges)
self.system.printChargesAndDipole(cycle, self.outfile)
self.gaussian.reset()
def populate_asec_vdw(self, cycle) -> List[Dict]:
# Both asec_charges and vdw_meanfield will utilize the Molecule() class and Atoms() with some None elements
asec_charges = []
if self.dice.nstep[-1] % self.dice.isave == 0:
nconfigs = round(self.dice.nstep[-1] / self.dice.isave)
else:
nconfigs = int(self.dice.nstep[-1] / self.dice.isave)
norm_factor = nconfigs * self.nprocs
nsitesref = len(self.system.molecule[0].atom)
nsites_total = self.dice.nmol[0] * nsitesref
for i in range(1, len(self.dice.nmol)):
nsites_total += self.dice.nmol[i] * len(self.system.molecule[i].atom)
thickness = []
picked_mols = []
for proc in range(1, self.nprocs + 1): # Run over folders
path = (
"simfiles"
+ os.sep
+ "step{:02d}".format(cycle)
+ os.sep
+ "p{:02d}".format(proc)
)
file = path + os.sep + self.dice.outname + ".xyz"
if not os.path.isfile(file):
sys.exit("Error: cannot find file {}".format(file))
try:
with open(file) as xyzfh:
xyzfile = xyzfh.readlines()
except:
sys.exit("Error: cannot open file {}".format(file))
for config in range(nconfigs): # Run over configs in a folder
if int(xyzfile.pop(0).split()[0]) != nsites_total:
sys.exit("Error: wrong number of sites in file {}".format(file))
box = xyzfile.pop(0).split()[-3:]
box = [float(box[0]), float(box[1]), float(box[2])]
sizes = self.system.molecule[0].sizes_of_molecule()
thickness.append(
min(
[
(box[0] - sizes[0]) / 2,
(box[1] - sizes[1]) / 2,
(box[2] - sizes[2]) / 2,
]
)
)
xyzfile = xyzfile[nsitesref:]
mol_count = 0
for type in range(len(self.dice.nmol)):
if type == 0:
nmols = self.dice.nmol[0] - 1
else:
nmols = self.dice.nmol[type]
for mol in range(nmols):
new_molecule = Molecule("ASEC TMP MOLECULE")
for site in range(len(self.system.molecule[type].atom)):
line = xyzfile.pop(0).split()
if (
line[0].title()
!= atomsymb[self.system.molecule[type].atom[site].na].strip()
):
sys.exit("Error reading file {}".format(file))
new_molecule.add_atom(
Atom(
self.system.molecule[type].atom[site].lbl,
self.system.molecule[type].atom[site].na,
float(line[1]),
float(line[2]),
float(line[3]),
self.system.molecule[type].atom[site].chg,
self.system.molecule[type].atom[site].eps,
self.system.molecule[type].atom[site].sig,
)
)
dist = self.system.molecule[0].minimum_distance(new_molecule)
if dist < thickness[-1]:
mol_count += 1
for atom in new_molecule.atom:
asec_charges.append({"lbl": atomsymb[atom.na], "rx": atom.rx, "ry": atom.ry, "rz": atom.rz, "chg": atom.chg})
# if self.vdwforces == "yes":
# vdw_meanfield[-1]["rx"] = atom["rx"]
# vdw_meanfield[-1]["ry"] = atom["ry"]
# vdw_meanfield[-1]["rz"] = atom["rz"]
# vdw_meanfield[-1]["eps"] = atom["eps"]
# vdw_meanfield[-1]["sig"] = atom["sig"]
# #### Read lines with ghosts or lps in molecules of type 0 (reference)
# #### and, if dist < thickness, appends to asec
# if type == 0:
# for ghost in ghost_atoms:
# line = xyzfile.pop(0).split()
# if line[0] != dice_ghost_label:
# sys.exit("Error reading file {}".format(file))
# if dist < thickness[-1]:
# asec_charges.append({})
# asec_charges[-1]['rx'] = float(line[1])
# asec_charges[-1]['ry'] = float(line[2])
# asec_charges[-1]['rz'] = float(line[3])
# asec_charges[-1]['chg'] = ghost['chg'] / norm_factor
# for lp in lp_atoms:
# line = xyzfile.pop(0).split()
# if line[0] != dice_ghost_label:
# sys.exit("Error reading file {}".format(file))
# if dist < thickness[-1]:
# asec_charges.append({})
# asec_charges[-1]['rx'] = float(line[1])
# asec_charges[-1]['ry'] = float(line[2])
# asec_charges[-1]['rz'] = float(line[3])
# asec_charges[-1]['chg'] = lp['chg'] / norm_factor
picked_mols.append(mol_count)
self.outfile.write("Done\n")
string = "In average, {:^7.2f} molecules ".format(
sum(picked_mols) / norm_factor
)
string += "were selected from each of the {} configurations ".format(
len(picked_mols)
)
string += (
"of the production simulations to form the ASEC, comprising a shell with "
)
string += "minimum thickness of {:>6.2f} Angstrom\n".format(
sum(thickness) / norm_factor
)
self.outfile.write(textwrap.fill(string, 86))
self.outfile.write("\n")
otherfh = open("ASEC.xyz", "w", 1)
for charge in asec_charges:
otherfh.write(
"{} {:>10.5f} {:>10.5f} {:>10.5f}\n".format(
charge['lbl'], charge['rx'], charge['ry'], charge['rz']
)
)
otherfh.close()
for charge in asec_charges:
charge['chg'] /= norm_factor
return asec_charges

View File

@@ -1,67 +0,0 @@
import os, sys, time
from posixpath import sep
import shutil, gzip
####################################### functions ######################################
def weekday_date_time():
return time.strftime("%A, %d %b %Y at %H:%M:%S")
def date_time():
return time.strftime("%d %b %Y at %H:%M:%S")
def compress_files_1mb(path):
working_dir = os.getcwd()
os.chdir(path)
files = filter(os.path.isfile, os.listdir(os.curdir))
for file in files:
if os.path.getsize(file) > 1024 * 1024: ## If bigger than 1MB
filegz = file + ".gz"
try:
with open(file, 'rb') as f_in:
with gzip.open(filegz, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
except:
sys.exit("Error: cannot compress file {}".format(file))
os.chdir(working_dir)
return
def make_simulation_dir():
sim_dir = "simfiles"
if os.path.exists(sim_dir):
sys.exit("Error: a file or a directory {} already exists, move or delete de simfiles directory to continue.".format(sim_dir))
try:
os.makedirs(sim_dir)
except:
sys.exit("Error: cannot make directory {}".format(sim_dir))
def make_step_dir(cycle):
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle)
path = sim_dir + os.sep + step_dir
if os.path.exists(path):
sys.exit("Error: a file or directory {} already exists".format(step_dir))
try:
os.makedirs(path)
except:
sys.exit("Error: cannot make directory {}".format(step_dir))
def make_qm_dir(cycle):
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle)
path = sim_dir + os.sep + step_dir + os.sep + "qm"
try:
os.makedirs(path)
except:
sys.exit("Error: cannot make directory {}".format(path))

View File

@@ -1,263 +0,0 @@
# import sys, math
# from copy import deepcopy
# import numpy as np
# from numpy import linalg
# from diceplayer.DPpack.SetGlobals import *
# epsilon = 1e-8
# ####################################### functions ######################################
# def best_previous_point():
# min_energy = 0
# idx = 0
# for energy in internal["energy"][:-1]:
# if energy < min_energy or abs(energy - min_energy) < 1e-10:
# min_energy = energy
# min_idx = idx
# idx += 1
# return min_idx
# def best_point():
# min_energy = 0
# idx = 0
# for energy in internal["energy"]:
# if energy < min_energy or abs(energy - min_energy) < 1e-10:
# min_energy = energy
# min_idx = idx
# idx += 1
# return min_idx
# def line_search(fh):
# X1 = internal["position"][-1] # numpy array
# e1 = internal["energy"][-1]
# G1 = internal["gradient"][-1] # numpy array
# idx = best_previous_point()
# X0 = internal["position"][idx] # numpy array
# e0 = internal["energy"][idx]
# G0 = internal["gradient"][idx] # numpy array
# # First try a quartic fit
# fh.write("Attempting a quartic fit.\n")
# success, y0 = quartic_fit(X0, X1, e0, e1, G0, G1, fh)
# if success and y0 > 0:
# if y0 < 1:
# new_point = X0 + y0 * (X1 - X0)
# new_gradient = interpolate_gradient(G0, G1, y0)
# new_gradient = perpendicular_projection(new_gradient, X1 - X0)
# fh.write("Line search succeded.\n")
# return True, new_point, new_gradient
# else:
# idx = best_point()
# if idx == len(internal["energy"]) - 1:
# new_point = X0 + y0 * (X1 - X0)
# new_gradient = interpolate_gradient(G0, G1, y0)
# new_gradient = perpendicular_projection(new_gradient, X1 - X0)
# fh.write("Line search succeded.\n")
# return True, new_point, new_gradient
# else:
# fh.write("Quartic step is not acceptable. ")
# elif success:
# fh.write("Quartic step is not acceptable. ")
# # If no condition is met, then y0 is unacceptable. Try the cubic fit next
# fh.write("Attempting a cubic fit.\n")
# success, y0 = cubic_fit(X0, X1, e0, e1, G0, G1, fh)
# if success and y0 > 0:
# if y0 < 1:
# new_point = X0 + y0 * (X1 - X0)
# new_gradient = interpolate_gradient(G0, G1, y0)
# new_gradient = perpendicular_projection(new_gradient, X1 - X0)
# fh.write("Line search succeded.\n")
# return True, new_point, new_gradient
# else:
# previous_step = X1 - internal["position"][-2]
# previous_step_size = linalg.norm(previous_step)
# new_point = X0 + y0 * (X1 - X0)
# step = new_point - X1
# step_size = linalg.norm(step)
# if step_size < previous_step_size:
# new_gradient = interpolate_gradient(G0, G1, y0)
# new_gradient = perpendicular_projection(new_gradient, X1 - X0)
# fh.write("Line search succeded.\n")
# return True, new_point, new_gradient
# else:
# fh.write("Cubic step is not acceptable. ")
# elif success:
# fh.write("Cubic step is not acceptable. ")
# # If no condition is met again, then all fits fail.
# fh.write("All fits fail. ")
# # Then, if the latest point is not the best, use y0 = 0.5 (step to the midpoint)
# idx = best_point()
# if idx < len(internal["energy"]) - 1:
# y0 = 0.5
# new_point = X0 + y0 * (X1 - X0)
# new_gradient = interpolate_gradient(G0, G1, y0)
# new_gradient = perpendicular_projection(new_gradient, X1 - X0)
# fh.write("Moving to the midpoint.\n")
# return True, new_point, new_gradient
# # If the latest point is the best point, no linear search is done
# fh.write("No linear search will be used in this step.\n")
# return False, None, None
# ## For cubic and quartic fits, G0 and G1 are the gradient vectors
# def cubic_fit(X0, X1, e0, e1, G0, G1, fh):
# line = X1 - X0
# line /= linalg.norm(line)
# g0 = np.dot(G0, line)
# g1 = np.dot(G1, line)
# De = e1 - e0
# fh.write(
# "De = {:<18.15e} g0 = {:<12.8f} g1 = {:<12.8f}\n".format(De, g0, g1)
# )
# alpha = g1 + g0 - 2 * De
# if abs(alpha) < epsilon:
# fh.write("Cubic fit failed: alpha too small\n")
# return False, None
# beta = 3 * De - 2 * g0 - g1
# discriminant = 4 * (beta**2 - 3 * alpha * g0)
# if discriminant < 0:
# fh.write("Cubic fit failed: no minimum found (negative Delta)\n")
# return False, None
# if abs(discriminant) < epsilon:
# fh.write("Cubic fit failed: no minimum found (null Delta)\n")
# return False, None
# y0 = (-beta + math.sqrt(discriminant / 4)) / (3 * alpha)
# fh.write("Minimum found with y0 = {:<8.4f}\n".format(y0))
# return True, y0
# def quartic_fit(X0, X1, e0, e1, G0, G1, fh):
# line = X1 - X0
# line /= linalg.norm(line)
# g0 = np.dot(G0, line)
# g1 = np.dot(G1, line)
# De = e1 - e0
# Dg = g1 - g0
# fh.write(
# "De = {:<18.15e} g0 = {:<12.8f} g1 = {:<12.8f}\n".format(De, g0, g1)
# )
# if Dg < 0 or De - g0 < 0:
# fh.write("Quartic fit failed: negative alpha\n")
# return False, None
# if abs(Dg) < epsilon or abs(De - g0) < epsilon:
# fh.write("Quartic fit failed: alpha too small\n")
# return False, None
# discriminant = 16 * (Dg**2 - 3 * (g1 + g0 - 2 * De) ** 2)
# if discriminant < 0:
# fh.write("Quartic fit failed: no minimum found (negative Delta)\n")
# return False, None
# alpha1 = (Dg + math.sqrt(discriminant / 16)) / 2
# alpha2 = (Dg - math.sqrt(discriminant / 16)) / 2
# fh.write("alpha1 = {:<7.4e} alpha2 = {:<7.4e}\n".format(alpha1, alpha2))
# alpha = alpha1
# beta = g1 + g0 - 2 * De - 2 * alpha
# gamma = De - g0 - alpha - beta
# y0 = (-1 / (2 * alpha)) * (
# (beta**3 - 4 * alpha * beta * gamma + 8 * g0 * alpha**2) / 4
# ) ** (1 / 3)
# fh.write("Minimum found with y0 = {:<8.4f}\n".format(y0))
# return True, y0
# def rfo_step(gradient, hessian, type):
# dim = len(gradient)
# aug_hessian = []
# for i in range(dim):
# aug_hessian.extend(hessian[i, :].tolist())
# aug_hessian.append(gradient[i])
# aug_hessian.extend(gradient.tolist())
# aug_hessian.append(0)
# aug_hessian = np.array(aug_hessian).reshape(dim + 1, dim + 1)
# evals, evecs = linalg.eigh(aug_hessian)
# if type == "min":
# step = np.array(evecs[:-1, 0])
# elif type == "ts":
# step = np.array(evecs[:-1, 1])
# return step
# def update_trust_radius():
# if internal["trust_radius"] == None:
# internal["trust_radius"] = player["maxstep"]
# elif len(internal["energy"]) > 1:
# X1 = internal["position"][-1]
# X0 = internal["position"][-2]
# Dx = X1 - X0
# displace = linalg.norm(Dx)
# e1 = internal["energy"][-1]
# e0 = internal["energy"][-2]
# De = e1 - e0
# g0 = internal["gradient"][-2]
# h0 = internal["hessian"][-2]
# rho = De / (np.dot(g0, Dx) + 0.5 * np.dot(Dx, np.matmul(h0, Dx.T).T))
# if rho > 0.75 and displace > 0.8 * internal["trust_radius"]:
# internal["trust_radius"] = 2 * internal["trust_radius"]
# elif rho < 0.25:
# internal["trust_radius"] = 0.25 * displace
# return
# def interpolate_gradient(G0, G1, y0):
# DG = G1 - G0
# gradient = G0 + y0 * DG
# return gradient
# def perpendicular_projection(vector, line):
# direction = line / linalg.norm(line)
# projection = np.dot(vector, direction) * direction
# return vector - projection

View File

@@ -1,21 +0,0 @@
from dataclasses import dataclass
from typing import List
from diceplayer.DPpack.Environment.Molecule import Molecule
@dataclass
class StepDTO:
cycle: int = None
initcyc: int = None
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

@@ -1,21 +1,19 @@
from diceplayer.player import Player
from pathlib import Path
import argparse
import os
import logging
import pickle
import shutil
import sys
import setproctitle
from diceplayer.DPpack.Player import Player
from diceplayer.DPpack.Utils.Misc import *
__VERSION = "v0.0.1"
os.nice(+19)
setproctitle.setproctitle("diceplayer-{}".format(__VERSION))
if __name__ == "__main__":
#### Read and store the arguments passed to the program ####
#### and set the usage and help messages ####
"""
Read and store the arguments passed to the program
and set the usage and help messages
"""
parser = argparse.ArgumentParser(prog="Diceplayer")
parser.add_argument(
@@ -38,173 +36,30 @@ if __name__ == "__main__":
metavar="OUTFILE",
help="output file of diceplayer [default = run.log]"
)
## Study the option of a parameter for continuing the last process via data from control.in and run.log files
args = parser.parse_args()
#### Open OUTFILE for writing and print keywords and initial info
# Open OUTFILE for writing and print keywords and initial info
try:
if args.opt_continue and os.path.exists(args.outfile):
pickle_path = Path("latest-step.pkl")
if args.opt_continue and pickle_path.exists():
with open(pickle_path) as pickle_file:
save = pickle.load(pickle_file)
save = pickle.load(open("latest-step.pkl", "rb"))
if os.path.isfile(args.outfile + ".backup"):
os.remove(args.outfile + ".backup")
os.rename(args.outfile, args.outfile + ".backup")
outfile = open(args.outfile, "w", 1)
elif os.path.exists(args.outfile):
os.rename(args.outfile, args.outfile + ".backup")
outfile = open(args.outfile, "w", 1)
else:
outfile = open(args.outfile, "w", 1)
output_path = Path(args.outfile)
if output_path.exists():
output_path.rename(str(output_path)+".backup")
except Exception as err:
sys.exit(err)
try:
if os.path.exists(args.infile):
infile = open(args.infile, "r")
except Exception as err:
sys.exit(err)
#### Read and check the keywords in INFILE
player = Player(infile, outfile)
player.read_keywords()
player.check_keywords()
player.print_keywords()
if args.opt_continue:
player.initcyc = save[0] + 1
player.system = save[1]
else:
player.initcyc = 1
player.read_potential()
#### Check whether the executables are in the path
#### and print potential to Log File
player.check_executables()
player.print_potential()
#### Bring the molecules to standard orientation and prints info about them
for i in range(len(player.system.molecule)):
player.outfile.write(
"\nMolecule type {} - {}:\n\n".format(
i + 1, player.system.molecule[i].molname
logging.basicConfig(
filename=args.outfile,
format='%(message)s',
level=logging.INFO
)
)
player.system.molecule[i].print_mol_info(player.outfile)
player.outfile.write(
" Translating and rotating molecule to standard orientation..."
)
player.system.molecule[i].standard_orientation()
player.outfile.write(" Done\n\n New values:\n")
player.system.molecule[i].print_mol_info(player.outfile)
player.outfile.write(90 * "=")
player.outfile.write("\n")
player = Player(args.infile)
if not args.opt_continue:
make_simulation_dir()
else:
simdir = "simfiles"
stepdir = "step{:02d}".format(player.initcyc)
if os.path.exists(simdir + os.sep + stepdir):
shutil.rmtree(simdir + os.sep + stepdir)
#### Open the geoms.xyz file and prints the initial geometry if starting from zero
if player.initcyc == 1:
try:
path = "geoms.xyz"
geomsfh = open(path, "w", 1)
except EnvironmentError as err:
sys.exit(err)
player.system.print_geom(0, geomsfh)
geomsfh.write(40 * "-" + "\n")
else:
try:
path = "geoms.xyz"
geomsfh = open(path, "a", 1)
except EnvironmentError as err:
sys.exit(err)
player.outfile.write("\nStarting the iterative process.\n")
## Initial position (in Bohr)
position = player.system.molecule[0].read_position()
## If restarting, read the last gradient and hessian
# if player.initcyc > 1:
# if player.qmprog in ("g03", "g09", "g16"):
# Gaussian.read_forces("grad_hessian.dat")
# Gaussian.read_hessian_fchk("grad_hessian.dat")
# if player['qmprog'] == "molcas":
# Molcas.read_forces("grad_hessian.dat")
# Molcas.read_hessian("grad_hessian.dat")
###
### Start the iterative process
###
player.outfile.write("\n" + 90 * "-" + "\n")
for cycle in range(player.initcyc, player.initcyc + player.maxcyc):
player.outfile.write("{} Step # {}\n".format(40 * " ", cycle))
player.outfile.write(90 * "-" + "\n\n")
make_step_dir(cycle)
####
#### Start block of parallel simulations
####
player.dice_start(cycle)
###
### End of parallel simulations block
###
## After ASEC is built, compress files bigger than 1MB
for proc in range(1, player.nprocs + 1):
path = "simfiles"+os.sep+"step{:02d}".format(cycle) + os.sep + "p{:02d}".format(proc)
compress_files_1mb(path)
###
### Start QM calculation
###
player.gaussian_start(cycle, geomsfh)
player.system.print_geom(cycle, geomsfh)
geomsfh.write(40 * "-" + "\n")
player.outfile.write("\n+" + 88 * "-" + "+\n")
pickle.dump([cycle, player.system], open("latest-step.pkl", "wb"))
####
#### End of the iterative process
####
## imprimir ultimas mensagens, criar um arquivo de potencial para ser usado em eventual
## continuacao, fechar arquivos (geoms.xyz, run.log, ...)
player.outfile.write("\nDiceplayer finished normally!\n")
player.outfile.close()
####
#### End of the program
####
player.start()

274
diceplayer/player.py Normal file
View File

@@ -0,0 +1,274 @@
from diceplayer.shared.environment.atom import Atom
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from diceplayer.shared.config.gaussian_dto import GaussianDTO
from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.environment.system import System
from diceplayer.shared.utils.misc import weekday_date_time
from diceplayer.shared.config.player_dto import PlayerDTO
from diceplayer.shared.external.gaussian import Gaussian
from diceplayer.shared.config.dice_dto import DiceDTO
from diceplayer.shared.external.dice import Dice
from dataclasses import fields
from pathlib import Path
from typing import Type
import logging
import yaml
import sys
import os
from diceplayer.shared.utils.ptable import atommass
ENV = ["OMP_STACKSIZE"]
class Player:
__slots__ = [
'config',
'system',
'dice',
'gaussian',
]
def __init__(self, infile: str):
config_data = self.read_keywords(infile)
self.system = System()
self.config = self.set_config(
config_data.get("diceplayer")
)
self.gaussian = Gaussian(config_data.get("gaussian"))
self.dice = Dice(config_data.get("dice"))
def start(self):
self.print_keywords()
self.create_simulation_dir()
self.read_potentials()
# self.print_potentials()
def create_simulation_dir(self):
simulation_dir_path = Path(self.config.simulation_dir)
if simulation_dir_path.exists():
raise FileExistsError(
f"Error: a file or a directory {self.config.simulation_dir} already exists,"
f" move or delete the simfiles directory to continue."
)
try:
simulation_dir_path.mkdir()
except FileExistsError:
OSError(
f"Error: cannot make directory {self.config.simulation_dir}"
)
def print_keywords(self) -> None:
def log_keywords(config: Dataclass, dto: Type[Dataclass]):
for key in sorted(list(map(lambda f: f.name, fields(dto)))):
if getattr(config, key) is not None:
if isinstance(getattr(config, key), list):
string = " ".join(str(x) for x in getattr(config, key))
logging.info(f"{key} = [ {string} ]")
else:
logging.info(f"{key} = {getattr(config, key)}")
logging.info(
"##########################################################################################\n"
"############# Welcome to DICEPLAYER version 1.0 #############\n"
"##########################################################################################\n"
"\n"
)
logging.info("Your python version is {}\n".format(sys.version))
logging.info("\n")
logging.info("Program started on {}\n".format(weekday_date_time()))
logging.info("\n")
logging.info("Environment variables:\n")
for var in ENV:
logging.info(
"{} = {}\n".format(
var, (os.environ[var] if var in os.environ else "Not set")
)
)
logging.info(
"\n==========================================================================================\n"
" CONTROL variables being used in this run:\n"
"------------------------------------------------------------------------------------------\n"
"\n"
)
logging.info("\n")
logging.info(
"------------------------------------------------------------------------------------------\n"
" DICE variables being used in this run:\n"
"------------------------------------------------------------------------------------------\n"
"\n"
)
log_keywords(self.dice.config, DiceDTO)
logging.info("\n")
logging.info(
"------------------------------------------------------------------------------------------\n"
" GAUSSIAN variables being used in this run:\n"
"------------------------------------------------------------------------------------------\n"
"\n"
)
log_keywords(self.gaussian.config, GaussianDTO)
logging.info("\n")
def read_potentials(self):
try:
with open(self.dice.config.ljname) as file:
ljdata = file.readlines()
except FileNotFoundError:
raise RuntimeError(
f"Potential file {self.dice.config.ljname} not found."
)
combrule = ljdata.pop(0).split()[0]
if combrule not in ("*", "+"):
sys.exit(
"Error: expected a '*' or a '+' sign in 1st line of file {}".format(
self.dice.config.ljname
)
)
self.dice.combrule = combrule
ntypes = ljdata.pop(0).split()[0]
if not ntypes.isdigit():
sys.exit(
"Error: expected an integer in the 2nd line of file {}".format(
self.dice.config.ljname
)
)
ntypes = int(ntypes)
if ntypes != len(self.dice.config.nmol):
sys.exit(
f"Error: number of molecule types in file {self.dice.config.ljname}"
f"must match that of 'nmol' keyword in config file"
)
for i in range(ntypes):
nsites, molname = ljdata.pop(0).split()[:2]
if not nsites.isdigit():
raise ValueError(
f"Error: expected nsites to be an integer for molecule type {i}"
)
if molname is None:
raise ValueError(
f"Error: expected molecule name for molecule type {i}"
)
nsites = int(nsites)
self.system.add_type(nsites, Molecule(molname))
atom_fields = ["lbl", "na", "rx", "ry", "rz", "chg", "eps", "sig"]
for j in range(nsites):
new_atom = dict(zip(
atom_fields,
ljdata.pop(0).split()
))
self.system.molecule[i].add_atom(
Atom(**self.validate_atom_dict(i, j, new_atom))
)
def dice_start(self):
self.dice.start()
def gaussian_start(self):
self.gaussian.start()
@staticmethod
def validate_atom_dict(molecule_type, molecule_site, atom_dict: dict) -> dict:
molecule_type += 1
molecule_site += 1
if len(atom_dict) < 8:
raise ValueError(
f'Invalid number of fields for site {molecule_site} for molecule type {molecule_type}.'
)
try:
atom_dict['lbl'] = int(atom_dict['lbl'])
except ValueError:
raise ValueError(
f'Invalid lbl fields for site {molecule_site} for molecule type {molecule_type}.'
)
try:
atom_dict['na'] = int(atom_dict['na'])
except ValueError:
raise ValueError(
f'Invalid na fields for site {molecule_site} for molecule type {molecule_type}.'
)
try:
atom_dict['rx'] = float(atom_dict['rx'])
except ValueError:
raise ValueError(
f'Invalid rx fields for site {molecule_site} for molecule type {molecule_type}.'
f'Value must be a float.'
)
try:
atom_dict['ry'] = float(atom_dict['ry'])
except ValueError:
raise ValueError(
f'Invalid ry fields for site {molecule_site} for molecule type {molecule_type}.'
f'Value must be a float.'
)
try:
atom_dict['rz'] = float(atom_dict['rx'])
except ValueError:
raise ValueError(
f'Invalid rz fields for site {molecule_site} for molecule type {molecule_type}.'
f'Value must be a float.'
)
try:
atom_dict['chg'] = float(atom_dict['chg'])
except ValueError:
raise ValueError(
f'Invalid chg fields for site {molecule_site} for molecule type {molecule_type}.'
f'Value must be a float.'
)
try:
atom_dict['eps'] = float(atom_dict['eps'])
except ValueError:
raise ValueError(
f'Invalid eps fields for site {molecule_site} for molecule type {molecule_type}.'
f'Value must be a float.'
)
try:
atom_dict['sig'] = float(atom_dict['sig'])
except ValueError:
raise ValueError(
f'Invalid sig fields for site {molecule_site} for molecule type {molecule_type}.'
f'Value must be a float.'
)
return atom_dict
@staticmethod
def set_config(data: dict) -> PlayerDTO:
return PlayerDTO.from_dict(data)
@staticmethod
def read_keywords(infile) -> dict:
with open(infile, 'r') as yml_file:
return yaml.load(yml_file, Loader=yaml.SafeLoader)

View File

@@ -0,0 +1,54 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from dataclasses import dataclass
from dacite import from_dict
from typing import List
@dataclass
class DiceDTO(Dataclass):
ljname: str
outname: str
ncores: int
dens: float
nmol: List[int]
nstep: List[int]
upbuf = 360
combrule = "*"
isave: int = 1000
press: float = 1.0
temp: float = 300.0
randominit: str = 'first'
def __post_init__(self):
if self.ljname is None:
raise ValueError(
"Error: 'ljname' keyword not specified in config file"
)
if self.outname is None:
raise ValueError(
"Error: 'outname' keyword not specified in config file"
)
if self.dens is None:
raise ValueError(
"Error: 'dens' keyword not specified in config file"
)
if self.nmol == 0:
raise ValueError(
"Error: 'nmol' keyword not defined appropriately in config file"
)
if self.nstep == 0:
raise ValueError(
"Error: 'nstep' keyword not defined appropriately in config file"
)
@classmethod
def from_dict(cls, param: dict):
return from_dict(DiceDTO, param)

View File

@@ -0,0 +1,28 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from dataclasses import dataclass
from dacite import from_dict
@dataclass
class GaussianDTO(Dataclass):
level: str
qmprog: str
keywords: str
chgmult = [0, 1]
pop: str = 'chelpg'
def __post_init__(self):
if self.qmprog not in ("g03", "g09", "g16"):
raise ValueError(
"Error: invalid qmprog value."
)
if self.level is None:
raise ValueError(
"Error: 'level' keyword not specified in config file."
)
@classmethod
def from_dict(cls, param: dict):
return from_dict(GaussianDTO, param)

View File

@@ -0,0 +1,24 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from dataclasses import dataclass
from dacite import from_dict
@dataclass
class PlayerDTO(Dataclass):
opt: bool
maxcyc: int
nprocs: int
qmprog: str = 'g16'
altsteps: int = 20000
simulation_dir = 'simfiles'
def __post_init__(self):
MIN_STEP = 20000
# altsteps value is always the nearest multiple of 1000
self.altsteps = round(max(MIN_STEP, self.altsteps) / 1000) * 1000
@classmethod
def from_dict(cls, param: dict):
return from_dict(PlayerDTO, param)

View File

@@ -1,5 +1,4 @@
from diceplayer.DPpack.Utils.PTable import *
from diceplayer.DPpack.Utils.Misc import *
from diceplayer.shared.utils.ptable import atommass
class Atom:
@@ -16,6 +15,7 @@ class Atom:
eps (float): quantum number epsilon of the represented atom.
sig (float): quantum number sigma of the represented atom.
"""
def __init__(
self,
lbl: int,

View File

@@ -1,23 +1,15 @@
from diceplayer.DPpack.Utils.PTable import *
from diceplayer.DPpack.Utils.Misc import *
from diceplayer.DPpack.Environment.Atom import Atom
from typing import IO, Any, Final, Tuple, List, TextIO
from nptyping import Float, NDArray, Shape
from numpy import linalg
import numpy as np
from copy import deepcopy
import sys, math
import sys
import logging
import math
from copy import deepcopy
from typing import List, Any, Tuple, Final, Union
import numpy as np
from nptyping import NDArray, Shape, Float
from numpy.linalg import linalg
""" Constants of unit conversion """
BOHR2ANG: Final[float] = 0.52917721092
ANG2BOHR: Final[float] = 1 / BOHR2ANG
from diceplayer.shared.environment.atom import Atom
from diceplayer.shared.utils.misc import BOHR2ANG
from diceplayer.shared.utils.ptable import ghost_number
class Molecule:
@@ -54,7 +46,7 @@ class Molecule:
self.lp_atoms: List[Atom] = []
self.total_mass: int = 0
self.com: NDArray[Any, Any] = None
self.com: Union[None, NDArray[Any, Any]] = None
def add_atom(self, a: Atom) -> None:
"""
@@ -67,13 +59,9 @@ class Molecule:
self.atom.append(a)
self.total_mass += a.mass
if a.na == ghost_number:
self.ghost_atoms.append(self.atom.index(a))
self.center_of_mass()
def center_of_mass(self) -> None:
def center_of_mass(self) -> NDArray[Any, Any]:
"""
Calculates the center of mass of the molecule
"""
@@ -81,11 +69,12 @@ class Molecule:
self.com = np.zeros(3)
for atom in self.atom:
self.com += atom.mass * np.array([atom.rx, atom.ry, atom.rz])
self.com = self.com / self.total_mass
return self.com
def center_of_mass_to_origin(self) -> None:
"""
Updated positions based on the center of mass of the molecule
@@ -94,7 +83,6 @@ class 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]
@@ -154,7 +142,6 @@ class Molecule:
Ixx = Ixy = Ixz = Iyy = Iyz = Izz = 0.0
for atom in self.atom:
dx = atom.rx - self.com[0]
dy = atom.ry - self.com[1]
dz = atom.rz - self.com[2]
@@ -215,7 +202,7 @@ class Molecule:
try:
evals, evecs = linalg.eigh(self.inertia_tensor())
except:
sys.exit("Error: diagonalization of inertia tensor did not converge")
raise RuntimeError("Error: diagonalization of inertia tensor did not converge")
return evals, evecs
@@ -305,21 +292,18 @@ class Molecule:
evals, evecs = self.principal_axes()
if round(linalg.det(evecs)) == -1:
evecs[0, 2] *= -1
evecs[1, 2] *= -1
evecs[2, 2] *= -1
if round(linalg.det(evecs)) != 1:
sys.exit(
raise RuntimeError(
"Error: could not make a rotation matrix while adopting the standard orientation"
)
rot_matrix = evecs.T
for atom in self.atom:
position = np.array([atom.rx, atom.ry, atom.rz])
new_position = np.matmul(rot_matrix, position.T).T
@@ -341,22 +325,18 @@ class Molecule:
new_molecule = deepcopy(self)
for atom in new_molecule.atom:
atom.rx += vector[0]
atom.ry += vector[1]
atom.rz += vector[2]
return new_molecule
def print_mol_info(self, fh: TextIO) -> None:
def print_mol_info(self) -> None:
"""
Prints the Molecule information into a Output File
Args:
fh (TextIO): Output File
"""
fh.write(
logging.info(
" Center of mass = ( {:>10.4f} , {:>10.4f} , {:>10.4f} )\n".format(
self.com[0], self.com[1], self.com[2]
)
@@ -364,45 +344,45 @@ class Molecule:
inertia = self.inertia_tensor()
evals, evecs = self.principal_axes()
fh.write(
logging.info(
" Moments of inertia = {:>9E} {:>9E} {:>9E}\n".format(
evals[0], evals[1], evals[2]
)
)
fh.write(
logging.info(
" Major principal axis = ( {:>10.6f} , {:>10.6f} , {:>10.6f} )\n".format(
evecs[0, 0], evecs[1, 0], evecs[2, 0]
)
)
fh.write(
logging.info(
" Inter principal axis = ( {:>10.6f} , {:>10.6f} , {:>10.6f} )\n".format(
evecs[0, 1], evecs[1, 1], evecs[2, 1]
)
)
fh.write(
logging.info(
" Minor principal axis = ( {:>10.6f} , {:>10.6f} , {:>10.6f} )\n".format(
evecs[0, 2], evecs[1, 2], evecs[2, 2]
)
)
sizes = self.sizes_of_molecule()
fh.write(
logging.info(
" Characteristic lengths = ( {:>6.2f} , {:>6.2f} , {:>6.2f} )\n".format(
sizes[0], sizes[1], sizes[2]
)
)
fh.write(" Total mass = {:>8.2f} au\n".format(self.total_mass))
logging.info(" Total mass = {:>8.2f} au\n".format(self.total_mass))
chg_dip = self.charges_and_dipole()
fh.write(" Total charge = {:>8.4f} e\n".format(chg_dip[0]))
fh.write(
logging.info(" Total charge = {:>8.4f} e\n".format(chg_dip[0]))
logging.info(
" Dipole moment = ( {:>9.4f} , {:>9.4f} , {:>9.4f} ) Total = {:>9.4f} Debye\n\n".format(
chg_dip[1], chg_dip[2], chg_dip[3], chg_dip[4]
)
)
def minimum_distance(self, molec: "Molecule") -> float:
def minimum_distance(self, molec: 'Molecule') -> float:
"""
Return the minimum distance between two molecules

View File

@@ -1,21 +1,13 @@
from diceplayer.DPpack.Utils.PTable import *
from diceplayer.DPpack.Utils.Misc import *
from diceplayer.DPpack.Environment.Molecule import ANG2BOHR, BOHR2ANG, Molecule
from diceplayer.DPpack.Environment.Atom import Atom
from typing import IO, Final, Tuple, List, TextIO
from numpy import linalg
import numpy as np
from copy import deepcopy
import sys, math
import sys
import math
from copy import deepcopy
from typing import List, Tuple, TextIO
BOHR2ANG: Final[float] = 0.52917721092
ANG2BOHR: Final[float] = 1 / BOHR2ANG
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
class System:
@@ -46,7 +38,7 @@ class System:
self.molecule.append(m)
self.nmols.append(nmols)
def center_of_mass_distance(self, a: Molecule, b: Molecule) -> float:
def center_of_mass_distance(self, a: int, b: int) -> float:
"""
Calculates the distance between the center of mass of two molecules
@@ -73,7 +65,7 @@ class System:
reference_mol = self.molecule[r_index]
if len(projecting_mol.atom) != len(reference_mol.atom):
sys.exit(
raise RuntimeError(
"Error in RMSD fit procedure: molecules have different number of atoms"
)
dim = len(projecting_mol.atom)
@@ -102,7 +94,7 @@ class System:
try:
evals, evecs = linalg.eigh(rr)
except:
sys.exit("Error: diagonalization of RR matrix did not converge")
raise RuntimeError("Error: diagonalization of RR matrix did not converge")
a1 = evecs[:, 2].T
a2 = evecs[:, 1].T
@@ -180,7 +172,7 @@ class System:
criterium = "com"
if criterium != "com" and criterium != "min":
sys.exit("Error in value passed to function nearest_image")
raise RuntimeError("Error in value passed to function nearest_image")
min_dist = 1e20

View File

@@ -0,0 +1,26 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from abc import ABC, abstractmethod
class External(ABC):
__slots__ = [
'config'
]
@abstractmethod
def __init__(self, data: dict):
pass
@staticmethod
@abstractmethod
def set_config(data: dict) -> Dataclass:
pass
@abstractmethod
def start(self):
pass
@abstractmethod
def reset(self):
pass

View File

22
diceplayer/shared/external/dice.py vendored Normal file
View File

@@ -0,0 +1,22 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from diceplayer.shared.external.__external import External
from diceplayer.shared.config.dice_dto import DiceDTO
class Dice(External):
def __init__(self, data: dict):
self.config: DiceDTO = self.set_config(data)
@staticmethod
def set_config(data: dict) -> DiceDTO:
return DiceDTO.from_dict(data)
def configure(self):
pass
def start(self):
pass
def reset(self):
pass

23
diceplayer/shared/external/gaussian.py vendored Normal file
View File

@@ -0,0 +1,23 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from diceplayer.shared.config.gaussian_dto import GaussianDTO
from diceplayer.shared.external.__external import External
class Gaussian(External):
def __init__(self, data: dict):
self.config: GaussianDTO = self.set_config(data)
@staticmethod
def set_config(data: dict) -> GaussianDTO:
return GaussianDTO.from_dict(data)
def configure(self):
pass
def start(self):
pass
def reset(self):
pass

View File

View File

@@ -0,0 +1,6 @@
from typing import runtime_checkable, Protocol
@runtime_checkable
class Dataclass(Protocol):
__dataclass_fields__: dict

View File

@@ -0,0 +1,64 @@
import gzip
import os
import shutil
import sys
import time
from typing import Final
####################################### constants ######################################
BOHR2ANG: Final[float] = 0.52917721092
ANG2BOHR: Final[float] = 1 / BOHR2ANG
####################################### functions ######################################
def weekday_date_time():
return time.strftime("%A, %d %b %Y at %H:%M:%S")
def date_time():
return time.strftime("%d %b %Y at %H:%M:%S")
def compress_files_1mb(path):
working_dir = os.getcwd()
os.chdir(path)
files = filter(os.path.isfile, os.listdir(os.curdir))
for file in files:
if os.path.getsize(file) > 1024 * 1024: ## If bigger than 1MB
filegz = file + ".gz"
try:
with open(file, 'rb') as f_in:
with gzip.open(filegz, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
except:
sys.exit("Error: cannot compress file {}".format(file))
os.chdir(working_dir)
return
def make_step_dir(cycle):
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle)
path = sim_dir + os.sep + step_dir
if os.path.exists(path):
sys.exit("Error: a file or directory {} already exists".format(step_dir))
try:
os.makedirs(path)
except:
sys.exit("Error: cannot make directory {}".format(step_dir))
def make_qm_dir(cycle):
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle)
path = sim_dir + os.sep + step_dir + os.sep + "qm"
try:
os.makedirs(path)
except:
sys.exit("Error: cannot make directory {}".format(path))

0
tests/__init__.py Normal file
View File

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

View File

View File

@@ -0,0 +1,19 @@
from diceplayer.shared.environment.atom import Atom
import unittest
class TestAtom(unittest.TestCase):
def test_class_instantiation(self):
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.assertIsInstance(atom, Atom)

View File

@@ -0,0 +1,61 @@
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])