OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
omd2omd.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 <fstream>
46#include <iostream>
47#include <string>
48
50#include "brains/Register.hpp"
51#include "brains/SimCreator.hpp"
52#include "brains/SimInfo.hpp"
53#include "brains/Thermo.hpp"
54#include "io/DumpReader.hpp"
55#include "io/DumpWriter.hpp"
56#include "math/Quaternion.hpp"
57#include "omd2omdCmd.hpp"
58#include "types/FluctuatingChargeAdapter.hpp"
59#include "utils/Constants.hpp"
60#include "utils/simError.h"
61
62using namespace OpenMD;
63
64using namespace std;
65
66void createMdFile(const std::string& oldMdFileName,
67 const std::string& newMdFileName, std::vector<int> nMol);
68
69int main(int argc, char* argv[]) {
70 gengetopt_args_info args_info;
71 string dumpFileName;
72 string outFileName;
73
74 // parse the command line option
75 if (cmdline_parser(argc, argv, &args_info) != 0) { exit(1); }
76
77 // get the dumpfile name and meta-data file name
78 if (args_info.input_given) {
79 dumpFileName = args_info.input_arg;
80 } else {
81 strcpy(painCave.errMsg, "No input file name was specified.\n");
82 painCave.isFatal = 1;
83 simError();
84 }
85
86 if (args_info.output_given) {
87 outFileName = args_info.output_arg;
88 } else {
89 strcpy(painCave.errMsg, "No output file name was specified.\n");
90 painCave.isFatal = 1;
91 simError();
92 }
93
94 // convert the input angles to radians for computation
95 double phi = args_info.rotatePhi_arg * (Constants::PI / 180.0);
96 double theta = args_info.rotateTheta_arg * (Constants::PI / 180.0);
97 double psi = args_info.rotatePsi_arg * (Constants::PI / 180.0);
98
99 Mat3x3d rotMatrix = Mat3x3d(0.0);
100
101 rotMatrix.setupRotMat(phi, theta, psi);
102
103 Vector3i repeat = Vector3i(args_info.repeatX_arg, args_info.repeatY_arg,
104 args_info.repeatZ_arg);
105
106 Mat3x3d repeatD = Mat3x3d(0.0);
107 repeatD(0, 0) = repeat.x();
108 repeatD(1, 1) = repeat.y();
109 repeatD(2, 2) = repeat.z();
110
111 Vector3d translate =
112 Vector3d(args_info.translateX_arg, args_info.translateY_arg,
113 args_info.translateZ_arg);
114
115 // parse md file and set up the system
116
117 SimCreator oldCreator;
118 SimInfo* oldInfo = oldCreator.createSim(dumpFileName, false);
119 Globals* simParams = oldInfo->getSimParams();
120 std::vector<Component*> components = simParams->getComponents();
121 std::vector<int> nMol;
122 for (vector<Component*>::iterator i = components.begin();
123 i != components.end(); ++i) {
124 int nMolOld = (*i)->getNMol();
125 int nMolNew = nMolOld * repeat.x() * repeat.y() * repeat.z();
126 nMol.push_back(nMolNew);
127 }
128
129 createMdFile(dumpFileName, outFileName, nMol);
130
131 SimCreator newCreator;
132 SimInfo* newInfo = newCreator.createSim(outFileName, false);
133
134 DumpReader* dumpReader = new DumpReader(oldInfo, dumpFileName);
135 int nframes = dumpReader->getNFrames();
136
137 DumpWriter* writer = new DumpWriter(newInfo, outFileName);
138 if (writer == NULL) {
139 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
140 "error in creating DumpWriter");
141 painCave.isFatal = 1;
142 simError();
143 }
144
145 SimInfo::MoleculeIterator miter;
146 Molecule::IntegrableObjectIterator iiter;
147 Molecule::RigidBodyIterator rbIter;
148 Molecule* mol;
149 StuntDouble* sd;
150 StuntDouble* sdNew;
151 RigidBody* rb;
152 Mat3x3d oldHmat;
153 Mat3x3d rotHmat;
154 Mat3x3d newHmat;
155 Snapshot* oldSnap;
156 Snapshot* newSnap;
157 Vector3d oldPos;
158 Vector3d newPos;
159 Vector3d relPos;
160 Vector3d COM;
161 Vector3d molCOM;
162 Thermo thermo(oldInfo);
163 AtomType* atype;
164
165 for (int i = 0; i < nframes; i++) {
166 cerr << "frame = " << i << "\n";
167 dumpReader->readFrame(i);
168 oldSnap = oldInfo->getSnapshotManager()->getCurrentSnapshot();
169 newSnap = newInfo->getSnapshotManager()->getCurrentSnapshot();
170
171 newSnap->setID(oldSnap->getID());
172 newSnap->setTime(oldSnap->getTime());
173
174 oldHmat = oldSnap->getHmat();
175 rotHmat = rotMatrix * oldHmat;
176 newHmat = repeatD * rotHmat;
177 newSnap->setHmat(newHmat);
178
179 newSnap->setThermostat(oldSnap->getThermostat());
180 newSnap->setBarostat(oldSnap->getBarostat());
181
182 COM = thermo.getCom();
183
184 int newIndex = 0;
185 for (mol = oldInfo->beginMolecule(miter); mol != NULL;
186 mol = oldInfo->nextMolecule(miter)) {
187 if (args_info.repairMolecules_arg == 1) { molCOM = mol->getCom(); }
188
189 for (int ii = 0; ii < repeat.x(); ii++) {
190 for (int jj = 0; jj < repeat.y(); jj++) {
191 for (int kk = 0; kk < repeat.z(); kk++) {
192 Vector3d trans = Vector3d(ii, jj, kk);
193 for (sd = mol->beginIntegrableObject(iiter); sd != NULL;
194 sd = mol->nextIntegrableObject(iiter)) {
195 if (args_info.repairMolecules_arg == 1) {
196 relPos = sd->getPos() - molCOM;
197 oldPos = molCOM - COM + translate;
198 oldSnap->wrapVector(relPos);
199 oldSnap->wrapVector(oldPos);
200 oldPos += relPos;
201 } else {
202 oldPos = sd->getPos() - COM + translate;
203 oldSnap->wrapVector(oldPos);
204 }
205
206 newPos = rotMatrix * oldPos + trans * oldHmat;
207 sdNew = newInfo->getIOIndexToIntegrableObject(newIndex);
208 sdNew->setPos(newPos);
209 sdNew->setVel(rotMatrix * sd->getVel());
210
211 if (sd->isDirectional()) {
212 Mat3x3d bodyRotMat = sd->getA();
213 bodyRotMat = bodyRotMat * rotMatrix.inverse();
214 sdNew->setA(bodyRotMat);
215
216 sdNew->setJ(rotMatrix * sd->getJ());
217 }
218
219 if (sd->isAtom()) {
220 atype = static_cast<Atom*>(sd)->getAtomType();
222 if (fqa.isFluctuatingCharge()) {
223 RealType charge = sd->getFlucQPos();
224 sdNew->setFlucQPos(charge);
225 RealType cv = sd->getFlucQVel();
226 sdNew->setFlucQVel(cv);
227 }
228 }
229
230 newIndex++;
231 }
232 }
233 }
234 }
235 }
236
237 // update atoms of rigidbody
238 for (mol = newInfo->beginMolecule(miter); mol != NULL;
239 mol = newInfo->nextMolecule(miter)) {
240 // change the positions of atoms which belong to the rigidbodies
241 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
242 rb = mol->nextRigidBody(rbIter)) {
243 rb->updateAtoms();
244 rb->updateAtomVel();
245 }
246 }
247
248 writer->writeDump();
249 }
250 // deleting the writer will put the closing at the end of the dump file.
251 delete writer;
252 delete oldInfo;
253}
254
255void createMdFile(const std::string& oldMdFileName,
256 const std::string& newMdFileName, std::vector<int> nMol) {
257 ifstream oldMdFile;
258 ofstream newMdFile;
259 const int MAXLEN = 65535;
260 char buffer[MAXLEN];
261
262 // create new .omd file based on old .omd file
263
264 oldMdFile.open(oldMdFileName.c_str());
265 newMdFile.open(newMdFileName.c_str());
266
267 oldMdFile.getline(buffer, MAXLEN);
268
269 std::size_t i = 0;
270 while (!oldMdFile.eof()) {
271 // correct molecule number
272 if (strstr(buffer, "nMol") != NULL) {
273 if (i < nMol.size()) {
274 snprintf(buffer, MAXLEN, "\tnMol = %i;", nMol.at(i));
275 newMdFile << buffer << std::endl;
276 i++;
277 }
278 } else
279 newMdFile << buffer << std::endl;
280
281 oldMdFile.getline(buffer, MAXLEN);
282 }
283
284 oldMdFile.close();
285 newMdFile.close();
286
287 if (i != nMol.size()) {
288 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
289 "Couldn't replace the correct number of nMol\n"
290 "\tstatements in component blocks.");
291 painCave.isFatal = 1;
292 simError();
293 }
294}
AtomType is what OpenMD looks to for unchanging data about an atom.
Definition AtomType.hpp:66
Vector3d getCom()
Returns the current center of mass position of this molecule.
Definition Molecule.cpp:298
The only responsibility of SimCreator is to parse the meta-data file and create a SimInfo instance ba...
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:93
The Snapshot class is a repository storing dynamic data during a Simulation.
Definition Snapshot.hpp:147
SquareMatrix3< Real > inverse() const
Sets the value of this matrix to the inverse of itself.
"Don't move, or you're dead! Stand up! Captain, we've got them!"
RotMat3x3d getA()
Returns the current rotation matrix of this stuntDouble.
Vector3d getVel()
Returns the current velocity of this stuntDouble.
Vector3d getPos()
Returns the current position of this stuntDouble.
RealType getFlucQPos()
Returns the current fluctuating charge of this stuntDouble.
Vector3d getJ()
Returns the current angular momentum of this stuntDouble (body -fixed).
bool isAtom()
Tests if this stuntDouble is an atom.
bool isDirectional()
Tests if this stuntDouble is a directional one.
RealType getFlucQVel()
Returns the current charge velocity of this stuntDouble.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
The header file for the command line option parser generated by GNU Gengetopt version 2....
Where the command line options are stored.