OpenMD 3.0
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["pitches"] = {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 w_.Key("centerOfPitch");
186 w_.StartArray();
187 w_.SetFormatOptions(kFormatSingleLineArray);
188
189 for (unsigned i = 0; i < 3; i++)
190 w_.Double(cop[i]);
191 w_.EndArray();
192 w_.SetFormatOptions(kFormatDefault);
193
194 w_.Key("pitchAxes");
195 w_.StartArray();
196 for (unsigned i = 0; i < 3; i++) {
197 w_.StartArray();
198 w_.SetFormatOptions(kFormatSingleLineArray);
199 for (unsigned j = 0; j < 3; j++) {
200 w_.Double(pitchAxes(i, j));
201 }
202 w_.EndArray();
203 w_.SetFormatOptions(kFormatDefault);
204 }
205 w_.EndArray();
206
207 w_.EndObject();
208#endif
209 }
210
211 void HydroIO::closeWriter(std::ostream& os) {
212#if defined(NLOHMANN_JSON)
213 os << j_.dump(2) << std::endl;
214#elif defined(RAPID_JSON)
215 w_.EndArray();
216 w_.EndObject();
217 delete osw_;
218#endif
219 writerOpen_ = false;
220 }
221
222 map<string, HydroProp*> HydroIO::parseHydroFile(const string& f) {
223 map<string, HydroProp*> props;
224
225 ifstream ifs(f);
226
227 if (!ifs.good()) {
228 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
229 "HydroIO: Cannot open file: %s\n", f.c_str());
230 painCave.isFatal = 1;
231 simError();
232 }
233
234#if defined(NLOHMANN_JSON)
235 json ij = json::parse(ifs);
236
237 auto& entries = ij["OpenMD-Hydro"];
238
239 for (auto& entry : entries) {
240 HydroProp* hp = new HydroProp();
241 std::string name;
242 Vector3d cor;
243 Mat6x6d Xi;
244
245 name = entry["name"].get<std::string>();
246
247 for (unsigned int i = 0; i < 3; i++) {
248 cor[i] = entry["centerOfResistance"].get<vector<RealType>>()[i];
249 }
250
251 for (unsigned int i = 0; i < 6; i++) {
252 for (unsigned int j = 0; j < 6; j++) {
253 Xi(i, j) =
254 entry["resistanceTensor"].get<vector<vector<RealType>>>()[i][j];
255 }
256 }
257
258 hp->setName(name);
259 hp->setCenterOfResistance(cor);
260 hp->setResistanceTensor(Xi);
261 props.insert(map<string, HydroProp*>::value_type(name, hp));
262 }
263#elif defined(RAPID_JSON)
264 // Parse entire file into memory once, then reuse d_ for subsequent
265 // hydroProps.
266
267 if (ifs.peek() != EOF) {
268 rapidjson::IStreamWrapper isw(ifs);
269 d_.ParseStream(isw);
270 if (d_.HasParseError()) {
271 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
272 "HydroIO: JSON parse error in file %s\n"
273 "\tError: %zu : %s\n",
274 f.c_str(), d_.GetErrorOffset(),
275 rapidjson::GetParseError_En(d_.GetParseError()));
276 painCave.isFatal = 1;
277 simError();
278 }
279 if (!d_.IsObject()) {
280 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
281 "HydroIO: OpenMD-Hydro should be a single object.\n");
282 painCave.isFatal = 1;
283 simError();
284 }
285 // OpenMD-Hydro has a single object, but check that it's really
286 // OpenMD-Hydro
287 if (!d_.HasMember("OpenMD-Hydro")) {
288 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
289 "HydroIO: File %s does not have a OpenMD-Hydro object.\n",
290 f.c_str());
291 painCave.isFatal = 1;
292 simError();
293 }
294 }
295 const Value& entries = d_["OpenMD-Hydro"];
296 for (auto& entry : entries.GetArray()) {
297 HydroProp* hp = new HydroProp();
298 std::string name;
299 Vector3d cor;
300 Mat6x6d Xi;
301
302 name = entry["name"].GetString();
303
304 for (unsigned int i = 0; i < 3; i++) {
305 cor[i] = entry["centerOfResistance"][i].GetDouble();
306 }
307
308 for (unsigned int i = 0; i < 6; i++) {
309 for (unsigned int j = 0; j < 6; j++) {
310 Xi(i, j) = entry["resistanceTensor"][i][j].GetDouble();
311 }
312 }
313
314 hp->setName(name);
315 hp->setCenterOfResistance(cor);
316 hp->setResistanceTensor(Xi);
317 props.insert(map<string, HydroProp*>::value_type(name, hp));
318 }
319#endif
320 return props;
321 }
322
323 void HydroIO::interpretHydroProp(HydroProp* hp, RealType viscosity,
324 RealType temperature) {
325 Vector3d ror = hp->getCenterOfResistance();
326
327 Mat6x6d Xi;
328 Xi = hp->getResistanceTensor();
329 Mat3x3d Xirtt;
330 Mat3x3d Xirrt;
331 Mat3x3d Xirtr;
332 Mat3x3d Xirrr;
333
334 Xi.getSubMatrix(0, 0, Xirtt);
335 Xi.getSubMatrix(0, 3, Xirrt);
336 Xi.getSubMatrix(3, 0, Xirtr);
337 Xi.getSubMatrix(3, 3, Xirrr);
338
339 Mat6x6d Dr;
340 Dr = hp->getDiffusionTensor(temperature);
341
342 Mat3x3d Drtt;
343 Mat3x3d Drrt;
344 Mat3x3d Drtr;
345 Mat3x3d Drrr;
346
347 Dr.getSubMatrix(0, 0, Drtt);
348 Dr.getSubMatrix(0, 3, Drrt);
349 Dr.getSubMatrix(3, 0, Drtr);
350 Dr.getSubMatrix(3, 3, Drrr);
351
352 std::cout << "\n";
353 std::cout << "-----------------------------------------\n";
354 std::cout << "viscosity = " << viscosity << " Poise" << std::endl;
355 std::cout << "temperature = " << temperature << " K" << std::endl;
356 std::cout << "-----------------------------------------\n";
357 std::cout << "The centers are based on the elements generated by Hydro "
358 << std::endl;
359 std::cout << "which have been placed in an .xyz or .stl file." << std::endl;
360 std::cout << "They are not based on the geometry in the .omd file.\n"
361 << std::endl;
362 std::cout << "-----------------------------------------\n\n";
363 std::cout << "Center of resistance :" << std::endl;
364 std::cout << ror << "\n" << std::endl;
365 std::cout << "-----------------------------------------\n\n";
366 std::cout << "Resistance tensor at center of resistance\n" << std::endl;
367 std::cout << "translation [kcal.fs/(mol.A^2)]:" << std::endl;
368 std::cout << Xirtt << std::endl;
369 std::cout << "rotation-translation [kcal.fs/(mol.A.radian)]:" << std::endl;
370 std::cout << Xirtr.transpose() << std::endl;
371 std::cout << "translation-rotation [kcal.fs/(mol.A.radian)]:" << std::endl;
372 std::cout << Xirtr << std::endl;
373 std::cout << "rotation [kcal.fs/(mol.radian^2)]:" << std::endl;
374 std::cout << Xirrr << std::endl;
375 std::cout << "-----------------------------------------\n\n";
376 std::cout << "Diffusion tensor at center of resistance\n" << std::endl;
377 std::cout << "translation (A^2 / fs):" << std::endl;
378 std::cout << Drtt << std::endl;
379 std::cout << "rotation-translation (A.radian / fs):" << std::endl;
380 std::cout << Drrt << std::endl;
381 std::cout << "translation-rotation (A.radian / fs):" << std::endl;
382 std::cout << Drtr << std::endl;
383 std::cout << "rotation (radian^2 / fs):" << std::endl;
384 std::cout << Drrr << std::endl;
385 std::cout << "-----------------------------------------\n\n";
386
387 // calculate center of diffusion using the same arbitrary origin as above
388 // (from the generated geometry file .xyz)
389
390 Vector3d cod = hp->getCenterOfDiffusion(temperature);
391 Mat6x6d Xid = hp->getResistanceTensorAtPos(cod);
392
393 Mat3x3d Xidtt;
394 Mat3x3d Xidrt;
395 Mat3x3d Xidtr;
396 Mat3x3d Xidrr;
397
398 Xid.getSubMatrix(0, 0, Xidtt);
399 Xid.getSubMatrix(0, 3, Xidrt);
400 Xid.getSubMatrix(3, 0, Xidtr);
401 Xid.getSubMatrix(3, 3, Xidrr);
402
403 // calculate Diffusion Tensor at center of diffusion
404 Mat6x6d Dd = hp->getDiffusionTensorAtPos(cod, temperature);
405
406 Mat3x3d Ddtt;
407 Mat3x3d Ddtr;
408 Mat3x3d Ddrt;
409 Mat3x3d Ddrr;
410
411 Dd.getSubMatrix(0, 0, Ddtt);
412 Dd.getSubMatrix(0, 3, Ddrt);
413 Dd.getSubMatrix(3, 0, Ddtr);
414 Dd.getSubMatrix(3, 3, Ddrr);
415
416 std::cout << "Center of diffusion: " << std::endl;
417 std::cout << cod << "\n" << std::endl;
418 std::cout << "-----------------------------------------\n\n";
419 std::cout << "Diffusion tensor at center of diffusion \n " << std::endl;
420 std::cout << "translation (A^2 / fs) :" << std::endl;
421 std::cout << Ddtt << std::endl;
422 std::cout << "rotation-translation (A.radian / fs):" << std::endl;
423 std::cout << Ddtr.transpose() << std::endl;
424 std::cout << "translation-rotation (A.radian / fs):" << std::endl;
425 std::cout << Ddtr << std::endl;
426 std::cout << "rotation (radian^2 / fs):" << std::endl;
427 std::cout << Ddrr << std::endl;
428 std::cout << "-----------------------------------------\n\n";
429 std::cout << "Resistance tensor at center of diffusion \n " << std::endl;
430 std::cout << "translation [kcal.fs/(mol.A^2)]:" << std::endl;
431 std::cout << Xidtt << std::endl;
432 std::cout << "rotation-translation [kcal.fs/(mol.A.radian)]:" << std::endl;
433 std::cout << Xidrt << std::endl;
434 std::cout << "translation-rotation [kcal.fs/(mol.A.radian)]:" << std::endl;
435 std::cout << Xidtr << std::endl;
436 std::cout << "rotation [kcal.fs/(mol.radian^2)]:" << std::endl;
437 std::cout << Xidrr << std::endl;
438 std::cout << "-----------------------------------------\n\n";
439 }
440} // namespace OpenMD
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.