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