1 /******************************************************************************
2
3 This source file is part of the Avogadro project.
4
5 Copyright 2010 Jens Thomas
6 Copyright 2010-2013 Kitware, Inc.
7
8 This source code is released under the New BSD License, (the "License").
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16 ******************************************************************************/
17
18 #include "gamessukout.h"
19 #include <fstream>
20 #include <iostream>
21
22 #include <QtCore/QRegExp>
23 #include <QtCore/QString>
24 #include <QtCore/QStringList>
25
26 using Eigen::Vector3d;
27 using std::vector;
28
29 namespace Avogadro {
30 namespace QuantumIO {
31
32 using Quantum::S;
33 using Quantum::SP;
34 using Quantum::P;
35 using Quantum::D;
36 using Quantum::F;
37 using Quantum::UU;
38
39 using Quantum::orbital;
40
41 //! Break a string (supplied as the second argument) into tokens, returned
42 //! in the first argument. Tokens are determined by the delimiters supplied
tokenize(std::vector<std::string> & vcr,const char * buf,const char * delimstr)43 bool tokenize(std::vector<std::string>& vcr, const char* buf,
44 const char* delimstr)
45 {
46 // Not the most efficient way to do this, but this avoids using GPL code
47 // from openbabel.
48 if (!buf || !delimstr)
49 return false;
50
51 QString tmp(buf);
52 tmp += "\n"; // for compatibility with old behavior
53 vcr.clear();
54 QString splitString("[");
55 splitString += QString(delimstr);
56 splitString += QString("]");
57 QRegExp splitter(splitString);
58 foreach (const QString& str, tmp.split(splitter, QString::SkipEmptyParts))
59 vcr.push_back(str.toStdString());
60
61 return true;
62 }
63
64 //! Removes white space from front and back of string
Trim(std::string & txt)65 std::string& Trim(std::string& txt)
66 {
67 // Not the most efficient way to do this, but this avoids using GPL code
68 // from openbabel.
69 txt = QString::fromStdString(txt).trimmed().toStdString();
70 return txt;
71 }
72
73 /**
74 * This purloined from: http://www.codeguru.com/forum/showthread.php?t=231054
75 */
76 template <class T>
from_string(T & t,const std::string & s,std::ios_base & (* f)(std::ios_base &))77 bool from_string(T& t, const std::string& s,
78 std::ios_base& (*f)(std::ios_base&))
79 {
80 std::istringstream iss(s);
81 return !(iss >> f >> t).fail();
82 }
83
outputCoord()84 void GUKBasisSet::outputCoord()
85 {
86 std::cout << "Coordinates:\n";
87 for (unsigned int i = 0; i < coordinates.size(); i++) {
88 printf("%d: %3s %10f %10f %10f\n", i, atomLabels[i].c_str(),
89 coordinates[i][0], coordinates[i][1], coordinates[i][2]);
90 }
91 } // end outputCoord
92
outputBasis()93 void GUKBasisSet::outputBasis()
94 {
95 std::cout << "Basis functions" << std::endl;
96
97 int prev;
98 for (unsigned int i = 0; i < shellLabels.size(); i++) {
99 std::cout << "Atom(" << i << "): " << shellLabels.at(i) << std::endl;
100 // std::cout << "shells at(i).size() " << shells.at(i).size() << std::endl;
101 for (unsigned int j = 0; j < shells.at(i).size(); j++) {
102 // The first indexes are different as they are the indexes held at the
103 // end of the last shell or 0 for the first one
104 if (i == 0 && j == 0)
105 prev = 0;
106 else if (j == 0)
107 prev = gtoIndicies.at(i - 1).back();
108 else
109 prev = gtoIndicies.at(i).at(j - 1);
110 std::cout << "shell type " << shells.at(i).at(j) << std::endl;
111 for (unsigned int k = prev; k < gtoIndicies.at(i).at(j); k++) {
112 std::cout << " e = " << gtoExponents.at(k)
113 << " c = " << gtoCoefficients.at(k) << std::endl;
114 }
115 }
116 }
117
118 std::cout << "Read in nShell " << nShell << std::endl;
119 std::cout << "Read in nBasisFunctions " << nBasisFunctions << std::endl;
120 std::cout << "Read in nElectrons " << nElectrons << std::endl;
121
122 } // end outputBasis
123
labelIndex(std::string label)124 bool GUKBasisSet::labelIndex(std::string label)
125 {
126 for (unsigned int i = 0; i < shellLabels.size(); i++)
127 if (shellLabels.at(i) == label)
128 return true;
129 return false;
130 } // end labelIndex
131
shellTypeFromString(std::string label)132 orbital GUKBasisSet::shellTypeFromString(std::string label)
133 {
134 /**
135 * Return the enum from basis.h for the supplied label as a string
136 * basisset.h: enum orbital { S, SP, P, D, D5, F, F7, UU };
137
138 * The label is from the GAMESS-UK basis set label, which is printed as shown
139 below:
140
141 * shell type prim exponents contraction coefficients
142 * 1 1s 3 5.533350 1.801737 ( 0.700713 )
143 * or
144 * 2 2sp 4 3.664980 -0.747384 ( -0.395897 )
145 1.709178 ( 0.236460 )
146
147 */
148
149 // Could be e.g. 's', 'l', '2sp' or '1s'.
150 // We assume that if it is longer then 1 character long, the rest is the label
151 if (label.size() > 1) {
152 // Remove the shell number
153 label = label.substr(1, std::string::npos);
154 }
155
156 // Check for sp
157 if (label.size() == 2) {
158 if (label.compare(0, 2, "sp") == 0)
159 return SP;
160 }
161
162 if (label.size() == 1) {
163 if (label == "l")
164 return SP;
165 if (label == "s")
166 return S;
167 if (label == "p")
168 return P;
169 if (label == "d")
170 return D;
171 } // end label of length 1
172
173 // if we get here, it's all gone wrong...
174 std::cerr << "ERROR: shellTypeFromString with label: " << label << std::endl;
175 return UU;
176 }
177
GamessukOut(const QString & qtfilename,GaussianSet * basis)178 GamessukOut::GamessukOut(const QString& qtfilename, GaussianSet* basis)
179 {
180 std::string filename;
181 filename = qtfilename.toStdString();
182 GamessukOutNoQt(filename, basis);
183 } // end GamessukOut
184
~GamessukOut()185 GamessukOut::~GamessukOut()
186 {
187 } // end ~GamessukOut
188
GamessukOutNoQt(const std::string & filename,GaussianSet * basis)189 void GamessukOut::GamessukOutNoQt(const std::string& filename,
190 GaussianSet* basis)
191 {
192
193 bool ok;
194 std::ifstream ifs;
195
196 ifs.open(filename.c_str());
197 if (!ifs) {
198 std::cerr << "Cannot open: " << filename << "\n";
199 return;
200 }
201
202 // Initialise the basis set object that holds the parsed data before we
203 // convert
204 // it into Avogadro form
205 gukBasis = GUKBasisSet();
206
207 // Now read the file
208 ok = parseFile(ifs);
209
210 ifs.close();
211
212 if (ok) {
213 // outputParsedData();
214 // Create the Avogadro basis set object
215 load(basis);
216 } else
217 std::cerr << "ERROR READING ORBITALS FROM FILE: " << filename << std::endl;
218
219 } // end GamessukOutNoQt
220
outputParsedData()221 void GamessukOut::outputParsedData()
222 {
223 gukBasis.outputCoord();
224 gukBasis.outputBasis();
225 } // end outputParsedData
226
parseFile(std::ifstream & ifs)227 bool GamessukOut::parseFile(std::ifstream& ifs)
228 {
229
230 /**
231 * Loop through the file, calling routines that read in the data of interest
232 * into the GUKBasisSet object
233 * Is currently pretty rudimentary - could do with lots of error trapping to
234 * check all o.k.
235 */
236
237 bool gotMOs = false; // used as return value - indicates if we have valid
238 // orbitals for the coordinates we've read in
239
240 while (ifs.good() && ifs.getline(buffer, BUFF_SIZE)) {
241
242 // First find oriented geometry - use this for single-point calculations
243 if (strstr(buffer,
244 " * atom atomic coordinates") !=
245 nullptr) {
246 readInitialCoordinates(ifs);
247 }
248
249 // The basis set definition
250 if (strstr(buffer, " atom shell type prim exponents "
251 " contraction coefficients") != nullptr) {
252 readBasisSet(ifs);
253 }
254
255 // Determine the scftype - can't do uhf yet
256 if (strstr(buffer, " * SCF TYPE") != nullptr) {
257 tokenize(tokens, buffer, " \t\n");
258 if (tokens[3].compare(0, 6, "rhf") != 0) {
259 std::cerr << "ERROR: can currently only do rhf!\n";
260 return false;
261 }
262 }
263
264 // The converged geometry
265 if (strstr(buffer, "optimization converged") != nullptr) {
266 readOptimisedCoordinates(ifs);
267 if (gotMOs)
268 gotMOs = false; // If we read in some MOs they are now redundant
269 }
270
271 // The molecular orbitals
272 if (strstr(
273 buffer,
274 " eigenvectors") !=
275 nullptr ||
276 strstr(buffer, " molecular orbitals") != nullptr) {
277 readMOs(ifs);
278 gotMOs = true;
279 }
280 }
281
282 return gotMOs;
283 }
284
readInitialCoordinates(std::ifstream & ifs)285 void GamessukOut::readInitialCoordinates(std::ifstream& ifs)
286 {
287 // string to mark end of the coordinates
288 char coordEnd[86] = " "
289 "********************************************************"
290 "********************";
291 double x = 0.0, y = 0.0, z = 0.0;
292
293 // skip five lines
294 ifs.getline(buffer, BUFF_SIZE) && ifs.getline(buffer, BUFF_SIZE) &&
295 ifs.getline(buffer, BUFF_SIZE) && ifs.getline(buffer, BUFF_SIZE) &&
296 ifs.getline(buffer, BUFF_SIZE);
297
298 while (strstr(buffer, coordEnd) == nullptr) {
299 // std::cout << "COORD line" << buffer << std::endl;
300 // ifs.getline(buffer, BUFF_SIZE);
301 tokenize(tokens, buffer, " \t\n");
302
303 if (tokens.size() == 8) {
304 // std::cout << "Coord line" << buffer << std::endl;
305 gukBasis.atomLabels.push_back(tokens.at(1));
306
307 from_string<double>(x, tokens.at(3), std::dec);
308 from_string<double>(y, tokens.at(4), std::dec);
309 from_string<double>(z, tokens.at(5), std::dec);
310 gukBasis.coordinates.push_back(
311 Eigen::Vector3d(x, y, z)); // Want coordinates in Bohr
312 }
313
314 ifs.getline(buffer, BUFF_SIZE);
315 }
316 }
317
readBasisSet(std::ifstream & ifs)318 void GamessukOut::readBasisSet(std::ifstream& ifs)
319 {
320
321 // std::cout << "readBasisSet\n";
322
323 bool newAtom = true, gotAtom = false, firstAtom = true;
324 std::string atomLabel;
325 double exponent, coefficient;
326 orbital stype;
327 int nshell = -1;
328 int lastNshell = -1; // the last shell number - is same as nshell when looping
329 // through a shell
330 int lastStype = -1; // need to keep track of sp shells as we split into s & p
331
332 // For separating sp-shells
333 std::vector<double> s_coeff;
334 std::vector<double> p_coeff;
335 std::vector<double> sp_exponents;
336
337 // skip 2 lines to be just before the first atom label
338 ifs.getline(buffer, BUFF_SIZE) && ifs.getline(buffer, BUFF_SIZE);
339
340 // now loop through the basis sets till we hit the end
341 while (!ifs.eof()) {
342 ifs.getline(buffer, BUFF_SIZE);
343 line = buffer;
344
345 if (line.compare(0, 10, " =========") == 0) {
346 // End of basis - add indicies of where the coffecients and exponents of
347 // the GTOs for the last shell end
348 gukBasis.gtoIndicies.at(gukBasis.shellLabels.size() - 1)
349 .push_back(static_cast<unsigned int>(gukBasis.gtoExponents.size()));
350 break;
351 }
352
353 // Remove blank space
354 line = Trim(line);
355
356 // skip blank lines
357 if (line.size() == 0)
358 continue;
359
360 // Separate into tokens
361 if (!tokenize(tokens, line.c_str(), " \t\n") || tokens.size() == 0) {
362 // If the string couldn't be tokenised, set tokens[0] to the entire string
363 tokens.clear();
364 tokens.push_back(line);
365 }
366
367 if (tokens.size() == 1) {
368 // This means a new atomLabel
369 newAtom = true;
370 if (firstAtom)
371 firstAtom = false;
372 else {
373 // Check if the last shell was sp - if so add the temp sp data
374 // structures
375 // to the main ones
376 if (lastStype == SP) {
377 addSpBasis(s_coeff, p_coeff, sp_exponents);
378
379 // Clear the temp data structures for separating out sp into s & p
380 s_coeff.clear();
381 p_coeff.clear();
382 sp_exponents.clear();
383 lastStype = -1;
384 } else {
385 // Add the index for where the GTO coffecients and exponents for the
386 // previous shell start
387 gukBasis.gtoIndicies.at(gukBasis.shellLabels.size() - 1)
388 .push_back(static_cast<unsigned int>(gukBasis.gtoExponents.size()));
389 }
390
391 } // end firstAtom
392
393 // Check if we've already processed an atom of this type
394 if (!gukBasis.labelIndex(tokens.at(0))) {
395 // std::cout << "Processing atom label: " << tokens.at(0) << std::endl;
396 gotAtom = false; // we'll be processing this atom
397 gukBasis.shellLabels.push_back(tokens.at(0));
398 gukBasis.shells.push_back(std::vector<orbital>());
399 gukBasis.gtoIndicies.push_back(std::vector<unsigned int>());
400 } else
401 gotAtom = true;
402 continue;
403
404 } // End new atomLabel
405
406 // if we're not processing an atom we can skip this line
407 if (gotAtom)
408 continue;
409
410 /* Here we are reading in a line of the format:
411 shell type prim exponents contraction coefficients
412 1 1s 3 5.533350 1.801737 ( 0.700713 )
413 or
414 2 2sp 4 3.664980 -0.747384 ( -0.395897 )
415 1.709178 ( 0.236460 )
416 */
417
418 from_string<int>(nshell, tokens.at(0), std::dec);
419
420 if (nshell != lastNshell) {
421 // Reading a new shell
422
423 if (!newAtom) {
424 // Add the data for the last shell processed
425
426 // First check if last shell was sp & we need to add the data we've
427 // gathered to the main structures
428 if (lastStype == SP) {
429
430 addSpBasis(s_coeff, p_coeff, sp_exponents);
431
432 // Clear the temp data structures for separating out sp into s & p
433 s_coeff.clear();
434 p_coeff.clear();
435 sp_exponents.clear();
436 } else {
437 // Add the index for where the primitives for the last shell finish
438 gukBasis.gtoIndicies.at(gukBasis.shellLabels.size() - 1)
439 .push_back(static_cast<unsigned int>(gukBasis.gtoExponents.size()));
440
441 } // end sp shell
442
443 } // end newAtom
444
445 // need to determine type
446 stype = gukBasis.shellTypeFromString(tokens.at(1));
447 // std::cout << "Reading new shell of type " << stype << std::endl;
448
449 if (stype != SP) {
450 // Add shell to symmetry list and AtomToShellIndex if not sp shell as we
451 // do that separately
452 gukBasis.shells.at(gukBasis.shellLabels.size() - 1).push_back(stype);
453 }
454
455 } // end new shell
456
457 // Now check for coefficients - we take the second lot to match Gaussian
458 from_string<double>(exponent, tokens.at(3), std::dec);
459
460 if (stype == SP) {
461 if (tokens.size() != 12)
462 std::cerr << "PROBLEM READING SP LINE!\n";
463 from_string<double>(coefficient, tokens.at(6), std::dec);
464 s_coeff.push_back(coefficient);
465 from_string<double>(coefficient, tokens.at(10), std::dec);
466 p_coeff.push_back(coefficient);
467 sp_exponents.push_back(exponent);
468 } else {
469 // std::cout << "Adding exponent " << exponent << std::endl;
470 gukBasis.gtoExponents.push_back(exponent);
471 from_string<double>(coefficient, tokens.at(6), std::dec);
472 gukBasis.gtoCoefficients.push_back(coefficient);
473 } // end type == SP
474
475 lastNshell = nshell;
476 lastStype = stype;
477 newAtom = false;
478
479 } // end while
480
481 // Finished reading the basis data - now just collect some data from the
482 // summary - mainly for checking
483
484 ifs.getline(buffer, BUFF_SIZE); // blank
485
486 // nShell
487 ifs.getline(buffer, BUFF_SIZE);
488 if (strstr(buffer, " total number of shells") == nullptr)
489 std::cerr << "Error reading nShell!: " << line << std::endl;
490 // reuse nshell from above as temporary variable
491 tokenize(tokens, buffer, " \t\n");
492 from_string<int>(nshell, tokens.at(4), std::dec);
493 gukBasis.nShell = nshell;
494
495 // nBasisFunctions
496 ifs.getline(buffer, BUFF_SIZE);
497 if (strstr(buffer, " total number of basis") == nullptr)
498 std::cerr << "Error reading nBasisFunctions!: " << line << std::endl;
499 tokenize(tokens, buffer, " \t\n");
500 // reuse nshell from above as temporary variable
501 from_string<int>(nshell, tokens.at(5), std::dec);
502 gukBasis.nBasisFunctions = nshell;
503
504 // nElectrons
505 ifs.getline(buffer, BUFF_SIZE);
506 if (strstr(buffer, " number of electrons") == nullptr)
507 std::cerr << "Error reading nElectrons!: " << line << std::endl;
508 tokenize(tokens, buffer, " \t\n");
509 // reuse nshell from above as temporary variable
510 from_string<int>(nshell, tokens.at(3), std::dec);
511 gukBasis.nElectrons = nshell;
512
513 } // end readBasisSet
514
addSpBasis(std::vector<double> s_coeff,std::vector<double> p_coeff,std::vector<double> sp_exponents)515 inline void GamessukOut::addSpBasis(std::vector<double> s_coeff,
516 std::vector<double> p_coeff,
517 std::vector<double> sp_exponents)
518 {
519
520 // Convenience function for adding separated sp basis
521
522 // Add s
523 gukBasis.shells.at(gukBasis.shellLabels.size() - 1).push_back(S);
524
525 for (unsigned int i = 0; i < s_coeff.size(); i++) {
526 gukBasis.gtoExponents.push_back(sp_exponents[i]);
527 gukBasis.gtoCoefficients.push_back(s_coeff[i]);
528 }
529 gukBasis.gtoIndicies.at(gukBasis.shellLabels.size() - 1)
530 .push_back(static_cast<unsigned int>(gukBasis.gtoExponents.size()));
531
532 // Add p
533 gukBasis.shells.at(gukBasis.shellLabels.size() - 1).push_back(P);
534
535 for (unsigned int i = 0; i < p_coeff.size(); i++) {
536 gukBasis.gtoExponents.push_back(sp_exponents[i]);
537 gukBasis.gtoCoefficients.push_back(p_coeff[i]);
538 }
539 gukBasis.gtoIndicies.at(gukBasis.shellLabels.size() - 1)
540 .push_back(static_cast<unsigned int>(gukBasis.gtoExponents.size()));
541
542 } // end addSpBasis
543
readOptimisedCoordinates(std::ifstream & ifs)544 void GamessukOut::readOptimisedCoordinates(std::ifstream& ifs)
545 {
546
547 // std::cout << "readOptimisedCoordinates\n";
548
549 double x, y, z;
550
551 // Nuke the old coordinates
552 gukBasis.atomLabels.clear();
553 gukBasis.coordinates.clear();
554
555 ifs.getline(buffer, BUFF_SIZE);
556 while (!ifs.eof()) {
557
558 // This for some optimize runtypes
559 if (strstr(
560 buffer,
561 " x y z chg tag") !=
562 nullptr) {
563 // std::cout << "start of opt coord\n";
564 // Skip 2 lines - should then be at the coordinates
565 ifs.getline(buffer, BUFF_SIZE) && ifs.getline(buffer, BUFF_SIZE);
566
567 while (!ifs.eof()) {
568 // End of geometry block
569 if (strstr(buffer, " "
570 "==================================================="
571 "=========") != nullptr)
572 return;
573
574 tokenize(tokens, buffer, " \t\n");
575
576 from_string<double>(x, tokens.at(0), std::dec);
577 from_string<double>(y, tokens.at(1), std::dec);
578 from_string<double>(z, tokens.at(2), std::dec);
579
580 gukBasis.coordinates.push_back(Eigen::Vector3d(x, y, z));
581 gukBasis.atomLabels.push_back(tokens.at(4));
582
583 ifs.getline(buffer, BUFF_SIZE);
584 } // end while
585 } else if (strstr(buffer,
586 "atom znuc x y z") !=
587 nullptr) {
588
589 // print "start of opt coord 2"
590
591 // Skip 3 lines - should then be at the coordinates
592 ifs.getline(buffer, BUFF_SIZE) && ifs.getline(buffer, BUFF_SIZE) &&
593 ifs.getline(buffer, BUFF_SIZE);
594
595 while (!ifs.eof()) {
596 // End of geometry block
597 if (strstr(buffer, "*************************") != nullptr)
598 return;
599
600 tokenize(tokens, buffer, " \t\n");
601
602 gukBasis.atomLabels.push_back(tokens.at(0));
603 from_string<double>(x, tokens.at(3), std::dec);
604 from_string<double>(y, tokens.at(4), std::dec);
605 from_string<double>(z, tokens.at(5), std::dec);
606
607 gukBasis.coordinates.push_back(Eigen::Vector3d(x, y, z));
608
609 ifs.getline(buffer, BUFF_SIZE);
610 } // end of while
611 }
612
613 ifs.getline(buffer, BUFF_SIZE);
614 } // end of read loop
615
616 } // end readOptimisedCoordinates
617
readMOs(std::ifstream & ifs)618 void GamessukOut::readMOs(std::ifstream& ifs)
619 {
620 /*
621 Read the Molecular Orbitals as printed out by util1.m subroutine prev
622 */
623
624 int orbitalsRead, orbitalsRead1;
625
626 // Nuke any old set - fix when look at alpha & beta
627 gukBasis.moVectors.clear();
628
629 // Skip 3 lines to be just before first header
630 ifs.getline(buffer, BUFF_SIZE) && ifs.getline(buffer, BUFF_SIZE) &&
631 ifs.getline(buffer, BUFF_SIZE);
632
633 orbitalsRead1 = readMOVectors(ifs);
634 orbitalsRead = orbitalsRead1;
635 while (orbitalsRead == orbitalsRead1 || orbitalsRead != 0)
636 orbitalsRead = readMOVectors(ifs);
637
638 } // end readMos
639
readMOVectors(std::ifstream & ifs)640 int GamessukOut::readMOVectors(std::ifstream& ifs)
641 {
642 /*
643 Loop through a series of columns of printed MO vectors & return the
644 number of orbitals read in
645 */
646
647 unsigned int norbitals, norbitalsRead;
648 double energy;
649
650 ifs.getline(buffer, BUFF_SIZE);
651 // std::cout << "HeaderLine " << buffer << std::endl;
652
653 // Check we're not at the end
654 if (strstr(buffer, "end of") != 0)
655 return 0;
656
657 tokenize(tokens, buffer, " \t\n");
658 // How many orbital columns:
659 norbitals = static_cast<unsigned int>(tokens.size());
660
661 for (unsigned int i = 0; i < tokens.size(); i++) {
662 from_string<double>(energy, tokens.at(i), std::dec);
663 // std::cout << "adding e " << energy << std::endl;
664 gukBasis.moEnergies.push_back(energy);
665 }
666
667 // Add the lists to hold this set of coefficients
668 // How many were read in previously:
669 norbitalsRead = static_cast<unsigned int>(gukBasis.moVectors.size());
670
671 // Create the arrays to hold the coefficients for each orbital
672 for (unsigned int i = 0; i < norbitals; i++)
673 gukBasis.moVectors.push_back(std::vector<double>());
674
675 // skip 5 lines to just before where first set of orbitals are printed
676 ifs.getline(buffer, BUFF_SIZE) && ifs.getline(buffer, BUFF_SIZE) &&
677 ifs.getline(buffer, BUFF_SIZE) && ifs.getline(buffer, BUFF_SIZE) &&
678 ifs.getline(buffer, BUFF_SIZE);
679
680 // loop nBasisFunctions times to read in up to norbitals coefficients
681 for (int i = 0; i < gukBasis.nBasisFunctions; i++) {
682 ifs.getline(buffer, BUFF_SIZE);
683 // std::cout << "MO line " << buffer << std::endl;
684
685 tokenize(tokens, buffer, " \t\n");
686
687 for (unsigned int j = 0; j < norbitals; j++) {
688 // reuse variable energy to hold coefficient
689 from_string<double>(energy, tokens.at(j + 4), std::dec);
690 gukBasis.moVectors.at(norbitalsRead + j).push_back(energy);
691 // std::cout << "Adding " << energy << " to vector " << norbitalsRead+j <<
692 // std::endl;
693 }
694 }
695
696 // skip 2 lines to where the next set of headers are printed
697 ifs.getline(buffer, BUFF_SIZE);
698 ifs.getline(buffer, BUFF_SIZE);
699
700 // If we are printed out after an optimisation under the control of "iprint
701 // vectors",
702 // the next line with be filled with " =================" if we've finished
703 if (strstr(buffer, " ===============================") != 0)
704 return 0;
705
706 return norbitals;
707
708 } // end readMOVectors
709
addBasisForLabel(unsigned int atomIndex,std::string label,GaussianSet * basis)710 void GamessukOut::addBasisForLabel(unsigned int atomIndex, std::string label,
711 GaussianSet* basis)
712 {
713 /*
714 Add the basis functions for the atom label
715 */
716
717 unsigned int s;
718 int prev;
719 for (unsigned int i = 0; i < gukBasis.shellLabels.size(); i++) {
720 if (gukBasis.shellLabels.at(i) != label)
721 continue;
722
723 for (unsigned int j = 0; j < gukBasis.shells.at(i).size(); j++) {
724 s = basis->addBasis(atomIndex, gukBasis.shells.at(i).at(j));
725
726 // The first indexes are different as they are the indexes held at the end
727 // of the last shell or
728 // 0 for the first one
729 if (i == 0 && j == 0)
730 prev = 0;
731 else if (j == 0)
732 prev = gukBasis.gtoIndicies.at(i - 1).back();
733 else
734 prev = gukBasis.gtoIndicies.at(i).at(j - 1);
735
736 for (unsigned int k = prev; k < gukBasis.gtoIndicies.at(i).at(j); k++) {
737 basis->addGTO(s, gukBasis.gtoCoefficients.at(k),
738 gukBasis.gtoExponents.at(k));
739 }
740 }
741 }
742 return;
743
744 } // end addBasisForLabel
745
load(GaussianSet * basis)746 void GamessukOut::load(GaussianSet* basis)
747 {
748 /*
749 We will only have read in a basis set for atoms of each type
750 Loop through the list of all the atoms & add the basis functions for each
751 individual atom
752
753 */
754
755 basis->setNumElectrons(gukBasis.nElectrons);
756
757 // Add the basis for each atom
758 for (unsigned int i = 0; i < gukBasis.atomLabels.size(); i++) {
759 basis->addAtom(gukBasis.coordinates.at(i));
760 addBasisForLabel(i, gukBasis.atomLabels.at(i), basis);
761 }
762
763 // Now to load in the MO coefficients
764 // This currently a dirty hack - basisset addMO just expects a long vector of
765 // doubles, which
766 // it then converts into a square matrix.
767 // For this test, we convert our vector of vectors to a single vector and fill
768 // the remaining
769 // virtual orbitals with zeros.
770
771 std::vector<double> MOs;
772 unsigned int moEnd,
773 nBasis = static_cast<unsigned int>(gukBasis.nBasisFunctions);
774
775 for (unsigned int i = 0; i < nBasis; i++) {
776 if (i >= gukBasis.moVectors.size()) {
777 // std::cout << "Adding blank vectors for non-printed MOs " << i <<
778 // std::endl;
779 moEnd = static_cast<unsigned int>(MOs.size()) + nBasis;
780 for (unsigned int j = static_cast<unsigned int>(MOs.size()); j < moEnd;
781 j++)
782 MOs.push_back(0.0);
783 } else {
784 // std::cout << "Adding actual vector " << i << std::endl;
785 MOs.insert(MOs.end(), gukBasis.moVectors.at(i).begin(),
786 gukBasis.moVectors.at(i).end());
787 }
788 }
789
790 // Need to multiply by -1 to bring into accordance with Gaussian.
791 // for( unsigned int i=0; i <MOs.size(); i++ ) MOs.at(i)=MOs.at(i)*-1;
792
793 basis->addMOs(MOs);
794
795 // basis->initCalculation();
796
797 } // end load
798
799 } // End Namespace
800 }
801