OpenMD 3.2
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 following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48#include <fstream>
49#include <iostream>
50#include <string>
51
53#include "brains/Register.hpp"
54#include "brains/SimCreator.hpp"
55#include "brains/SimInfo.hpp"
56#include "brains/Thermo.hpp"
57#include "io/DumpReader.hpp"
58#include "io/DumpWriter.hpp"
59#include "math/Quaternion.hpp"
60#include "omd2omdCmd.hpp"
61#include "types/FluctuatingChargeAdapter.hpp"
62#include "utils/Constants.hpp"
63#include "utils/simError.h"
64
65using namespace OpenMD;
66
67using namespace std;
68
69void createMdFile(const std::string& oldMdFileName,
70 const std::string& newMdFileName, std::vector<int> nMol);
71
72int main(int argc, char* argv[]) {
73 gengetopt_args_info args_info;
74 string dumpFileName;
75 string outFileName;
76
77 // parse the command line option
78 if (cmdline_parser(argc, argv, &args_info) != 0) { exit(1); }
79
80 // get the dumpfile name and meta-data file name
81 if (args_info.input_given) {
82 dumpFileName = args_info.input_arg;
83 } else {
84 strcpy(painCave.errMsg, "No input file name was specified.\n");
85 painCave.isFatal = 1;
86 simError();
87 }
88
89 if (args_info.output_given) {
90 outFileName = args_info.output_arg;
91 } else {
92 strcpy(painCave.errMsg, "No output file name was specified.\n");
93 painCave.isFatal = 1;
94 simError();
95 }
96
97 // convert the input angles to radians for computation
98 double phi = args_info.rotatePhi_arg * (Constants::PI / 180.0);
99 double theta = args_info.rotateTheta_arg * (Constants::PI / 180.0);
100 double psi = args_info.rotatePsi_arg * (Constants::PI / 180.0);
101
102 Mat3x3d rotMatrix = Mat3x3d(0.0);
103
104 rotMatrix.setupRotMat(phi, theta, psi);
105
106 Vector3i repeat = Vector3i(args_info.repeatX_arg, args_info.repeatY_arg,
107 args_info.repeatZ_arg);
108
109 Mat3x3d repeatD = Mat3x3d(0.0);
110 repeatD(0, 0) = repeat.x();
111 repeatD(1, 1) = repeat.y();
112 repeatD(2, 2) = repeat.z();
113
114 Vector3d translate =
115 Vector3d(args_info.translateX_arg, args_info.translateY_arg,
116 args_info.translateZ_arg);
117
118 // parse md file and set up the system
119
120 SimCreator oldCreator;
121 SimInfo* oldInfo = oldCreator.createSim(dumpFileName, false);
122 Globals* simParams = oldInfo->getSimParams();
123 std::vector<Component*> components = simParams->getComponents();
124 std::vector<int> nMol;
125 for (vector<Component*>::iterator i = components.begin();
126 i != components.end(); ++i) {
127 int nMolOld = (*i)->getNMol();
128 int nMolNew = nMolOld * repeat.x() * repeat.y() * repeat.z();
129 nMol.push_back(nMolNew);
130 }
131
132 createMdFile(dumpFileName, outFileName, nMol);
133
134 SimCreator newCreator;
135 SimInfo* newInfo = newCreator.createSim(outFileName, false);
136
137 DumpReader* dumpReader = new DumpReader(oldInfo, dumpFileName);
138 int nframes = dumpReader->getNFrames();
139
140 DumpWriter* writer = new DumpWriter(newInfo, outFileName);
141 if (writer == NULL) {
142 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
143 "error in creating DumpWriter");
144 painCave.isFatal = 1;
145 simError();
146 }
147
148 SimInfo::MoleculeIterator miter;
149 Molecule::IntegrableObjectIterator iiter;
150 Molecule::RigidBodyIterator rbIter;
151 Molecule* mol;
152 StuntDouble* sd;
153 StuntDouble* sdNew;
154 RigidBody* rb;
155 Mat3x3d oldHmat;
156 Mat3x3d rotHmat;
157 Mat3x3d newHmat;
158 Snapshot* oldSnap;
159 Snapshot* newSnap;
160 Vector3d oldPos;
161 Vector3d newPos;
162 Vector3d relPos;
163 Vector3d COM;
164 Vector3d molCOM;
165 Thermo thermo(oldInfo);
166 AtomType* atype;
167
168 for (int i = 0; i < nframes; i++) {
169 cerr << "frame = " << i << "\n";
170 dumpReader->readFrame(i);
171 oldSnap = oldInfo->getSnapshotManager()->getCurrentSnapshot();
172 newSnap = newInfo->getSnapshotManager()->getCurrentSnapshot();
173
174 newSnap->setID(oldSnap->getID());
175 newSnap->setTime(oldSnap->getTime());
176
177 oldHmat = oldSnap->getHmat();
178 rotHmat = rotMatrix * oldHmat;
179 newHmat = repeatD * rotHmat;
180 newSnap->setHmat(newHmat);
181
182 newSnap->setThermostat(oldSnap->getThermostat());
183 newSnap->setBarostat(oldSnap->getBarostat());
184
185 // Do one loop to re-center and re-rewrap the old system
186
187 if (args_info.noCOM_flag) {
188 COM = V3Zero;
189 } else {
190 COM = thermo.getCom();
191 }
192
193 for (mol = oldInfo->beginMolecule(miter); mol != NULL;
194 mol = oldInfo->nextMolecule(miter)) {
195 if (args_info.repairMolecules_arg == 1) { molCOM = mol->getCom(); }
196
197 for (sd = mol->beginIntegrableObject(iiter); sd != NULL;
198 sd = mol->nextIntegrableObject(iiter)) {
199 if (args_info.repairMolecules_arg == 1) {
200 relPos = sd->getPos() - molCOM;
201 oldPos = molCOM - COM;
202
203 if (!args_info.noWrap_flag) {
204 oldSnap->wrapVector(relPos);
205 oldSnap->wrapVector(oldPos);
206 }
207
208 oldPos += relPos;
209
210 } else {
211 oldPos = sd->getPos() - COM;
212
213 if (!args_info.noWrap_flag) { oldSnap->wrapVector(oldPos); }
214 }
215 sd->setPos(oldPos);
216 }
217 }
218
219 // now a second pass through to translate and rotate into the new
220
221 int newIndex = 0;
222 for (mol = oldInfo->beginMolecule(miter); mol != NULL;
223 mol = oldInfo->nextMolecule(miter)) {
224 for (int ii = 0; ii < repeat.x(); ii++) {
225 for (int jj = 0; jj < repeat.y(); jj++) {
226 for (int kk = 0; kk < repeat.z(); kk++) {
227 Vector3d trans = Vector3d(ii, jj, kk);
228
229 for (sd = mol->beginIntegrableObject(iiter); sd != NULL;
230 sd = mol->nextIntegrableObject(iiter)) {
231 oldPos = sd->getPos();
232
233 newPos = rotMatrix * oldPos + trans * oldHmat + translate;
234
235 sdNew = newInfo->getIOIndexToIntegrableObject(newIndex);
236 sdNew->setPos(newPos);
237 sdNew->setVel(rotMatrix * sd->getVel());
238
239 if (sd->isDirectional()) {
240 Mat3x3d bodyRotMat = sd->getA();
241 bodyRotMat = bodyRotMat * rotMatrix.inverse();
242 sdNew->setA(bodyRotMat);
243 sdNew->setJ(rotMatrix * sd->getJ());
244 }
245
246 if (sd->isAtom()) {
247 atype = static_cast<Atom*>(sd)->getAtomType();
249 if (fqa.isFluctuatingCharge()) {
250 RealType charge = sd->getFlucQPos();
251 sdNew->setFlucQPos(charge);
252 RealType cv = sd->getFlucQVel();
253 sdNew->setFlucQVel(cv);
254 }
255 }
256
257 newIndex++;
258 }
259 }
260 }
261 }
262 }
263
264 // update atoms of rigidbody
265 for (mol = newInfo->beginMolecule(miter); mol != NULL;
266 mol = newInfo->nextMolecule(miter)) {
267 // change the positions of atoms which belong to the rigidbodies
268 for (rb = mol->beginRigidBody(rbIter); rb != NULL;
269 rb = mol->nextRigidBody(rbIter)) {
270 rb->updateAtoms();
271 rb->updateAtomVel();
272 }
273 }
274
275 writer->writeDump();
276 }
277 // deleting the writer will put the closing at the end of the dump file.
278 delete writer;
279 delete oldInfo;
280}
281
282void createMdFile(const std::string& oldMdFileName,
283 const std::string& newMdFileName, std::vector<int> nMol) {
284 ifstream oldMdFile;
285 ofstream newMdFile;
286 const int MAXLEN = 65535;
287 char buffer[MAXLEN];
288
289 // create new .omd file based on old .omd file
290
291 oldMdFile.open(oldMdFileName.c_str());
292 newMdFile.open(newMdFileName.c_str());
293
294 oldMdFile.getline(buffer, MAXLEN);
295
296 std::size_t i = 0;
297 while (!oldMdFile.eof()) {
298 // correct molecule number
299 if (strstr(buffer, "nMol") != NULL) {
300 if (i < nMol.size()) {
301 snprintf(buffer, MAXLEN, "\tnMol = %i;", nMol.at(i));
302 newMdFile << buffer << std::endl;
303 i++;
304 }
305 } else
306 newMdFile << buffer << std::endl;
307
308 oldMdFile.getline(buffer, MAXLEN);
309 }
310
311 oldMdFile.close();
312 newMdFile.close();
313
314 if (i != nMol.size()) {
315 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
316 "Couldn't replace the correct number of nMol\n"
317 "\tstatements in component blocks.");
318 painCave.isFatal = 1;
319 simError();
320 }
321}
AtomType is what OpenMD looks to for unchanging data about an atom.
Definition AtomType.hpp:69
int getNFrames()
Returns the number of frames in the dump file.
Vector3d getCom()
Returns the current center of mass position of this molecule.
Definition Molecule.cpp:315
void updateAtoms()
update the positions of atoms belong to this rigidbody
The only responsibility of SimCreator is to parse the meta-data file and create a SimInfo instance ba...
SimInfo * createSim(const std::string &mdFileName, bool loadInitCoords=true)
Setup Simulation.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:96
Molecule * beginMolecule(MoleculeIterator &i)
Returns the first molecule in this SimInfo and intialize the iterator.
Definition SimInfo.cpp:243
Molecule * nextMolecule(MoleculeIterator &i)
Returns the next avaliable Molecule based on the iterator.
Definition SimInfo.cpp:248
SnapshotManager * getSnapshotManager()
Returns the snapshot manager.
Definition SimInfo.hpp:251
StuntDouble * getIOIndexToIntegrableObject(int index)
return an integral objects by its global index.
Definition SimInfo.cpp:1031
The Snapshot class is a repository storing dynamic data during a Simulation.
Definition Snapshot.hpp:166
Mat3x3d getHmat()
Returns the H-Matrix.
Definition Snapshot.cpp:217
void setHmat(const Mat3x3d &m)
Sets the H-Matrix.
Definition Snapshot.cpp:220
void setID(int id)
Sets the id of this Snapshot.
Definition Snapshot.cpp:198
void wrapVector(Vector3d &v)
Wrapping the vector according to periodic boundary condition.
Definition Snapshot.cpp:340
int getID()
Returns the id of this Snapshot.
Definition Snapshot.cpp:195
Snapshot * getCurrentSnapshot()
Returns the pointer of current snapshot.
SquareMatrix3< Real > inverse() const
Sets the value of this matrix to the inverse of itself.
void setupRotMat(const Vector3< Real > &eulerAngles)
Sets this matrix to a rotation matrix by three euler angles @ param euler.
"Don't move, or you're dead! Stand up! Captain, we've got them!"
void setFlucQVel(RealType cvel)
Sets the current charge velocity of this stuntDouble.
RotMat3x3d getA()
Returns the current rotation matrix of this stuntDouble.
Vector3d getVel()
Returns the current velocity of this stuntDouble.
virtual void setA(const RotMat3x3d &a)
Sets the current rotation matrix of this stuntDouble.
void setFlucQPos(RealType charge)
Sets the current fluctuating charge of this stuntDouble.
Vector3d getPos()
Returns the current position of this stuntDouble.
RealType getFlucQPos()
Returns the current fluctuating charge of this stuntDouble.
void setPos(const Vector3d &pos)
Sets the current position of this stuntDouble.
void setVel(const Vector3d &vel)
Sets the current velocity 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.
void setJ(const Vector3d &angMom)
Sets the current angular momentum of this stuntDouble (body-fixed).
RealType getFlucQVel()
Returns the current charge velocity of this stuntDouble.
Real & z()
Returns reference of the third element of Vector3.
Definition Vector3.hpp:123
Real & x()
Returns reference of the first element of Vector3.
Definition Vector3.hpp:99
Real & y()
Returns reference of the second element of Vector3.
Definition Vector3.hpp:111
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.
double translateY_arg
translate all y coordinates by some amount (default='0.0').
int repeatY_arg
The number of images to repeat in the y direction (default='0').
unsigned int output_given
Whether output was given.
double translateZ_arg
translate all z coordinates by some amount (default='0.0').
int noCOM_flag
do not use Center of Mass as origin of the box (default=off).
int repeatX_arg
The number of images to repeat in the x direction (default='0').
double rotateTheta_arg
rotate all coordinates Euler angle Theta (default='0.0').
int repairMolecules_arg
rewrap molecules around the molecular center of mass (default='1').
char * output_arg
output file name.
char * input_arg
input dump file.
int repeatZ_arg
The number of images to repeat in the z direction (default='0').
int noWrap_flag
do not rewrap coordinates into the box (default=off).
double rotatePhi_arg
rotate all coordinates Euler angle Phi (default='0.0').
unsigned int input_given
Whether input was given.
double rotatePsi_arg
rotate all coordinates Euler angle Psi (default='0.0').
double translateX_arg
translate all x coordinates by some amount (default='0.0').