OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
Hydro.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
52#include "HydroCmd.hpp"
53#include "brains/Register.hpp"
54#include "brains/SimCreator.hpp"
55#include "brains/SimInfo.hpp"
56#include "hydrodynamics/AnalyticalModel.hpp"
57#include "hydrodynamics/AtomicBeadModel.hpp"
58#include "hydrodynamics/BoundaryElementModel.hpp"
59#include "hydrodynamics/CompositeShape.hpp"
60#include "hydrodynamics/HydroIO.hpp"
61#include "hydrodynamics/HydrodynamicsModel.hpp"
62#include "hydrodynamics/HydrodynamicsModelCreator.hpp"
64#include "hydrodynamics/Mesh.hpp"
65#include "hydrodynamics/RoughShell.hpp"
66#include "hydrodynamics/ShapeBuilder.hpp"
67#include "hydrodynamics/Sphere.hpp"
68#include "io/MSMSFormat.hpp"
69#include "io/XYZFormat.hpp"
70#include "stl_reader.h"
72#include "utils/MemoryUtils.hpp"
74#include "utils/StringUtils.hpp"
75#include "utils/Trim.hpp"
76#include "utils/simError.h"
77
78using namespace OpenMD;
79
80void registerHydrodynamicsModels();
81void writeHydroProps(std::ostream& os);
82
83int main(int argc, char* argv[]) {
84 registerHydrodynamicsModels();
85
86 gengetopt_args_info args_info;
87 // parse the command line option
88 if (cmdline_parser(argc, argv, &args_info) != 0) { exit(1); }
89
90 std::string inFileName;
91 std::string modelName;
92 std::string modelSpecified;
93 std::string modelRequired;
94
95 bool hasInput = false;
96 bool hasModel = false;
97
98 Shape* shape;
99
100 // Check to make sure the model has been given
101 if (args_info.model_given) {
102 switch (args_info.model_arg) {
103 case model_arg_RoughShell:
104 modelSpecified = "RoughShell";
105 break;
106 case model_arg_BoundaryElement:
107 modelSpecified = "BoundaryElementModel";
108 break;
109 case model_arg_AtomicBead:
110 default:
111 modelSpecified = "AtomicBeadModel";
112 break;
113 }
114 hasModel = true;
115 }
116
117 // figure out what kind of input file we have
118
119 if (args_info.input_given) {
120 inFileName = args_info.input_arg;
121 modelRequired = modelSpecified;
122 hasInput = true;
123 } else if (args_info.stl_given) {
124 inFileName = args_info.stl_arg;
125 modelRequired = "BoundaryElementModel";
126 hasInput = true;
127 } else if (args_info.msms_given) {
128 inFileName = args_info.msms_arg;
129 modelRequired = "BoundaryElementModel";
130 hasInput = true;
131 } else if (args_info.xyz_given) {
132 inFileName = args_info.xyz_arg;
133 modelRequired = "AtomicBeadModel";
134 hasInput = true;
135 }
136
137 if (!hasInput) {
138 strcpy(painCave.errMsg, "No input file name was specified.\n");
139 painCave.isFatal = 1;
140 simError();
141 }
142
143 if (hasModel) {
144 if (modelSpecified.compare(modelRequired) != 0) {
145 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
146 "Specified model (%s) does not match model required for input "
147 "type (%s).\n",
148 modelSpecified.c_str(), modelRequired.c_str());
149 painCave.isFatal = 1;
150 simError();
151 } else {
152 modelName = modelSpecified;
153 }
154 } else {
155 modelName = modelRequired;
156 hasModel = true;
157 }
158
159 std::string prefix;
160 if (args_info.output_given) {
161 prefix = args_info.output_arg;
162 } else {
163 prefix = getPrefix(inFileName);
164 }
165
166 std::string outputFilename = prefix + ".hydro";
167
168 RealType temperature = args_info.temperature_arg;
169 RealType viscosity = args_info.viscosity_arg;
170 RealType beadSize = args_info.beadSize_arg;
171
172 // read the files and create the shapes:
173
174 std::map<std::string, Shape*> uniqueShapes;
175
176 if (args_info.stl_given) {
177 try {
178 stl_reader::StlMesh<RealType, unsigned int> mesh(inFileName.c_str());
179 for (size_t isolid = 0; isolid < mesh.num_solids(); ++isolid) {
180 shape = new Mesh();
181 std::cout << "solid " << isolid << std::endl;
182 for (size_t itri = mesh.solid_tris_begin(isolid);
183 itri < mesh.solid_tris_end(isolid); ++itri) {
184 const RealType* c0 = mesh.tri_corner_coords(itri, 0);
185 const RealType* c1 = mesh.tri_corner_coords(itri, 1);
186 const RealType* c2 = mesh.tri_corner_coords(itri, 2);
187 Vector3d vert0(c0[0], c0[1], c0[2]);
188 Vector3d vert1(c1[0], c1[1], c1[2]);
189 Vector3d vert2(c2[0], c2[1], c2[2]);
190 dynamic_cast<Mesh*>(shape)->add(vert0, vert1, vert2);
191 }
192 std::string solidName;
193 if (mesh.num_solids() > 1) {
194 solidName = prefix + "_" + std::to_string(isolid);
195 } else {
196 solidName = prefix;
197 }
198
199 shape->setName(solidName);
200 uniqueShapes.insert(
201 std::map<std::string, Shape*>::value_type(solidName, shape));
202 }
203 } catch (std::exception& e) { std::cout << e.what() << std::endl; }
204
205 } else if (args_info.msms_given) {
206 MSMSFormat* msms = new MSMSFormat(inFileName.c_str());
207 shape = msms->ReadShape();
208 shape->setName(prefix);
209 uniqueShapes.insert(
210 std::map<std::string, Shape*>::value_type(prefix, shape));
211 } else if (args_info.xyz_given) {
212 ifstream in(inFileName);
213 if (!in) {
214 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
215 "Could not open XYZ file\n");
216 painCave.isFatal = 1;
217 simError();
218 }
219
220 XYZFormat* xyz = new XYZFormat();
221 xyz->ReadMolecule(in);
222
223 shape = new CompositeShape();
224 shape->setName(xyz->title_);
225
226 Shape* currShape = NULL;
227
228 size_t natoms = xyz->mol_.size();
229 for (size_t iatom = 0; iatom < natoms; ++iatom) {
230 Vector3d pos = xyz->mol_[iatom]->pos;
231 int anum = xyz->mol_[iatom]->atomicNum;
232 std::string atype = xyz->mol_[iatom]->type;
233 currShape = new Sphere(pos, etab.GetVdwRad(anum));
234 currShape->setName(atype);
235 if (currShape != NULL) {
236 dynamic_cast<CompositeShape*>(shape)->addShape(currShape);
237 }
238 }
239 uniqueShapes.insert(
240 std::map<std::string, Shape*>::value_type(xyz->title_, shape));
241 } else {
242 // parse md file and set up the system
243 SimCreator creator;
244 SimInfo* info = creator.createSim(inFileName, true);
245
246 SimInfo::MoleculeIterator mi;
247 Molecule* mol;
248 Molecule::IntegrableObjectIterator ii;
249 StuntDouble* sd;
250
251 Globals* simParams = info->getSimParams();
252
253 if (simParams->haveViscosity()) {
254 viscosity = simParams->getViscosity();
255 } else {
256 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
257 "viscosity must be set\n");
258 painCave.isFatal = 1;
259 simError();
260 }
261
262 if (simParams->haveTargetTemp()) {
263 temperature = simParams->getTargetTemp();
264 } else {
265 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
266 "target temperature must be set\n");
267 painCave.isFatal = 1;
268 simError();
269 }
270
271 for (mol = info->beginMolecule(mi); mol != NULL;
272 mol = info->nextMolecule(mi)) {
273 for (sd = mol->beginIntegrableObject(ii); sd != NULL;
274 sd = mol->nextIntegrableObject(ii)) {
275 if (uniqueShapes.find(sd->getType()) == uniqueShapes.end()) {
276 sd->setPos(V3Zero);
277 if (sd->isRigidBody()) {
279 RigidBody* rb = static_cast<RigidBody*>(sd);
280 rb->updateAtoms();
281 }
282
283 Shape* tmp = ShapeBuilder::createShape(sd);
284 uniqueShapes.insert(
285 std::map<std::string, Shape*>::value_type(sd->getType(), tmp));
286 }
287 }
288 }
289 delete info;
290 }
291
292 HydrodynamicsModel* model =
294 modelName);
295
296 if (model == NULL) {
297 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
298 "Could not create HydrodynamicsModel\n");
299 painCave.isFatal = 1;
300 simError();
301 } else {
302 model->init();
303
304 if (modelName.compare("RoughShell") == 0) {
305 dynamic_cast<RoughShell*>(model)->setSigma(beadSize);
306 }
307
308 std::ofstream outputHydro;
309 outputHydro.open(outputFilename.c_str());
310 HydroIO* hio = new HydroIO();
311 hio->openWriter(outputHydro);
312
313 std::map<std::string, Shape*>::iterator si;
314 for (si = uniqueShapes.begin(); si != uniqueShapes.end(); ++si) {
315 shape = si->second;
316 model->setShape(shape);
317
318 // write out the elements making up the shape:
319 std::ofstream ofs;
320 std::stringstream elementFile;
321 elementFile << prefix << "_" << shape->getName();
322 if (modelName.compare("BoundaryElementModel") == 0) {
323 elementFile << ".stl";
324 } else {
325 elementFile << ".xyz";
326 }
327 ofs.open(elementFile.str().c_str());
328 model->writeElements(ofs);
329 ofs.close();
330
331 // if elements option is turned on, skip the calculation
332 if (!args_info.elements_flag) {
333 HydroProp* hp = model->calcHydroProps(viscosity);
334 hio->writeHydroProp(hp, viscosity, temperature, outputHydro);
335 hio->interpretHydroProp(hp, viscosity, temperature);
336 }
337 }
338
339 hio->closeWriter(outputHydro);
340 outputHydro.close();
341
342 delete model;
343 }
344}
345
346void registerHydrodynamicsModels() {
348 new HydrodynamicsModelBuilder<RoughShell>("RoughShell"));
350 new HydrodynamicsModelBuilder<AtomicBeadModel>("AtomicBeadModel"));
352 new HydrodynamicsModelBuilder<AnalyticalModel>("AnalyticalModel"));
355 "BoundaryElementModel"));
356}
This basic Periodic Table class was originally taken from the data.h file in OpenBabel.
The header file for the command line option parser generated by GNU Gengetopt version 2....
Combine composite pattern and visitor pattern.
Container for information about the hydrodynamic behavior of objects interacting with surroundings.
Definition HydroProp.hpp:77
bool registerHydrodynamicsModel(HydrodynamicsModelCreator *creator)
Registers a creator with a type identifier.
HydrodynamicsModel * createHydrodynamicsModel(const std::string &id)
Looks up the type identifier in the internal map.
static HydrodynamicsModelFactory * getInstance()
Returns an instance of HydrodynamicsModel factory.
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
"Don't move, or you're dead! Stand up! Captain, we've got them!"
virtual void setA(const RotMat3x3d &a)
Sets the current rotation matrix of this stuntDouble.
virtual std::string getType()=0
Returns the name of this stuntDouble.
void setPos(const Vector3d &pos)
Sets the current position of this stuntDouble.
bool isRigidBody()
Tests if this stuntDouble is a rigid body.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)
Where the command line options are stored.
double viscosity_arg
viscosity (in poise) (default='0.01').
Definition HydroCmd.hpp:67
unsigned int output_given
Whether output was given.
enum enum_model model_arg
hydrodynamics model.
Definition HydroCmd.hpp:59
unsigned int msms_given
Whether msms was given.
Definition HydroCmd.hpp:79
unsigned int xyz_given
Whether xyz was given.
Definition HydroCmd.hpp:77
double beadSize_arg
bead size (diameter) for RoughShell model (in angstroms) (default='0.2').
Definition HydroCmd.hpp:62
char * output_arg
output file name.
char * input_arg
input dump file.
double temperature_arg
temperature (in Kelvin (default='300').
Definition HydroCmd.hpp:70
unsigned int stl_given
Whether stl was given.
Definition HydroCmd.hpp:78
char * xyz_arg
xyz file for AtomicBead model.
Definition HydroCmd.hpp:47
int elements_flag
output the hydrodynamic elements (beads or triangles) only, hydrodynamics calculation will not be per...
Definition HydroCmd.hpp:65
unsigned int input_given
Whether input was given.
char * stl_arg
stl file for BoundaryElement model.
Definition HydroCmd.hpp:50
unsigned int model_given
Whether model was given.
Definition HydroCmd.hpp:81
char * msms_arg
filename root for MSMS .vert and .face files.
Definition HydroCmd.hpp:53