OpenMD 3.1
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
HydroIO.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 "hydrodynamics/HydroIO.hpp"
46
47#include <fstream>
48#include <iomanip>
49
50#include "utils/simError.h"
51
52using namespace std;
53
54namespace OpenMD {
55
56 HydroIO::~HydroIO() {}
57
58 void HydroIO::openWriter(std::ostream& os) {
59 std::string h = "OpenMD-Hydro";
60#if defined(NLOHMANN_JSON)
61 j_[h] = ordered_json::array();
62 writerOpen_ = true;
63#elif defined(RAPID_JSON)
64 osw_ = new OStreamWrapper(os);
65 w_.Reset(*osw_);
66 writerOpen_ = true;
67
68 w_.SetMaxDecimalPlaces(7);
69 w_.SetIndent(' ', 2);
70
71 w_.StartObject();
72 w_.Key(h.c_str());
73 w_.StartArray();
74#endif
75 }
76
77 void HydroIO::writeHydroProp(HydroProp* hp, RealType viscosity,
78 RealType temperature, std::ostream& os) {
79 if (!writerOpen_) openWriter(os);
80
81 std::string h = "OpenMD-Hydro";
82 std::string name = hp->getName();
83 Vector3d cor = hp->getCenterOfResistance();
84 Mat6x6d Xi = hp->getResistanceTensor();
85 Vector3d cod = hp->getCenterOfDiffusion(temperature);
86 Mat6x6d Xid = hp->getDiffusionTensorAtPos(cod, temperature);
87 Vector3d cop = hp->getCenterOfPitch();
88 Mat3x3d pitchAxes;
89 Vector3d pitches;
90 RealType pitchScalar;
91
92 hp->pitchAxes(pitchAxes, pitches, pitchScalar);
93
94#if defined(NLOHMANN_JSON)
95
96 ordered_json o;
97 o["name"] = name;
98 o["viscosity"] = viscosity;
99 o["centerOfResistance"] = {cor[0], cor[1], cor[2]};
100 o["resistanceTensor"] = json::array();
101
102 for (unsigned int i = 0; i < 6; i++) {
103 o["resistanceTensor"][i] = {Xi(i, 0), Xi(i, 1), Xi(i, 2),
104 Xi(i, 3), Xi(i, 4), Xi(i, 5)};
105 }
106
107 o["temperature"] = temperature;
108 o["centerOfDiffusion"] = {cod[0], cod[1], cod[2]};
109 o["diffusionTensor"] = json::array();
110
111 for (unsigned int i = 0; i < 6; i++) {
112 o["diffusionTensor"][i] = {Xid(i, 0), Xid(i, 1), Xid(i, 2),
113 Xid(i, 3), Xid(i, 4), Xid(i, 5)};
114 }
115
116 o["pitch"] = pitchScalar;
117 o["centerOfPitch"] = {cop[0], cop[1], cop[2]};
118 o["momentsOfPitch"] = {pitches[0], pitches[1], pitches[2]};
119
120 o["pitchAxes"] = json::array();
121 for (unsigned int i = 0; i < 3; i++) {
122 o["pitchAxes"][i] = {pitchAxes(i, 0), pitchAxes(i, 1), pitchAxes(i, 2)};
123 }
124
125 j_[h].push_back(o);
126
127#elif defined(RAPID_JSON)
128
129 w_.StartObject();
130 w_.Key("name");
131 w_.String(name.c_str());
132
133 w_.Key("viscosity");
134 w_.Double(viscosity);
135 w_.Key("centerOfResistance");
136 w_.StartArray();
137 w_.SetFormatOptions(kFormatSingleLineArray);
138
139 for (unsigned i = 0; i < 3; i++)
140 w_.Double(cor[i]);
141 w_.EndArray();
142 w_.SetFormatOptions(kFormatDefault);
143
144 w_.Key("resistanceTensor");
145 w_.StartArray();
146 for (unsigned i = 0; i < 6; i++) {
147 w_.StartArray();
148 w_.SetFormatOptions(kFormatSingleLineArray);
149
150 for (unsigned j = 0; j < 6; j++) {
151 w_.Double(Xi(i, j));
152 }
153 w_.EndArray();
154 w_.SetFormatOptions(kFormatDefault);
155 }
156 w_.EndArray();
157
158 w_.Key("temperature");
159 w_.Double(temperature);
160 w_.Key("centerOfDiffusion");
161 w_.StartArray();
162 w_.SetFormatOptions(kFormatSingleLineArray);
163
164 for (unsigned i = 0; i < 3; i++)
165 w_.Double(cod[i]);
166 w_.EndArray();
167 w_.SetFormatOptions(kFormatDefault);
168
169 w_.Key("diffusionTensor");
170 w_.StartArray();
171 for (unsigned i = 0; i < 6; i++) {
172 w_.StartArray();
173 w_.SetFormatOptions(kFormatSingleLineArray);
174
175 for (unsigned j = 0; j < 6; j++) {
176 w_.Double(Xid(i, j));
177 }
178 w_.EndArray();
179 w_.SetFormatOptions(kFormatDefault);
180 }
181 w_.EndArray();
182
183 w_.Key("pitch");
184 w_.Double(pitchScalar);
185
186 w_.Key("centerOfPitch");
187 w_.StartArray();
188 w_.SetFormatOptions(kFormatSingleLineArray);
189 for (unsigned i = 0; i < 3; i++)
190 w_.Double(cop[i]);
191 w_.EndArray();
192 w_.SetFormatOptions(kFormatDefault);
193
194 w_.Key("momentsOfPitch");
195 w_.StartArray();
196 w_.SetFormatOptions(kFormatSingleLineArray);
197 for (unsigned i = 0; i < 3; i++)
198 w_.Double(pitches[i]);
199 w_.EndArray();
200 w_.SetFormatOptions(kFormatDefault);
201
202 w_.Key("pitchAxes");
203 w_.StartArray();
204 for (unsigned i = 0; i < 3; i++) {
205 w_.StartArray();
206 w_.SetFormatOptions(kFormatSingleLineArray);
207 for (unsigned j = 0; j < 3; j++) {
208 w_.Double(pitchAxes(i, j));
209 }
210 w_.EndArray();
211 w_.SetFormatOptions(kFormatDefault);
212 }
213 w_.EndArray();
214
215 w_.EndObject();
216#endif
217 }
218
219 void HydroIO::closeWriter(std::ostream& os) {
220#if defined(NLOHMANN_JSON)
221 os << j_.dump(2) << std::endl;
222#elif defined(RAPID_JSON)
223 w_.EndArray();
224 w_.EndObject();
225 delete osw_;
226#endif
227 writerOpen_ = false;
228 }
229
230 map<string, HydroProp*> HydroIO::parseHydroFile(const string& f) {
231 map<string, HydroProp*> props;
232
233 ifstream ifs(f);
234
235 if (!ifs.good()) {
236 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
237 "HydroIO: Cannot open file: %s\n", f.c_str());
238 painCave.isFatal = 1;
239 simError();
240 }
241
242#if defined(NLOHMANN_JSON)
243 json ij = json::parse(ifs);
244
245 auto& entries = ij["OpenMD-Hydro"];
246
247 for (auto& entry : entries) {
248 HydroProp* hp = new HydroProp();
249 std::string name;
250 Vector3d cor;
251 Mat6x6d Xi;
252
253 name = entry["name"].get<std::string>();
254
255 for (unsigned int i = 0; i < 3; i++) {
256 cor[i] = entry["centerOfResistance"].get<vector<RealType>>()[i];
257 }
258
259 for (unsigned int i = 0; i < 6; i++) {
260 for (unsigned int j = 0; j < 6; j++) {
261 Xi(i, j) =
262 entry["resistanceTensor"].get<vector<vector<RealType>>>()[i][j];
263 }
264 }
265
266 hp->setName(name);
267 hp->setCenterOfResistance(cor);
268 hp->setResistanceTensor(Xi);
269 props.insert(map<string, HydroProp*>::value_type(name, hp));
270 }
271#elif defined(RAPID_JSON)
272 // Parse entire file into memory once, then reuse d_ for subsequent
273 // hydroProps.
274
275 if (ifs.peek() != EOF) {
276 rapidjson::IStreamWrapper isw(ifs);
277 d_.ParseStream(isw);
278 if (d_.HasParseError()) {
279 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
280 "HydroIO: JSON parse error in file %s\n"
281 "\tError: %zu : %s\n",
282 f.c_str(), d_.GetErrorOffset(),
283 rapidjson::GetParseError_En(d_.GetParseError()));
284 painCave.isFatal = 1;
285 simError();
286 }
287 if (!d_.IsObject()) {
288 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
289 "HydroIO: OpenMD-Hydro should be a single object.\n");
290 painCave.isFatal = 1;
291 simError();
292 }
293 // OpenMD-Hydro has a single object, but check that it's really
294 // OpenMD-Hydro
295 if (!d_.HasMember("OpenMD-Hydro")) {
296 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
297 "HydroIO: File %s does not have a OpenMD-Hydro object.\n",
298 f.c_str());
299 painCave.isFatal = 1;
300 simError();
301 }
302 }
303 const Value& entries = d_["OpenMD-Hydro"];
304 for (auto& entry : entries.GetArray()) {
305 HydroProp* hp = new HydroProp();
306 std::string name;
307 Vector3d cor;
308 Mat6x6d Xi;
309
310 name = entry["name"].GetString();
311
312 for (unsigned int i = 0; i < 3; i++) {
313 cor[i] = entry["centerOfResistance"][i].GetDouble();
314 }
315
316 for (unsigned int i = 0; i < 6; i++) {
317 for (unsigned int j = 0; j < 6; j++) {
318 Xi(i, j) = entry["resistanceTensor"][i][j].GetDouble();
319 }
320 }
321
322 hp->setName(name);
323 hp->setCenterOfResistance(cor);
324 hp->setResistanceTensor(Xi);
325 props.insert(map<string, HydroProp*>::value_type(name, hp));
326 }
327#endif
328 return props;
329 }
330
331 void HydroIO::interpretHydroProp(HydroProp* hp, RealType viscosity,
332 RealType temperature) {
333 Vector3d ror = hp->getCenterOfResistance();
334
335 Mat6x6d Xi;
336 Xi = hp->getResistanceTensor();
337 Mat3x3d Xirtt;
338 Mat3x3d Xirrt;
339 Mat3x3d Xirtr;
340 Mat3x3d Xirrr;
341
342 Xi.getSubMatrix(0, 0, Xirtt);
343 Xi.getSubMatrix(0, 3, Xirrt);
344 Xi.getSubMatrix(3, 0, Xirtr);
345 Xi.getSubMatrix(3, 3, Xirrr);
346
347 Mat6x6d Dr;
348 Dr = hp->getDiffusionTensor(temperature);
349
350 Mat3x3d Drtt;
351 Mat3x3d Drrt;
352 Mat3x3d Drtr;
353 Mat3x3d Drrr;
354
355 Dr.getSubMatrix(0, 0, Drtt);
356 Dr.getSubMatrix(0, 3, Drrt);
357 Dr.getSubMatrix(3, 0, Drtr);
358 Dr.getSubMatrix(3, 3, Drrr);
359
360 std::cout << "\n";
361 std::cout << "-----------------------------------------\n";
362 std::cout << "viscosity = " << viscosity << " Poise" << std::endl;
363 std::cout << "temperature = " << temperature << " K" << std::endl;
364 std::cout << "-----------------------------------------\n";
365 std::cout << "The centers are based on the elements generated by Hydro "
366 << std::endl;
367 std::cout << "which have been placed in an .xyz or .stl file." << std::endl;
368 std::cout << "They are not based on the geometry in the .omd file.\n"
369 << std::endl;
370 std::cout << "-----------------------------------------\n\n";
371 std::cout << "Center of resistance :" << std::endl;
372 std::cout << ror << "\n" << std::endl;
373 std::cout << "-----------------------------------------\n\n";
374 std::cout << "Resistance tensor at center of resistance\n" << std::endl;
375 std::cout << "translation [kcal.fs/(mol.A^2)]:" << std::endl;
376 std::cout << Xirtt << std::endl;
377 std::cout << "rotation-translation [kcal.fs/(mol.A.radian)]:" << std::endl;
378 std::cout << Xirtr.transpose() << std::endl;
379 std::cout << "translation-rotation [kcal.fs/(mol.A.radian)]:" << std::endl;
380 std::cout << Xirtr << std::endl;
381 std::cout << "rotation [kcal.fs/(mol.radian^2)]:" << std::endl;
382 std::cout << Xirrr << std::endl;
383 std::cout << "-----------------------------------------\n\n";
384 std::cout << "Diffusion tensor at center of resistance\n" << std::endl;
385 std::cout << "translation (A^2 / fs):" << std::endl;
386 std::cout << Drtt << std::endl;
387 std::cout << "rotation-translation (A.radian / fs):" << std::endl;
388 std::cout << Drrt << std::endl;
389 std::cout << "translation-rotation (A.radian / fs):" << std::endl;
390 std::cout << Drtr << std::endl;
391 std::cout << "rotation (radian^2 / fs):" << std::endl;
392 std::cout << Drrr << std::endl;
393 std::cout << "-----------------------------------------\n\n";
394
395 // calculate center of diffusion using the same arbitrary origin as above
396 // (from the generated geometry file .xyz)
397
398 Vector3d cod = hp->getCenterOfDiffusion(temperature);
399 Mat6x6d Xid = hp->getResistanceTensorAtPos(cod);
400
401 Mat3x3d Xidtt;
402 Mat3x3d Xidrt;
403 Mat3x3d Xidtr;
404 Mat3x3d Xidrr;
405
406 Xid.getSubMatrix(0, 0, Xidtt);
407 Xid.getSubMatrix(0, 3, Xidrt);
408 Xid.getSubMatrix(3, 0, Xidtr);
409 Xid.getSubMatrix(3, 3, Xidrr);
410
411 // calculate Diffusion Tensor at center of diffusion
412 Mat6x6d Dd = hp->getDiffusionTensorAtPos(cod, temperature);
413
414 Mat3x3d Ddtt;
415 Mat3x3d Ddtr;
416 Mat3x3d Ddrt;
417 Mat3x3d Ddrr;
418
419 Dd.getSubMatrix(0, 0, Ddtt);
420 Dd.getSubMatrix(0, 3, Ddrt);
421 Dd.getSubMatrix(3, 0, Ddtr);
422 Dd.getSubMatrix(3, 3, Ddrr);
423
424 std::cout << "Center of diffusion: " << std::endl;
425 std::cout << cod << "\n" << std::endl;
426 std::cout << "-----------------------------------------\n\n";
427 std::cout << "Diffusion tensor at center of diffusion \n " << std::endl;
428 std::cout << "translation (A^2 / fs) :" << std::endl;
429 std::cout << Ddtt << std::endl;
430 std::cout << "rotation-translation (A.radian / fs):" << std::endl;
431 std::cout << Ddtr.transpose() << std::endl;
432 std::cout << "translation-rotation (A.radian / fs):" << std::endl;
433 std::cout << Ddtr << std::endl;
434 std::cout << "rotation (radian^2 / fs):" << std::endl;
435 std::cout << Ddrr << std::endl;
436 std::cout << "-----------------------------------------\n\n";
437 std::cout << "Resistance tensor at center of diffusion \n " << std::endl;
438 std::cout << "translation [kcal.fs/(mol.A^2)]:" << std::endl;
439 std::cout << Xidtt << std::endl;
440 std::cout << "rotation-translation [kcal.fs/(mol.A.radian)]:" << std::endl;
441 std::cout << Xidrt << std::endl;
442 std::cout << "translation-rotation [kcal.fs/(mol.A.radian)]:" << std::endl;
443 std::cout << Xidtr << std::endl;
444 std::cout << "rotation [kcal.fs/(mol.radian^2)]:" << std::endl;
445 std::cout << Xidrr << std::endl;
446 std::cout << "-----------------------------------------\n\n";
447 }
448} // namespace OpenMD
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.