KIDS  ver-0.0.1
KIDS : Kernel Integrated Dynamics Simulator
Loading...
Searching...
No Matches
Model_Interf_MNDO.cpp
Go to the documentation of this file.
2
5#include "kids/chem.h"
6#include "kids/hash_fnv1a.h"
7#include "kids/linalg.h"
8#include "kids/macro_utils.h"
9#include "kids/vars_list.h"
10
11inline int removeFile(const std::string& filename) { return remove(filename.c_str()); }
12
13inline void clearFile(const std::string& filename) { std::ofstream clear(filename, std::ios::trunc); }
14
15inline void closeOFS(std::ofstream& ofs) {
16 if (ofs.is_open()) ofs.close();
17}
18
19inline bool isFileExists(const std::string& name) { return std::ifstream{name.c_str()}.good(); }
20
21namespace PROJECT_NS {
22
23const std::string Model_Interf_MNDO::getName() { return "Model_Interf_MNDO"; }
24
26
27void Model_Interf_MNDO::setInputParam_impl(std::shared_ptr<Param>& PM) {
29
30 // parse mndo input
31 exec_file = PM->get_string("exec_file", LOC(), "mndo");
32 directory = PM->get_string("directory", LOC());
33 classical_bath = PM->get_bool("classical_bath", LOC(), false);
34
35 std::string mndoinp = PM->get_string("mndoinp", LOC(), "null");
36 natom = parse_mndo(mndoinp);
37
38 assert(Dimension::N == 3 * natom);
39 assert(Dimension::F <= ncigrd);
40 assert(Dimension::F <= nciref);
41 assert(directory != "");
42}
43
44void Model_Interf_MNDO::setInputDataSet_impl(std::shared_ptr<DataSet>& DS) {
45 x = DS->def(DATA::integrator::x);
46 p = DS->def(DATA::integrator::p);
47
48 x0 = DS->def(DATA::model::x0);
49 p0 = DS->def(DATA::model::p0);
50 w = DS->def(DATA::model::w);
53
54 // model field
55 atoms = DS->def(DATA::model::atoms);
56 mass = DS->def(DATA::model::mass);
57 vpes = DS->def(DATA::model::vpes);
58 grad = DS->def(DATA::model::grad);
59 hess = DS->def(DATA::model::hess);
60 Tmod = DS->def(DATA::model::Tmod);
61 f_r = DS->def(DATA::model::f_r);
62 f_p = DS->def(DATA::model::f_p);
63 f_rp = DS->def(DATA::model::f_rp);
64 V = DS->def(DATA::model::V);
65 dV = DS->def(DATA::model::dV);
66 E = DS->def(DATA::model::rep::E);
67 T = DS->def(DATA::model::rep::T);
68 dE = DS->def(DATA::model::rep::dE);
69 nac = DS->def(DATA::model::rep::nac);
71 succ_ptr = DS->def(DATA::iter::succ);
73 frez_ptr = DS->def(DATA::iter::frez);
75
76 for (int i = 0, ik = 0; i < Dimension::F; ++i) {
77 for (int k = 0; k < Dimension::F; ++k, ++ik) T[ik] = (i == k) ? 1.0e0 : 0.0e0;
78 }
79
80 // read z index
81 for (int i = 0, idx = 0, idxR = 0; i < natom; ++i) {
82 atoms[i] = stoi(mndo_data[idx++]);
83 for (int j = 0; j < 3; ++j, ++idxR) {
84 mass[idxR] = ELEMENTS_MASS[atoms[i]] / phys::au_2_amu; // convert amu to au
85 x0[idxR] = stod(mndo_data[idx++]) / phys::au_2_ang; // convert angstrom into au
86 idx++; // skip fixflag
87 }
88 }
89
90 // read temperature
91 double temperature = _param->get_double("temperature", LOC(), phys::temperature_d, 1.0f);
92 beta = 1.0f / (phys::au::k * temperature); // don't ignore k_Boltzman
93
94 // read task
95 init_nuclinp = _param->get_string("init_nuclinp", LOC(), "#hess");
96
97 if (init_nuclinp == "#normalmode") {
99 exit(0);
100 }
101 if (init_nuclinp == "#scan") {
102 calc_scan();
103 exit(0);
104 }
105 if (init_nuclinp == "#samp") {
106 calc_samp();
107 exit(0);
108 }
109
110 // read hessian from hessian calculation (jop=2 kprint=1)
111 if (init_nuclinp == "#hess") {
112 std::string hess_log = _param->get_string("hess_log", LOC(), "hess.out");
113 if (!isFileExists(hess_log))
114 throw std::runtime_error(utils::concat("hess_log file [", hess_log, "] is missed!"));
115
116 parse_hessian(hess_log);
117
118 // from hessian & temperature to prepare initial sampling
119 for (int j = 0; j < Dimension::N; ++j) {
120 if (j < 6 || w[j] < 1.0e-10) { // cutoff low frequency
121 x_sigma[j] = 0.0f;
122 p_sigma[j] = 0.0f;
123 } else { // NOTE: it's for normal-mode!
124 double Qoverbeta = 0.5f * w[j] / std::tanh(0.5f * beta * w[j]);
125 if (classical_bath) Qoverbeta = 1.0e0 / beta;
126
127 x_sigma[j] = std::sqrt(Qoverbeta / (w[j] * w[j]));
128 p_sigma[j] = std::sqrt(Qoverbeta);
129 }
130 }
131 }
132 if (init_nuclinp == "#hess2") {
133 std::string hess_mol = _param->get_string("hess_mol", LOC(), "hess_molden.dat");
134 if (!isFileExists(hess_mol))
135 throw std::runtime_error(utils::concat("hess_mol file [", hess_mol, "] is missed!"));
136
137 parse_hessian2(hess_mol);
138 }
139}
140
156 if (init_nuclinp == "#hess" || init_nuclinp == "#hess2") { // assuming .hess is given
157 // sampling normal-mode
160 for (int i = 0; i < 6; ++i) x[i] = 0.0f, p[i] = 0.0f;
161 for (int i = 0; i < Dimension::N; ++i) {
162 x[i] *= x_sigma[i];
163 p[i] *= p_sigma[i];
164 }
165 // transfrom normal-mode to cartesian coordinates
166 ARRAY_MATMUL(x, Tmod, x, Dimension::N, Dimension::N, 1); // .eval()!
167 ARRAY_MATMUL(p, Tmod, p, Dimension::N, Dimension::N, 1); // .eval()!
168 for (int i = 0; i < Dimension::N; ++i) {
169 x[i] = x[i] / std::sqrt(mass[i]) + x0[i];
170 p[i] = p[i] * std::sqrt(mass[i]) + p0[i];
171 }
172 } else if (init_nuclinp == "#fix") { // for initial md
173 for (int i = 0; i < Dimension::N; ++i) x[i] = x0[i], p[i] = 0.0f;
174 } else { // init_nuclinp as dataset from which we read x and p
175 std::string open_file = init_nuclinp;
176 if (!isFileExists(init_nuclinp)) open_file = utils::concat(init_nuclinp, stat.icalc, ".ds");
177
178 std::string stmp, eachline;
179 std::ifstream ifs(open_file);
180 while (getline(ifs, eachline)) {
181 if (eachline.find("init.x") != eachline.npos) {
182 getline(ifs, eachline);
183 for (int i = 0; i < Dimension::N; ++i) ifs >> x[i];
184 }
185 if (eachline.find("init.p") != eachline.npos) {
186 getline(ifs, eachline);
187 for (int i = 0; i < Dimension::N; ++i) ifs >> p[i];
188 }
189 }
190
191 // ARRAY_SHOW(x, 1, Dimension::N);
192 // ARRAY_SHOW(p, 1, Dimension::N);
193 }
194
195 _dataset->def_real("init.x", x, Dimension::N);
196 _dataset->def_real("init.p", p, Dimension::N);
197
198 std::string hdlr_str = _param->get_string("handler", LOC());
199
200 refer = false;
201 task_control = (hdlr_str == "sampling") ? "samp" : "nad";
202 removeFile(utils::concat(directory, "/imomap.dat"));
203 executeKernel_impl(stat);
204 refer = true;
205 task_control = "nad";
206 return stat;
207}
208
210 if (frez_ptr[0]) return stat_in;
211
212 // convert atomic unit
213 for (int i = 0; i < Dimension::N; ++i) x[i] *= phys::au_2_ang;
214 // ARRAY_CLEAR(E, Dimension::F); // keep the old values
215 // ARRAY_CLEAR(dE, Dimension::NFF); // keep the old values
216
217 // prepare a mndo input file
218 std::string inpfile = utils::concat(".mndoinp.", stat_in.icalc);
219 std::string outfile = utils::concat(".mndoout.", stat_in.icalc);
220
221 std::string control_copy = task_control;
222 if (last_attempt_ptr[0] && fail_type_ptr[0] == 1) {
223 control_copy = "nad-hard";
224 removeFile(utils::concat(directory, "/imomap.dat"));
225 std::string rm_exe = utils::concat("rm ", directory, "/imomap.dat");
226 system(rm_exe.c_str());
227 std::cout << "last try mndo\n";
228 }
229 new_task(utils::concat(directory, "/", inpfile), control_copy);
230
231 std::string cmd_exe = utils::concat("cd ", directory, " && ", exec_file, " < ", inpfile, " > ", outfile);
232 int stat = system(cmd_exe.c_str());
233
234 parse_standard(utils::concat(directory, "/", outfile), stat_in); // parse in MNDO's units
235
236 track_nac_sign(); // @note track_nac_sign is important
237 for (int i = 0, idx = 0; i < Dimension::N; ++i) {
238 for (int j = 0; j < Dimension::F; ++j) {
239 for (int k = 0; k < Dimension::F; ++k, ++idx) {
240 if (j == k) continue;
241 dE[idx] = nac[idx] * (E[k] - E[j]);
242 }
243 }
244 }
245
246 // std::cout << "1\n";
247 // ARRAY_SHOW(x, 1, Dimension::N);
248 // ARRAY_SHOW(E, 1, Dimension::F);
249 // ARRAY_SHOW(dE, Dimension::N, Dimension::FF);
250
251 // convert units
252 for (int i = 0; i < Dimension::N; ++i) x[i] /= phys::au_2_ang;
253 for (int i = 0; i < Dimension::F; ++i) E[i] /= phys::au_2_kcal_1mea;
254 for (int i = 0; i < Dimension::NFF; ++i)
256
257 // std::cout << "2\n";
258 // ARRAY_SHOW(x, 1, Dimension::N);
259 // ARRAY_SHOW(E, 1, Dimension::F);
260 // ARRAY_SHOW(dE, Dimension::N, Dimension::FF);
261 // ARRAY_SHOW(nac, Dimension::N, Dimension::FF);
262
263 // @TODO
264 // if (!ARRAY_ISFINITE(R, Dimension::N) || !ARRAY_ISFINITE(E, F) || !ARRAY_ISFINITE(dE, NFF)) {
265 // std::cout << "Problem for calling forcefield";
266 // stat = -1;
267 // }
268 return stat_in;
269}
270
276int Model_Interf_MNDO::parse_mndo(const std::string& mndoinp) {
277 enum Stage { KEYWORD, COMMENT, DATA, ADDITION };
278 Stage istage = KEYWORD;
279
280 std::stringstream mndo_keyword_sstr;
281 std::stringstream mndo_comment_sstr;
282 std::stringstream mndo_addition_sstr;
283
284 int count_atom = 0;
285 std::ifstream ifs(mndoinp);
286 std::string eachline;
287 while (getline(ifs, eachline)) {
288 eachline.erase(eachline.find_last_not_of(" ") + 1); // remove last blank
289 switch (istage) {
290 case KEYWORD: {
291 mndo_keyword_sstr << eachline << std::endl;
292 std::string data, key, val;
293 std::istringstream input(eachline);
294 while (input >> data) {
295 if (data == "+") continue;
296 std::istringstream pair(data); // "key=val" pattern
297 getline(pair, key, '=');
298 getline(pair, val, '=');
299 std::for_each(key.begin(), key.end(), [](char& c) { c = ::tolower(c); });
300
301 if (key == "ncigrd") ncigrd = std::stoi(val);
302 if (key == "nciref") nciref = std::stoi(val);
303 if (key == "iroot") iroot = std::stoi(val);
304
305 keyword.push_back({key, val});
306 }
307 if (eachline.back() != '+') istage = COMMENT;
308 break;
309 }
310 case COMMENT: {
311 mndo_comment_sstr << eachline << std::endl;
312 getline(ifs, eachline);
313 mndo_comment_sstr << eachline << std::endl;
314 istage = DATA;
315 break;
316 }
317 case DATA: {
318 int ndata = 0;
319 std::string data, databuf[16];
320 std::istringstream input(eachline);
321 while (input >> data) databuf[ndata++] = data;
322 if (std::stoi(databuf[0]) != 0) {
323 count_atom++;
324 for (int i = 0; i < ndata; ++i) mndo_data.push_back(databuf[i]);
325 } else {
326 istage = ADDITION;
327 mndo_addition_sstr << eachline << std::endl;
328 }
329 break;
330 }
331 case ADDITION: {
332 mndo_addition_sstr << eachline << std::endl;
333 break;
334 }
335 }
336 }
337 ifs.close();
338 mndo_keyword = mndo_keyword_sstr.str();
339 mndo_comment = mndo_comment_sstr.str();
340 mndo_addition = mndo_addition_sstr.str();
341 assert(count_atom > 0);
342 int data_size = mndo_data.size();
343 if (7 * count_atom == data_size) std::cout << "read from cartesian format";
344 if (10 * count_atom == data_size) throw std::runtime_error("cannot read from zmat format");
345 return count_atom;
346}
347
348
352std::string Model_Interf_MNDO::new_keyword(const MNDOKW_map& newkeyword) {
353 std::stringstream sstr;
354 int i = 0;
355 const int ntermperline = 8;
356 for (auto iter = keyword.begin(); iter != keyword.end(); ++iter, ++i) {
357 MNDOKW& kw = *iter;
358 if (i != 0 && i % ntermperline == 0) sstr << "+" << std::endl;
359 if (newkeyword.find(kw.key) != newkeyword.end()) {
360 sstr << kw.key << "=" << newkeyword.at(kw.key) << " ";
361 } else {
362 sstr << kw.key << "=" << kw.val << " ";
363 }
364 }
365 sstr << std::endl;
366 return sstr.str();
367}
368
369
373int Model_Interf_MNDO::new_task(const std::string& file, const std::string& task_flag) {
374 std::string revised_keyword, revised_addition;
375 if (task_flag == "sp") { // single point calculation
376 revised_keyword = new_keyword({{"jop", "-1"}, {"icross", "0"}});
377 } else if (task_flag == "samp") { // single point calculation
378 revised_keyword = new_keyword(
379 {{"jop", "-1"}, {"icross", "7"}, {"mprint", "1"}, {"iuvcd", "2"}, {"imomap", "0"}, {"mapthr", "90"}});
380 } else if (task_flag == "force") { // force calculation
381 revised_keyword = new_keyword({{"jop", "-2"}, {"icross", "1"}});
382 // revised_addition = ...; // additional lines
383 } else if (task_flag == "nad") { // non-adiabatic coupling calculation
384 revised_keyword =
385 new_keyword({{"jop", "-2"}, {"icross", "7"}, {"mprint", "1"}, {"imomap", "3"}, {"mapthr", "97"}});
386 // revised_addition = ...; // additional lines
387 } else if (task_flag == "nad-hard") { // non-adiabatic coupling calculation (hard case)
388 revised_keyword = new_keyword(
389 {{"jop", "-2"}, {"icross", "7"}, {"mprint", "1"}, {"imomap", "3"}, {"mapthr", "75"}, {"kitscf", "5000"}});
390 // revised_addition = ...; // additional lines
391 } else if (task_flag == "hess") { // hessian calculation
392 revised_keyword = new_keyword({{"jop", "2"}, {"icross", "0"}, {"kprint", "1"}});
393 } else { // default
394 revised_keyword = mndo_keyword;
395 }
396
397 revised_addition = mndo_addition;
398 const int fixflag = 0;
399 std::ofstream ofs(file);
400 ofs << revised_keyword;
401 ofs << mndo_comment;
402 for (int i = 0, idx = 0; i < natom; ++i) {
403 ofs << FMT(4) << atoms[i] // Atom index
404 << FMT(8) << x[idx++] << FMT(4) << fixflag // Xk, flag_Xk
405 << FMT(8) << x[idx++] << FMT(4) << fixflag // Yk, flag_Yk
406 << FMT(8) << x[idx++] << FMT(4) << fixflag // Zk, flag_Zk
407 << std::endl;
408 }
409 ofs << revised_addition;
410 ofs.close();
411 return 0;
412}
413
421 if (refer) {
422 for (int i = 0; i < Dimension::F; ++i) {
423 for (int j = 0; j < Dimension::F; ++j) { // check if NAC(:,i,j) should flip its sign
424 if (i == j) continue;
425
426 const double norm_eps = 10e-14;
427 double norm_old = 0.0f;
428 double norm_new = 0.0f;
429 double cosangle = 0.0f;
430 int IJ = i * Dimension::F + j;
431 for (int k = 0, idx = IJ; k < Dimension::N; ++k, idx += Dimension::FF) {
432 norm_old += nac_prev[idx] * nac_prev[idx];
433 norm_new += nac[idx] * nac[idx];
434 cosangle += nac_prev[idx] * nac[idx];
435 }
436 norm_old = sqrt(norm_old);
437 norm_new = sqrt(norm_new);
438 if (norm_old < norm_eps || norm_new < norm_eps) {
439 cosangle = 1.0f;
440 } else {
441 cosangle = cosangle / (norm_old * norm_new);
442 }
443
444 if (norm_new > 10e12 || norm_old > 10e12) {
445 for (int k = 0; k < Dimension::N; ++k) {
446 nac[k * Dimension::FF + i * Dimension::F + j] =
447 copysign(nac[k * Dimension::FF + i * Dimension::F + j],
448 nac_prev[k * Dimension::FF + i * Dimension::F + j]);
449 }
450 } else if (cosangle < 0) { // in this case we flip the sign of NAC(:,i,j)
451 for (int k = 0; k < Dimension::N; ++k) { nac[k * Dimension::FF + i * Dimension::F + j] *= -1; }
452 }
453 }
454 }
455 }
456 for (int i = 0; i < Dimension::NFF; ++i) nac_prev[i] = nac[i]; // save a copy
457 return 0;
458}
459
460
468Status& Model_Interf_MNDO::parse_standard(const std::string& log, Status& stat_in) {
469 int stat = -1;
470 int istate_force = 0, istate_force_meet = 0;
471 int istate, jstate;
472
473 std::ifstream ifs(log);
474 std::string stmp, eachline;
475 std::string ERROR_MSG = "";
476 while (getline(ifs, eachline, '\n')) {
477 if (eachline.find("ERROR") != eachline.npos || eachline.find("UNABLE") != eachline.npos) {
478 ERROR_MSG += eachline;
479 }
480
484 if (eachline.find("Properties of transitions 1 -> #") != eachline.npos) {
485 for (int i = 0; i < 2; ++i) getline(ifs, eachline); // blankline + headline
486 for (int i = 1; i < nciref; ++i) {
487 ifs >> stmp >> stmp >> stmp >> stmp >> stmp >> stmp >> f_r[i] >> f_p[i] >> f_rp[i] >> stmp;
488 }
489 stat = 0;
490 }
494 else if (eachline.find("SUMMARY OF MULTIPLE CI CALCULATIONS") != eachline.npos) {
495 for (int i = 0; i < 4; ++i) getline(ifs, eachline);
496 for (int i = 0; i < Dimension::F; ++i) {
497 ifs >> stmp >> stmp >> E[i] >> stmp >> stmp;
498 }
499 stat = 0;
500 }
504 else if (eachline.find("CI CALCULATION FOR STATE:") != eachline.npos) {
505 std::istringstream sstr(eachline);
506 sstr >> stmp >> stmp >> stmp >> stmp >> istate_force;
507 istate_force--;
508 }
509 //
510 else if (eachline.find("GRADIENTS (KCAL/(MOL*ANGSTROM))") != eachline.npos &&
511 istate_force_meet == istate_force) {
512 istate_force_meet++;
513 for (int i = 0; i < 8; ++i) ifs >> stmp;
514 for (int i = 0, idx = 0; i < natom; ++i) {
515 ifs >> stmp >> stmp >> stmp >> stmp >> stmp // skips
516 >> dE[(idx++) * Dimension::FF + istate_force * Dimension::Fadd1] // grad(Xk,i,i)
517 >> dE[(idx++) * Dimension::FF + istate_force * Dimension::Fadd1] // grad(Yk,i,i)
518 >> dE[(idx++) * Dimension::FF + istate_force * Dimension::Fadd1]; // grad(Zk,i,i)
519 }
520 }
525 else if (eachline.find("CI CALCULATION FOR INTERSTATE "
526 "COUPLING OF STATES:") != eachline.npos) {
527 std::istringstream sstr(eachline);
528 sstr >> stmp >> stmp >> stmp >> stmp >> stmp >> stmp >> stmp >> istate >> jstate;
529 istate--, jstate--;
530 if (istate < Dimension::F && jstate < Dimension::F && istate != jstate) { // skip additional NAC
531 int IJ = istate * Dimension::F + jstate;
532 int JI = jstate * Dimension::F + istate;
533 while (getline(ifs, eachline)) {
534 if (eachline.find("GRADIENTS (KCAL/(MOL*ANGSTROM))") != eachline.npos) {
535 for (int i = 0; i < 8; ++i) ifs >> stmp;
536 for (int i = 0, idx = 0; i < natom; ++i) {
537 ifs >> stmp >> stmp >> stmp >> stmp >> stmp // skips
538 >> nac[(idx++) * Dimension::FF + IJ] // nac(Xk,i,i)
539 >> nac[(idx++) * Dimension::FF + IJ] // nac(Yk,i,i)
540 >> nac[(idx++) * Dimension::FF + IJ]; // nac(Zk,i,i)
541 }
542 for (int idx = 0; idx < Dimension::N; ++idx) { // copy to the other half-side nacv
543 nac[idx * Dimension::FF + JI] = -nac[idx * Dimension::FF + IJ];
544 }
545 break;
546 }
547 // if (eachline.find("COMPLETE EXPRESSION.") != eachline.npos) { // let `MPRINT=1`
548 // for (int i = 0, idx = 0; i < natom; ++i) { ///< found nacv in 1/angstrom
549 // ifs >> stmp // skips
550 // >> nac[(idx++) * Dimension::FF + IJ] // nac(Xk, i, j)
551 // >> nac[(idx++) * Dimension::FF + IJ] // nac(Yk, i, j)
552 // nac[(idx++) * Dimension::FF + IJ] // nac(Zk, i, j)
553 // }
554 // for (int idx = 0; idx < Dimension::N; ++idx) { // copy to the other half-side nacv
555 // nac[idx * Dimension::FF + JI] = -nac[idx * Dimension::FF + IJ];
556 // }
557 // break;
558 // }
559 }
560 }
561 stat = 2;
562 }
563 }
564 ifs.close();
565 if (stat != 2) {
566 succ_ptr[0] = false;
567 fail_type_ptr[0] = 1;
568 std::cout << "fail in calling MNDO! " << ERROR_MSG << "\n";
569
570 int* istep_ptr = _dataset->def_int("iter.istep");
571 std::string cmd_exe = utils::concat("cp ", directory, "/.mndoinp.", stat_in.icalc, " ", directory,
572 "/.mndoinp.", stat_in.icalc, ".err.", istep_ptr[0]);
573 system(cmd_exe.c_str());
574 cmd_exe = utils::concat("cp ", directory, "/.mndoout.", stat_in.icalc, " ", directory, "/.mndoout.",
575 stat_in.icalc, ".err.", istep_ptr[0]);
576 system(cmd_exe.c_str());
577 } else {
578 succ_ptr[0] = true;
579 if (last_attempt_ptr[0] && fail_type_ptr[0] == 1) {
580 std::cout << "survive in last try mndo\n";
581 } else if (last_attempt_ptr[0] && fail_type_ptr[0] == 2) {
582 std::cout << "mndo pass during last try conservation\n";
583 }
584 if (fail_type_ptr[0] == 1) fail_type_ptr[0] = 0;
585 }
586 return stat_in;
587}
588
593int Model_Interf_MNDO::parse_hessian(const std::string& log) {
594 std::ifstream ifs(log);
595
596 // initialization of arrays
600
601 std::string stmp, eachline;
602 int v1 = Dimension::N / 10, v2 = Dimension::N % 10, eqstat = 0, itmp;
603 double dtmp = 0.0f;
604 while (getline(ifs, eachline)) {
605 if (eachline.find("GRADIENT NORM =") != eachline.npos) {
606 double norm;
607 std::string stmp;
608 std::istringstream sstr(eachline);
609 sstr >> stmp >> stmp >> stmp >> norm;
610 eqstat = (norm < 10.0f) ? 0 : -1;
611 if (eqstat != 0) std::cerr << "Warning Hessian is not used under equilibrium!\n";
612 }
613 if (eachline.find("FORCE CONSTANT MATRIX AFTER SYMMETRIZATION.") != eachline.npos) {
614 for (int i = 0; i < v1; ++i) {
615 getline(ifs, eachline); // skip a blankline
616 for (int k = 0; k < 10; ++k) ifs >> itmp; // skip header
617 for (int j = 0; j < Dimension::N; ++j) {
618 ifs >> itmp; // skip index
619 for (int k = 0; k < 10; ++k) ifs >> hess[Dimension::N * j + i * 10 + k]; // read
620 }
621 }
622 if (v2 == 0) continue;
623 getline(ifs, eachline); // skip a blankline
624 for (int k = 0; k < v2; ++k) ifs >> itmp; // skip header
625 for (int j = 0; j < Dimension::N; ++j) {
626 ifs >> itmp; // skip index
627 for (int k = 0; k < v2; ++k) ifs >> hess[Dimension::N * j + v1 * 10 + k]; // read
628 }
629 }
630 if (eachline.find("EIGENVECTORS OF THE MASS-WEIGHTED") != eachline.npos) {
631 for (int i = 0; i < v1; ++i) {
632 getline(ifs, eachline); // skip a blankline
633 for (int k = 0; k < 10; ++k) ifs >> itmp; // skip header
634 for (int k = 0; k < 10; ++k) { // read frequency
635 if (ifs >> dtmp) w[i * 10 + k] = dtmp / phys::au_2_wn; // [convert wn to au]
636 }
637 for (int j = 0; j < Dimension::N; ++j) { // read normal-mode
638 ifs >> itmp; // skip index
639 for (int k = 0; k < 10; ++k) {
640 if (ifs >> dtmp) Tmod[Dimension::N * j + i * 10 + k] = dtmp;
641 }
642 }
643 }
644 if (v2 == 0) continue;
645 getline(ifs, eachline); // skip a blankline
646 for (int k = 0; k < v2; ++k) ifs >> itmp; // skip header
647 for (int k = 0; k < v2; ++k) { // read frequency
648 if (ifs >> dtmp) w[v1 * 10 + k] = dtmp / phys::au_2_wn; // [convert wn to au]
649 }
650 for (int j = 0; j < Dimension::N; ++j) { // read normal-mode
651 ifs >> itmp; // skip index
652 for (int k = 0; k < v2; ++k) {
653 if (ifs >> dtmp) Tmod[Dimension::N * j + v1 * 10 + k] = dtmp;
654 }
655 }
656 }
657 }
658 ifs.close();
659 return 0;
660}
661
665int Model_Interf_MNDO::parse_hessian2(const std::string& molden_file) {
666 std::ifstream ifs(molden_file);
667
668 // initialization of arrays
669 ARRAY_CLEAR(w, Dimension::N);
670 ARRAY_CLEAR(hess, Dimension::NN);
671 ARRAY_CLEAR(Tmod, Dimension::NN);
672
673 std::string stmp, eachline;
674 int itmp;
675 double dtmp = 0.0f;
676 while (getline(ifs, eachline)) {
677 if (eachline.find("[FREQ]") != eachline.npos) {
678 for (int j = 6; j < Dimension::N; ++j) {
679 getline(ifs, eachline);
680 std::stringstream sstr{eachline};
681 if (sstr >> dtmp) w[j] = dtmp / phys::au_2_wn;
682 }
683 }
684 if (eachline.find("[FR-NORM-COORD]") != eachline.npos) {
685 for (int i = 6; i < Dimension::N; ++i) {
686 ifs >> stmp >> itmp;
687 for (int j = 0; j < Dimension::N; ++j) {
688 if (ifs >> dtmp) Tmod[j * Dimension::N + i] = dtmp * sqrt(mass[j] * phys::au_2_amu);
689 }
690 }
691 }
692 }
693 ifs.close();
694
695 // ARRAY_SHOW(w, 1, Dimension::N);
696 // ARRAY_SHOW(mass, 1, Dimension::N);
697 // ARRAY_SHOW(Tmod, Dimension::N, Dimension::N);
698 // std::cout << FMT(8) << phys::au_2_amu << "\n";
699 return 0;
700}
701
702
710int Model_Interf_MNDO::calc_normalmode() {
711 // update mndohess input/output files
712 if (isFileExists(".mndohess.out")) {
713 new_task(".mndohess.in", "hess");
714 int stat = system("mndo < .mndohess.in > .mndohess.out");
715 if (stat != 0) return stat;
716 }
717 int stat = parse_hessian(".mndohess.out");
718 assert(stat == 0);
719
727 int ntime = 50; // report 50 points in [0,2*pi] period
728 for (int iw = 0; iw < Dimension::N; ++iw) { // iw-the mode
729 std::string save = "normalmode";
730 std::ofstream ofs(save + std::to_string(iw) + ".xyz");
731 for (int itime = 0; itime < ntime; ++itime) { // itime
732 for (int i = 0; i < Dimension::N; ++i) {
733 x[i] = x0[i] + Tmod[Dimension::N * i + iw] / std::sqrt(mass[i]) *
734 std::sin(itime * phys::math::twopi / ntime) / std::sqrt(2.0f * w[iw]);
735 }
736 ofs << natom << std::endl;
737 ofs << "time: " << (itime * phys::math::twopi) / (w[iw] * ntime) << std::endl;
738 for (int i = 0, idx = 0; i < natom; ++i) {
739 ofs << FMT(8) << ELEMENTS_LABEL[atoms[i]] //
740 << FMT(8) << x[idx++] * phys::au_2_ang //
741 << FMT(8) << x[idx++] * phys::au_2_ang //
742 << FMT(8) << x[idx++] * phys::au_2_ang << std::endl;
743 }
744 }
745 ofs.close();
746 }
747 return 0;
748}
749
757int Model_Interf_MNDO::calc_samp() {
758 Status stat;
759
760 if (!isFileExists(".mndohess.out")) {
761 new_task(".mndohess.in", "hess");
762 system("mndo < .mndohess.in > .mndohess.out");
763 // if (stat != 0) return stat;
764 }
765 parse_hessian(".mndohess.out");
766 // assert(stat == 0);
767
771 for (int i = 0, idx = 0; i < Dimension::N; ++i)
772 for (int j = 0; j < Dimension::N; ++j, ++idx) hess[idx] /= sqrt(mass[i] * mass[j]);
773
774 double Qeff = 6.0;
775 for (int j = 0; j < Dimension::N; ++j) {
776 if (j < 6 || w[j] < 1.0e-3) { // cutoff low frequency
777 x_sigma[j] = 0.0f;
778 p_sigma[j] = 0.0f;
779 } else { // NOTE: it's for normal-mode!
780 double Qoverbeta = 1.0f / beta; // 0.5f * w[j] / std::tanh(0.5f * beta * w[j]);
781 Qeff += Qoverbeta * beta;
782 x_sigma[j] = std::sqrt(Qoverbeta / (w[j] * w[j]));
783 p_sigma[j] = std::sqrt(Qoverbeta);
784 }
785 }
786 Qeff /= Dimension::N;
787 Qeff = 0.5f * beta * w[Dimension::N - 1] / std::tanh(0.5f * beta * w[Dimension::N - 1]);
788
789 std::cout << "Qeff = " << Qeff;
790
791 for (int i = 0; i < Dimension::N; ++i) x[i] = x0[i];
792 executeKernel_impl(stat);
793 double ref_ener = E[0];
794 std::cout << ref_ener;
795
796 for (int isamp = 0; isamp < 500; ++isamp) {
797 Kernel_Random::rand_gaussian(x, Dimension::N);
798 Kernel_Random::rand_gaussian(p, Dimension::N);
799 for (int i = 0; i < 6; ++i) x[i] = 0.0f, p[i] = 0.0f;
800 for (int i = 0; i < Dimension::N; ++i) {
801 x[i] *= x_sigma[i];
802 p[i] *= p_sigma[i];
803 }
804 // transfrom normal-mode to cartesian coordinates
805 ARRAY_MATMUL(x, Tmod, x, Dimension::N, Dimension::N, 1);
806 ARRAY_MATMUL(p, Tmod, p, Dimension::N, Dimension::N, 1);
807 for (int i = 0; i < Dimension::N; ++i) {
808 x[i] = x[i] / std::sqrt(mass[i]) + x0[i];
809 p[i] = p[i] * std::sqrt(mass[i]);
810 }
811
812 // fluctuation of Kinetic energy
813 double Ekin = 0.0;
814 for (int i = 0; i < Dimension::N; ++i) Ekin += 0.5f * p[i] * p[i] / mass[i];
815
816 // fluctuation of potential energy
817 executeKernel_impl(stat);
818 double Epot = (E[0] - ref_ener); // convert to au
819 std::cout << Epot;
820 std::cout << "::: " << beta * Epot / Qeff << " " << beta * Ekin / Qeff;
821
822 if (beta * Epot > 10 || beta * Ekin > 10) {
823 std::cout << "failed sample once";
824 std::ofstream ofs(utils::concat("sampfail", isamp));
825 ofs << FMT(8) << natom << std::endl; // number of atoms
826 ofs << FMT(8) << isamp << FMT(8) << beta << FMT(8) << Epot << FMT(8) << Ekin << std::endl;
827 for (int i = 0, idx1 = 0, idx2 = 0; i < natom; ++i) {
828 // output configuration ([angstrom])
829 ofs << FMT(8) << ELEMENTS_LABEL[atoms[i]];
830 for (int k = 0; k < 3; ++k, ++idx1) ofs << FMT(8) << x[idx1] * phys::au_2_ang;
831 // output velocity ([angstrom/ps])
832 for (int k = 0; k < 3; ++k, ++idx2) ofs << FMT(8) << p[idx2] / mass[idx2] * phys::au_2_angoverps;
833 ofs << std::endl;
834 }
835 ofs.close();
836 isamp--;
837 continue; // for resampling
838 };
839
840 std::cout << "test: " << beta * Epot << " " << beta * Ekin;
841
842 std::ofstream ofs(utils::concat("samp", isamp));
843 ofs << FMT(8) << natom << std::endl; // number of atoms
844 ofs << FMT(8) << isamp << std::endl;
845 for (int i = 0, idx1 = 0, idx2 = 0; i < natom; ++i) {
846 // output configuration ([angstrom])
847 ofs << FMT(8) << ELEMENTS_LABEL[atoms[i]];
848 for (int k = 0; k < 3; ++k, ++idx1) ofs << FMT(8) << x[idx1] * phys::au_2_ang;
849 // output velocity ([angstrom/ps])
850 for (int k = 0; k < 3; ++k, ++idx2) ofs << FMT(8) << p[idx2] / mass[idx2] * phys::au_2_angoverps;
851 ofs << std::endl;
852 }
853 ofs.close();
854 }
855 return 0;
856}
857
858int Model_Interf_MNDO::calc_scan() {
859 int istep = 0, readn;
860 kids_real tmp;
861 std::string eachline;
862 Status stat;
863
864 // savefile_traj = utils::concat("traj-", 0, ".xyz");
865 // savefile_ener = utils::concat("ener-", 0, ".dat");
866 // savefile_grad = utils::concat("grad-", 0, ".dat");
867 // savefile_nac = utils::concat("nac-", 0, ".dat");
868 // clearFile(savefile_traj);
869 // clearFile(savefile_ener);
870 // clearFile(savefile_grad);
871 // clearFile(savefile_nac);
872
873 std::ifstream ifs("scan.xyz");
874 if (!ifs.is_open()) throw std::runtime_error("scan.xyz cannot open");
875
876 while (getline(ifs, eachline)) {
877 std::istringstream isstr(eachline);
878 isstr >> readn;
879 assert(natom == readn);
880 getline(ifs, eachline); // skip comments
881 for (int iatom = 0, idx1 = 0; iatom < natom; ++iatom) {
882 ifs >> eachline; // skip atomic flag
883 for (int i = 0; i < 3; ++i, ++idx1) { // read in [angstrom]
884 if (ifs >> tmp) x[idx1] = tmp / phys::au_2_ang;
885 }
886 }
887 getline(ifs, eachline); // a line!!!
888 executeKernel_impl(stat);
889 istep++;
890 }
891 ifs.close();
892 return 0;
893}
894}; // namespace PROJECT_NS
bool isFileExists(const std::string &name)
void closeOFS(std::ofstream &ofs)
bool isFileExists(const std::string &name)
int removeFile(const std::string &filename)
void clearFile(const std::string &filename)
#define ARRAY_MATMUL(_A, _B, _C, _n1, _n2, _n3)
#define ARRAY_CLEAR(_A, _n)
Definition array_macro.h:36
provide databases in chemistry
const char *const ELEMENTS_LABEL[]
Definition chem.h:40
const double ELEMENTS_MASS[]
Definition chem.h:55
static int rand_gaussian(kids_real *res_arr, int N=1, kids_real sigma=1.0, kids_real mu=0.0)
static bool onthefly
flag indicated the ab inition calculation
std::shared_ptr< Param > _param
Shared pointer to the Param object associated with this kernel.
Definition Kernel.h:273
std::shared_ptr< DataSet > _dataset
Shared pointer to the DataSet object associated with this kernel.
Definition Kernel.h:278
void setInputParam_impl(std::shared_ptr< Param > &PM)
Virtual function to set input parameters for the kernel implementation.
Status & parse_standard(const std::string &log, Status &stat)
parse energy/gradients/nac from output
std::string new_keyword(const MNDOKW_map &newkeyword)
generate a new set of keywords
void setInputDataSet_impl(std::shared_ptr< DataSet > &DS)
Virtual function to set input data set for the kernel implementation.
int track_nac_sign()
this part track the sign of NAC between current step with the last step, in order to make sure nac ch...
int parse_hessian(const std::string &log)
parse frequency calculation log where the frequency should be calculated by specifying (JOP=2),...
int parse_mndo(const std::string &mndoinp)
this function parse mndo input (only support cartesian format)
virtual const std::string getName()
Get the name of the kernel.
std::vector< MNDOKW > keyword
int parse_hessian2(const std::string &log)
parse frequency calculation (JOP=2) and (KPRINT=1)
Status & executeKernel_impl(Status &stat)
Virtual function to execute the kernel implementation.
virtual int getType() const
Get the type of the kernel.
int new_task(const std::string &file, const std::string &task_flag)
generate input file for a new task based on the template
int calc_normalmode()
this function generates normalmode trajectories
int calc_samp()
this function generates initialization configuration
std::vector< std::string > mndo_data
Status & initializeKernel_impl(Status &stat)
ForceField_init for mndo.
#define LOC()
show the location information for debug
Definition fmt.h:49
#define FMT(X)
Definition fmt.h:40
Provide linalg APIs.
#define FUNCTION_NAME
Definition macro_utils.h:9
VARIABLE< kids_real > p
VARIABLE< kids_real > x
VARIABLE< kids_bint > frez
VARIABLE< kids_bint > last_attempt
VARIABLE< kids_int > fail_type
VARIABLE< kids_bint > succ
VARIABLE< kids_real > dE
VARIABLE< kids_real > E
VARIABLE< kids_real > T
VARIABLE< kids_real > nac
VARIABLE< kids_real > nac_prev
VARIABLE< kids_real > Tmod
VARIABLE< kids_real > f_r
VARIABLE< kids_real > hess
VARIABLE< kids_real > f_p
VARIABLE< kids_real > p_sigma
VARIABLE< kids_real > vpes
VARIABLE< kids_int > atoms
VARIABLE< kids_real > V
VARIABLE< kids_real > p0
VARIABLE< kids_real > dV
VARIABLE< kids_real > x_sigma
VARIABLE< kids_real > x0
VARIABLE< kids_real > w
VARIABLE< kids_real > grad
VARIABLE< kids_real > mass
VARIABLE< kids_real > f_rp
std::size_t NFF
Product of N, F, and F (N * F * F).
Definition vars_list.cpp:22
std::size_t N
Number of nuclear degrees of freedom.
Definition vars_list.cpp:10
std::size_t NN
Product of N and N (N * N).
Definition vars_list.cpp:20
std::size_t F
Number of electronic degrees of freedom.
Definition vars_list.cpp:11
std::size_t Fadd1
F plus 1 (F + 1).
Definition vars_list.cpp:24
std::size_t FF
Product of F and F (F * F).
Definition vars_list.cpp:21
< http://warp.povusers.org/FunctionParser/fparser.html
Definition Context.h:39
double kids_real
Alias for real number type.
Definition Types.h:59
std::map< std::string, std::string > MNDOKW_map
constexpr real_precision twopi
Definition phys.h:31
constexpr dimension7 temperature_d
Definition phys.h:195
static CONSTTYPE real_precision au_2_angoverps
Definition phys.h:1002
static CONSTTYPE real_precision au_2_amu
1mea means we measure a quantity at 1*N level.
Definition phys.h:992
static CONSTTYPE real_precision au_2_wn
Definition phys.h:998
static CONSTTYPE real_precision au_2_ang
Definition phys.h:993
static CONSTTYPE real_precision au_2_kcal_1mea
Definition phys.h:996
std::basic_string< CharT > concat(const separator_t< CharT > &sep, Args &&... seq)
Definition concat.h:242
constexpr uint32_t hash(const char *str)
Definition hash_fnv1a.h:12
declaration of variables used in the program.