OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
ShapeAtomTypesSectionParser.cpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45#include "io/ShapeAtomTypesSectionParser.hpp"
46
47#include <memory>
48
49#include "brains/ForceField.hpp"
52#include "types/AtomType.hpp"
53#include "types/DirectionalAdapter.hpp"
55#include "utils/CaseConversion.hpp"
56#include "utils/StringUtils.hpp"
57#include "utils/simError.h"
58
59namespace OpenMD {
60
61 ShapeAtomTypesSectionParser::ShapeAtomTypesSectionParser(ForceFieldOptions&) {
62 setSectionName("ShapeAtomTypes");
63 }
64
65 void ShapeAtomTypesSectionParser::parseLine(ForceField& ff,
66 const std::string& line,
67 int lineNo) {
68 StringTokenizer tokenizer(line);
69
70 if (tokenizer.countTokens() >= 2) {
71 std::string shapeTypeName = tokenizer.nextToken();
72 std::string shapeFile = tokenizer.nextToken();
73
74 AtomType* atomType = ff.getAtomType(shapeTypeName);
75 if (atomType == NULL) {
76 atomType = new AtomType();
77 int ident = ff.getNAtomType() + 1;
78 atomType->setIdent(ident);
79 atomType->setName(shapeTypeName);
80 ff.addAtomType(shapeTypeName, atomType);
81 }
82
83 parseShapeFile(ff, shapeFile, atomType);
84
85 } else {
86 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
87 "ShapesAtomTypesSectionParser Error: "
88 "Not enough tokens at line %d\n",
89 lineNo);
90 painCave.severity = OPENMD_ERROR;
91 painCave.isFatal = 1;
92 simError();
93 }
94 }
95
96 void ShapeAtomTypesSectionParser::parseShapeFile(ForceField&,
97 std::string& shapeFileName,
98 AtomType* at) {
99 const int bufferSize = 65535;
100 char buffer[bufferSize];
101 std::string token;
102
103 Mat3x3d momInert;
104 RealSphericalHarmonic* rsh;
105 std::vector<RealSphericalHarmonic*> functionVector;
106 ifstrstream shapeStream;
107 std::string tempString;
108 std::string ffPath;
109 char* tempPath;
110
111 tempPath = getenv("FORCE_PARAM_PATH");
112
113 if (tempPath == NULL) {
114 // convert a macro from compiler to a string in c++
115 STR_DEFINE(ffPath, FRC_PATH);
116 } else {
117 ffPath = tempPath;
118 }
119
120 shapeStream.open(shapeFileName.c_str());
121
122 if (!shapeStream.is_open()) {
123 tempString = ffPath;
124 tempString += "/";
125 tempString += shapeFileName;
126 shapeFileName = tempString;
127
128 shapeStream.open(shapeFileName.c_str());
129
130 if (!shapeStream.is_open()) {
131 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
132 "Error opening the shape file:\n"
133 "\t%s\n"
134 "\tHave you tried setting the FORCE_PARAM_PATH environment "
135 "variable?\n",
136 shapeFileName.c_str());
137 painCave.severity = OPENMD_ERROR;
138 painCave.isFatal = 1;
139 simError();
140 }
141 }
142
143 ShapeAtomType* st = new ShapeAtomType();
144
145 // first parse the info. in the ShapeInfo section
146 findBegin(shapeStream, "ShapeInfo");
147 shapeStream.getline(buffer, bufferSize);
148
149 // loop over the interior of the ShapeInfo section
150 while (!shapeStream.eof()) {
151 // toss comment lines
152 if (buffer[0] != '!' && buffer[0] != '#') {
153 // end marks section completion
154 if (isEndLine(buffer)) break;
155 StringTokenizer tokenInfo(buffer);
156 // blank lines are ignored
157 if (tokenInfo.countTokens() != 0) {
158 if (tokenInfo.countTokens() < 5) {
159 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
160 "ShapesAtomTypesSectionParser Error: Not enough "
161 "information on a ShapeInfo line in file: %s\n",
162 shapeFileName.c_str());
163 painCave.severity = OPENMD_ERROR;
164 painCave.isFatal = 1;
165 simError();
166 } else {
167 tokenInfo.skipToken();
168 at->setMass(tokenInfo.nextTokenAsDouble());
169 DirectionalAdapter da = DirectionalAdapter(at);
170 Mat3x3d I;
171 I(0, 0) = tokenInfo.nextTokenAsDouble();
172 I(1, 1) = tokenInfo.nextTokenAsDouble();
173 I(2, 2) = tokenInfo.nextTokenAsDouble();
174 da.makeDirectional(I);
175 }
176 }
177 }
178 shapeStream.getline(buffer, bufferSize);
179 }
180
181 // now grab the contact functions
182 findBegin(shapeStream, "ContactFunctions");
183 functionVector.clear();
184
185 shapeStream.getline(buffer, bufferSize);
186 while (!shapeStream.eof()) {
187 // toss comment lines
188 if (buffer[0] != '!' && buffer[0] != '#') {
189 // end marks section completion
190 if (isEndLine(buffer)) break;
191 StringTokenizer tokenInfo1(buffer);
192 // blank lines are ignored
193 if (tokenInfo1.countTokens() != 0) {
194 if (tokenInfo1.countTokens() < 4) {
195 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
196 "ShapesAtomTypesSectionParser Error: Not enough "
197 "information on a ContactFunctions line in file: %s\n",
198 shapeFileName.c_str());
199 painCave.severity = OPENMD_ERROR;
200 painCave.isFatal = 1;
201 simError();
202 } else {
203 // read in a spherical harmonic function
204 rsh = new RealSphericalHarmonic();
205 rsh->setL(tokenInfo1.nextTokenAsInt());
206 rsh->setM(tokenInfo1.nextTokenAsInt());
207 token = tokenInfo1.nextToken();
208 toLower(token);
209 if (token == "sin")
210 rsh->makeSinFunction();
211 else
212 rsh->makeCosFunction();
213 rsh->setCoefficient(tokenInfo1.nextTokenAsDouble());
214
215 functionVector.push_back(rsh);
216 }
217 }
218 }
219 shapeStream.getline(buffer, bufferSize);
220 }
221
222 // pass contact functions to ShapeType
223 st->setContactFuncs(functionVector);
224
225 // now grab the range functions
226 findBegin(shapeStream, "RangeFunctions");
227 functionVector.clear();
228
229 shapeStream.getline(buffer, bufferSize);
230 while (!shapeStream.eof()) {
231 // toss comment lines
232 if (buffer[0] != '!' && buffer[0] != '#') {
233 // end marks section completion
234 if (isEndLine(buffer)) break;
235 StringTokenizer tokenInfo2(buffer);
236 // blank lines are ignored
237 if (tokenInfo2.countTokens() != 0) {
238 if (tokenInfo2.countTokens() < 4) {
239 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
240 "ShapesAtomTypesSectionParser Error: Not enough "
241 "information on a RangeFunctions line in file: %s\n",
242 shapeFileName.c_str());
243 painCave.severity = OPENMD_ERROR;
244 painCave.isFatal = 1;
245 simError();
246 } else {
247 // read in a spherical harmonic function
248 rsh = new RealSphericalHarmonic();
249 rsh->setL(tokenInfo2.nextTokenAsInt());
250 rsh->setM(tokenInfo2.nextTokenAsInt());
251 token = tokenInfo2.nextToken();
252 toLower(token);
253 if (token == "sin")
254 rsh->makeSinFunction();
255 else
256 rsh->makeCosFunction();
257 rsh->setCoefficient(tokenInfo2.nextTokenAsDouble());
258
259 functionVector.push_back(rsh);
260 }
261 }
262 }
263 shapeStream.getline(buffer, bufferSize);
264 }
265
266 // pass range functions to ShapeType
267 st->setRangeFuncs(functionVector);
268
269 // finally grab the strength functions
270 findBegin(shapeStream, "StrengthFunctions");
271 functionVector.clear();
272
273 shapeStream.getline(buffer, bufferSize);
274 while (!shapeStream.eof()) {
275 // toss comment lines
276 if (buffer[0] != '!' && buffer[0] != '#') {
277 // end marks section completion
278 if (isEndLine(buffer)) break;
279 StringTokenizer tokenInfo3(buffer);
280 // blank lines are ignored
281 if (tokenInfo3.countTokens() != 0) {
282 if (tokenInfo3.countTokens() < 4) {
283 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
284 "ShapesAtomTypesSectionParser Error: Not enough "
285 "information on a StrengthFunctions line in file: %s\n",
286 shapeFileName.c_str());
287 painCave.severity = OPENMD_ERROR;
288 painCave.isFatal = 1;
289 simError();
290 } else {
291 // read in a spherical harmonic function
292 rsh = new RealSphericalHarmonic();
293 rsh->setL(tokenInfo3.nextTokenAsInt());
294 rsh->setM(tokenInfo3.nextTokenAsInt());
295 token = tokenInfo3.nextToken();
296 toLower(token);
297 if (token == "sin")
298 rsh->makeSinFunction();
299 else
300 rsh->makeCosFunction();
301 rsh->setCoefficient(tokenInfo3.nextTokenAsDouble());
302
303 functionVector.push_back(rsh);
304 }
305 }
306 }
307 shapeStream.getline(buffer, bufferSize);
308 }
309
310 // pass strength functions to ShapeType
311 st->setStrengthFuncs(functionVector);
312 at->addProperty(
313 std::shared_ptr<GenericData>(new ShapeAtypeData("Shape", st)));
314 // delete shapeStream;
315 }
316} // namespace OpenMD
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
int findBegin(std::istream &theStream, const char *startText)
Finds the location of the string "begin <startText>" in an input stream.
int isEndLine(char *line)
discovers whether or not the line contains the "end" token