1 /*
2 * (c) 2004 Iowa State University
3 * see the LICENSE file in the top level directory
4 */
5
6 /* Most text file parsing routines
7
8 1/1998 - Modified the GAMESS log file parsing code for the new format BMB
9 10/1998 - GAMESS log files also read in normal mode intensities BMB
10 11/1998 - Added MDL MolFile input/export code BMB
11 12/1998 - modified fragment parser routines BMB
12 8/2000 - Fixed log file parser for new MCSCF orbital header and new basis set format
13 1/2001 - Moved normal mode parser to Frame::ParseNormalModes BMB
14 1/2001 - Added exception class UserCancel to more cleanly handle Progress aborts BMB
15 2/2001 - Added check to allow user to disable the change of the creator type for text files BMB
16 9/2001 - Fixed initial fragment parser to account for change in GAMESS log file output BMB
17 11/2001 - ROHF logs now obtain the correct beta orbital occupation BMB
18 11/2001 - OpenGAMESSDRC updated for the modified header in DRC output BMB
19 3/2002 - Fixed bug when keywords appear in the Run Title BMB
20 3/2002 - Redid ReadControlOptions to remove any order dependance among keywords BMB
21 4/2002 - Modified initial fragment parser and fragment energy search BMB
22 5/2004 - Modified atomic label parsing to fix conflict between Zr/ZN and fragments BMB
23 10/2007 - Added import support for Molkel (.MKL) files ?/BMB/DMR
24 6/2008 - Added import support for MOPAC input (.MOP) and archive (.ARC) files DMR
25 */
26
27 #include "Files.h"
28 #include "Globals.h"
29 #include "GlobalExceptions.h"
30 #include "Progress.h"
31 #include "MoleculeData.h"
32 #include "Frame.h"
33 #include "Gradient.h"
34 #include "Internals.h"
35 #include "BasisSet.h"
36 #include "SurfaceTypes.h"
37 #include "BFiles.h"
38 #include "myFiles.h"
39 #ifndef __wxBuild__
40 #include "MyWindowClasses.h"
41 #include "MolDisplay.h"
42 #include "UtilWin.h"
43 #include "StdPrefsLib.h"
44 #else
45 #include "MolDisplayWin.h"
46 #endif
47 #include <iostream>
48
49 //#include "mat2quat.h"
50 #include "InputData.h"
51 #include "Prefs.h"
52 #include <string.h>
53 #include <string>
54 #include <stdio.h>
55 #include <cctype>
56 #include <fstream>
57 #include <iostream>
58 //using namespace std;
59 #include <new>
60
61 #if defined(WIN32)
62 #undef AddAtom
63 #endif
64
65 extern WinPrefs * gPreferences;
66
67 //Local function definitions
68 bool ReadGVBOccupancy(BufferFile * Buffer, long NumPairOrbs, long MaxOrbs, float * Occupancy);
69
WriteError(void)70 void FileError::WriteError(void) {
71 if (Error == eofErr)
72 wxLogMessage(_("Unexpected End Of File. Please check to make sure the file is complete."));
73 else {
74 wxString err;
75 err.Printf(_("File System related error. Please report error number %d."), (int) Error);
76 wxLogMessage(err);
77 }
78 }
79 /**
80 * Adds support for opening GAMESS Input (.INP) files.
81 * @param Buffer A BufferFileObject that the .INP or .inp file is buffered
82 * into to make parsing the file easier. See the BufferFile object for
83 * valid BufferFile operations.
84 */
OpenGAMESSInput(BufferFile * Buffer)85 long MolDisplayWin::OpenGAMESSInput(BufferFile * Buffer) {
86 char Line[kMaxLineLength], token[kMaxLineLength], DFTTYP[kMaxLineLength]="";
87 int scanerr;
88 long nAtoms;
89 wxFileOffset StartPos, EndPos;
90 bool BasisFound=false, BoolTest, EndOfGroup;
91
92 ProgressInd->ChangeText("Reading GAMESS input file...");
93
94 MainData->InputOptions = new InputData;
95
96 EndOfGroup = false;
97 if (Buffer->FindGroup("CONTRL")) {
98 do {
99 Buffer->GetLine(Line);
100 if (ReadStringKeyword(Line, "SCFTYP", token))
101 MainData->InputOptions->Control->SetSCFType(token);
102 if (ReadStringKeyword(Line, "RUNTYP", token))
103 MainData->InputOptions->Control->SetRunType(token);
104 if (ReadLongKeyword(Line, "MPLEVL", &nAtoms))
105 MainData->InputOptions->Control->SetMPLevel(nAtoms);
106 if (ReadStringKeyword(Line, "CITYP", token))
107 MainData->InputOptions->Control->SetCIType(token);
108 if (ReadStringKeyword(Line, "COORD", token))
109 MainData->InputOptions->Data->SetCoordType(token);
110 if (ReadStringKeyword(Line, "UNITS", token))
111 MainData->InputOptions->Data->SetUnits(token);
112 if (ReadLongKeyword(Line, "ICHARG", &nAtoms))
113 MainData->InputOptions->Control->SetCharge(nAtoms);
114 if (ReadStringKeyword(Line, "LOCAL", token))
115 MainData->InputOptions->Control->SetLocal(token);
116 if (ReadLongKeyword(Line, "MULT", &nAtoms))
117 MainData->InputOptions->Control->SetMultiplicity(nAtoms);
118 if (ReadLongKeyword(Line, "MAXIT", &nAtoms))
119 MainData->InputOptions->Control->SetMaxIt(nAtoms);
120 if (ReadStringKeyword(Line, "ECP", token))
121 MainData->InputOptions->Basis->SetECPPotential(token);
122 if (ReadStringKeyword(Line, "PP", token))
123 MainData->InputOptions->Basis->SetECPPotential(token);
124 //look for the DFTTYP keyword, but we must allow for reading the DFT group
125 //later before setting the functional since it depends on the method
126 ReadStringKeyword(Line, "DFTTYP", DFTTYP);
127 if (ReadLongKeyword(Line, "ISPHER", &nAtoms)) {
128 if (nAtoms == 1)
129 MainData->InputOptions->Control->UseSphericalHarmonics(true);
130 }
131 if (ReadLongKeyword(Line, "NOSYM", &nAtoms)) {
132 MainData->InputOptions->Data->SetUseSym((nAtoms==0));
133 }
134
135 if (-1 < FindKeyWord(Line, "$END", 4)) { //End of this group
136 //scan for multiple occurances of this group
137 if (!Buffer->FindGroup("CONTRL")) EndOfGroup = true;
138 }
139 } while (!EndOfGroup);
140 }
141 Buffer->SetFilePos(0); //restart search from beginning of file
142 EndOfGroup = false;
143 if (Buffer->FindGroup("BASIS")) {
144 BasisFound = true;
145 do {
146 Buffer->GetLine(Line);
147 if (ReadStringKeyword(Line, "GBASIS", token))
148 MainData->InputOptions->Basis->SetBasis(token);
149 if (ReadLongKeyword(Line, "NGAUSS", &nAtoms))
150 MainData->InputOptions->Basis->SetNumGauss(nAtoms);
151 if (ReadLongKeyword(Line, "NDFUNC", &nAtoms))
152 MainData->InputOptions->Basis->SetNumDFuncs(nAtoms);
153 if (ReadLongKeyword(Line, "NPFUNC", &nAtoms))
154 MainData->InputOptions->Basis->SetNumPFuncs(nAtoms);
155 if (ReadLongKeyword(Line, "NFFUNC", &nAtoms))
156 MainData->InputOptions->Basis->SetNumFFuncs(nAtoms);
157 if (ReadBooleanKeyword(Line, "DIFFS", &BoolTest))
158 MainData->InputOptions->Basis->SetDiffuseS(BoolTest);
159 if (ReadBooleanKeyword(Line, "DIFFSP", &BoolTest))
160 MainData->InputOptions->Basis->SetDiffuseSP(BoolTest);
161 if (ReadStringKeyword(Line, "POLAR", token))
162 MainData->InputOptions->Basis->SetPolar(token);
163
164 if (-1 < FindKeyWord(Line, "$END", 4)) { //End of this group
165 //scan for multiple occurances of this group
166 if (!Buffer->FindGroup("BASIS")) EndOfGroup = true;
167 }
168 } while (!EndOfGroup);
169 }
170 Buffer->SetFilePos(0); //restart search from beginning of file
171 EndOfGroup = false;
172 if (Buffer->FindGroup("SYSTEM")) {
173 do {
174 Buffer->GetLine(Line);
175 if (ReadLongKeyword(Line, "TIMLIM", &nAtoms))
176 MainData->InputOptions->System->SetTimeLimit(nAtoms);
177 if (ReadLongKeyword(Line, "MEMORY", &nAtoms))
178 MainData->InputOptions->System->SetMemory(nAtoms);
179 if (ReadLongKeyword(Line, "MEMDDI", &nAtoms))
180 MainData->InputOptions->System->SetMemDDI(nAtoms);
181 if (ReadBooleanKeyword(Line, "PARALL", &BoolTest))
182 MainData->InputOptions->System->SetParallel(BoolTest);
183 if (ReadLongKeyword(Line, "KDIAG", &nAtoms))
184 MainData->InputOptions->System->SetDiag(nAtoms);
185 if (ReadBooleanKeyword(Line, "COREFL", &BoolTest))
186 MainData->InputOptions->System->SetCoreFlag(BoolTest);
187 if (ReadStringKeyword(Line, "BALTYP", token)) {
188 nAtoms = FindKeyWord(token, "NXTVAL", 6);
189 if (nAtoms > -1)
190 MainData->InputOptions->System->SetBalanceType(true);
191 }
192 if (ReadBooleanKeyword(Line, "XDR", &BoolTest))
193 MainData->InputOptions->System->SetXDR(BoolTest);
194
195 if (-1 < FindKeyWord(Line, "$END", 4)) { //End of this group
196 //scan for multiple occurances of this group
197 if (!Buffer->FindGroup("SYSTEM")) EndOfGroup = true;
198 }
199 } while (!EndOfGroup);
200 }
201 Buffer->SetFilePos(0); //restart search from beginning of file
202 EndOfGroup = false;
203 if (Buffer->FindGroup("GUESS")) {
204 if (!MainData->InputOptions->Guess) MainData->InputOptions->Guess = new GuessGroup;
205 do {
206 Buffer->GetLine(Line);
207 if (ReadStringKeyword(Line, "GUESS", token))
208 MainData->InputOptions->Guess->SetGuess(token);
209 if (ReadLongKeyword(Line, "NORB", &nAtoms))
210 MainData->InputOptions->Guess->SetNumOrbs(nAtoms);
211 if (ReadBooleanKeyword(Line, "PRTMO", &BoolTest))
212 MainData->InputOptions->Guess->SetPrintMO(BoolTest);
213 if (ReadBooleanKeyword(Line, "MIX", &BoolTest))
214 MainData->InputOptions->Guess->SetMix(BoolTest);
215
216 if (-1 < FindKeyWord(Line, "$END", 4)) { //End of this group
217 //scan for multiple occurances of this group
218 if (!Buffer->FindGroup("GUESS")) EndOfGroup = true;
219 }
220 } while (!EndOfGroup);
221 }
222 Buffer->SetFilePos(0); //restart search from beginning of file
223 EndOfGroup = false;
224 if (Buffer->FindGroup("SCF")) {
225 if (!MainData->InputOptions->SCF) MainData->InputOptions->SCF = new SCFGroup;
226 do {
227 Buffer->GetLine(Line);
228 if (ReadBooleanKeyword(Line, "DIRSCF", &BoolTest))
229 MainData->InputOptions->SCF->SetDirectSCF(BoolTest);
230 if (ReadBooleanKeyword(Line, "FDIFF", &BoolTest))
231 MainData->InputOptions->SCF->SetFockDiff(BoolTest);
232 if (ReadLongKeyword(Line, "NCONV", &nAtoms))
233 MainData->InputOptions->SCF->SetConvergance(nAtoms);
234 if (ReadBooleanKeyword(Line, "UHFNOS", &BoolTest))
235 MainData->InputOptions->SCF->SetUHFNO(BoolTest);
236 if (ReadLongKeyword(Line, "NCO", &nAtoms))
237 MainData->InputOptions->SCF->SetGVBNumCoreOrbs(nAtoms);
238 if (ReadLongKeyword(Line, "NPAIR", &nAtoms))
239 MainData->InputOptions->SCF->SetGVBNumPairs(nAtoms);
240 if (ReadLongKeyword(Line, "NSETO", &nAtoms))
241 MainData->InputOptions->SCF->SetGVBNumOpenShells(nAtoms);
242 if (ReadStringKeyword(Line, "NO(1)", token)) {
243 int nchar = 0;
244 int tlen = strlen(token);
245 MainData->InputOptions->SCF->ClearGVBOpenShellDeg();
246 while (nchar < tlen) {
247 int nchar2=0;
248 long shellDeg;
249 if (sscanf(&(token[nchar]), "%ld%n", &shellDeg, &nchar2) == 1) {
250 nchar += nchar2+1;
251 MainData->InputOptions->SCF->AddGVBOpenShellDeg(shellDeg);
252 } else
253 break;
254 }
255 }
256 if (ReadStringKeyword(Line, "NPREO(1)", token)) { //npreo should have 2 or 4 integer elements
257 int nchar = 0;
258 int tlen = strlen(token);
259 int npreoValues=0;
260 MainData->InputOptions->SCF->ClearNPREOArray();
261 while (nchar < tlen) {
262 int nchar2=0;
263 long npreoVal;
264 if (sscanf(&(token[nchar]), "%ld%n", &npreoVal, &nchar2) == 1) {
265 nchar += nchar2+1;
266 MainData->InputOptions->SCF->AddNPREOValue(npreoVal);
267 npreoValues++;
268 } else
269 break;
270 }
271 if ((npreoValues!=2)&&(npreoValues!=4)) {
272 wxLogMessage(_T("Unexpected number of NPREO values encountered!"));
273 }
274 }
275
276 if (-1 < FindKeyWord(Line, "$END", 4)) { //End of this group
277 //scan for multiple occurances of this group
278 if (!Buffer->FindGroup("SCF")) EndOfGroup = true;
279 }
280 } while (!EndOfGroup);
281 }
282 Buffer->SetFilePos(0); //restart search from beginning of file
283 EndOfGroup = false;
284 if (Buffer->FindGroup("MP2")) {
285 if (!MainData->InputOptions->MP2) MainData->InputOptions->MP2 = new MP2Group;
286 do {
287 float tempf;
288 Buffer->GetLine(Line);
289 if (ReadLongKeyword(Line, "NACORE", &nAtoms))
290 MainData->InputOptions->MP2->SetNumCoreElectrons(nAtoms);
291 if (ReadBooleanKeyword(Line, "MP2PRP", &BoolTest))
292 MainData->InputOptions->MP2->SetMP2Prop(BoolTest);
293 if (ReadBooleanKeyword(Line, "LMOMP2", &BoolTest))
294 MainData->InputOptions->MP2->SetLMOMP2(BoolTest);
295 if (ReadLongKeyword(Line, "NWORD", &nAtoms))
296 MainData->InputOptions->MP2->SetMemory(nAtoms);
297 if (ReadLongKeyword(Line, "METHOD", &nAtoms))
298 MainData->InputOptions->MP2->SetMethod(nAtoms);
299 if (ReadStringKeyword(Line, "AOINTS", token))
300 MainData->InputOptions->MP2->SetAOIntMethod(token);
301 if (ReadFloatKeyword(Line, "CUTOFF", &tempf))
302 MainData->InputOptions->MP2->SetIntCutoff(tempf);
303
304 if (-1 < FindKeyWord(Line, "$END", 4)) { //End of this group
305 //scan for multiple occurances of this group
306 if (!Buffer->FindGroup("MP2")) EndOfGroup = true;
307 }
308 } while (!EndOfGroup);
309 }
310 Buffer->SetFilePos(0); //restart search from beginning of file
311 EndOfGroup = false;
312 if (Buffer->FindGroup("FORCE")) {
313 if (!MainData->InputOptions->Hessian) MainData->InputOptions->Hessian = new HessianGroup;
314 do {
315 float tempf;
316 Buffer->GetLine(Line);
317 if (ReadStringKeyword(Line, "METHOD", token))
318 MainData->InputOptions->Hessian->SetAnalyticMethod(
319 strncasecmp(token, "ANALYTIC", 8) == 0);
320 if (ReadLongKeyword(Line, "NVIB", &nAtoms))
321 MainData->InputOptions->Hessian->SetDoubleDiff(nAtoms==2);
322 if (ReadFloatKeyword(Line, "VIBSIZ", &tempf))
323 MainData->InputOptions->Hessian->SetDisplacementSize(tempf);
324 if (ReadBooleanKeyword(Line, "PURIFY", &BoolTest))
325 MainData->InputOptions->Hessian->SetPurify(BoolTest);
326 if (ReadBooleanKeyword(Line, "PRTIFC", &BoolTest))
327 MainData->InputOptions->Hessian->SetPrintFC(BoolTest);
328 if (ReadBooleanKeyword(Line, "VIBANL", &BoolTest))
329 MainData->InputOptions->Hessian->SetVibAnalysis(BoolTest);
330 if (ReadFloatKeyword(Line, "SCLFAC", &tempf))
331 MainData->InputOptions->Hessian->SetFreqScale(tempf);
332
333 if (-1 < FindKeyWord(Line, "$END", 4)) { //End of this group
334 //scan for multiple occurances of this group
335 if (!Buffer->FindGroup("FORCE")) EndOfGroup = true;
336 }
337 } while (!EndOfGroup);
338 }
339 Buffer->SetFilePos(0); //restart search from beginning of file
340 EndOfGroup = false;
341 if (Buffer->FindGroup("STATPT")) {
342 if (!MainData->InputOptions->StatPt) MainData->InputOptions->StatPt = new StatPtGroup;
343 do {
344 float tempf;
345 Buffer->GetLine(Line);
346 if (ReadFloatKeyword(Line, "OPTTOL", &tempf))
347 MainData->InputOptions->StatPt->SetOptConvergance(tempf);
348 if (ReadLongKeyword(Line, "NSTEP", &nAtoms))
349 MainData->InputOptions->StatPt->SetMaxSteps(nAtoms);
350 if (ReadStringKeyword(Line, "METHOD", token))
351 MainData->InputOptions->StatPt->SetMethod(token);
352 if (ReadFloatKeyword(Line, "DXMAX", &tempf))
353 MainData->InputOptions->StatPt->SetInitRadius(tempf);
354 if (ReadFloatKeyword(Line, "TRMAX", &tempf))
355 MainData->InputOptions->StatPt->SetMaxRadius(tempf);
356 if (ReadFloatKeyword(Line, "TRMIN", &tempf))
357 MainData->InputOptions->StatPt->SetMinRadius(tempf);
358 if (ReadLongKeyword(Line, "IFOLOW", &nAtoms))
359 MainData->InputOptions->StatPt->SetModeFollow(nAtoms);
360 if (ReadBooleanKeyword(Line, "STPT", &BoolTest))
361 MainData->InputOptions->StatPt->SetStatPoint(BoolTest);
362 if (ReadFloatKeyword(Line, "STSTEP", &tempf))
363 MainData->InputOptions->StatPt->SetStatJump(tempf);
364 if (ReadLongKeyword(Line, "IHREP", &nAtoms))
365 MainData->InputOptions->StatPt->SetHessRecalcInterval(nAtoms);
366 if (ReadLongKeyword(Line, "NPRT", &nAtoms))
367 MainData->InputOptions->StatPt->SetAlwaysPrintOrbs(nAtoms==1);
368 if (ReadStringKeyword(Line, "HESS", token))
369 MainData->InputOptions->StatPt->SetHessMethod(token);
370
371 if (-1 < FindKeyWord(Line, "$END", 4)) { //End of this group
372 //scan for multiple occurances of this group
373 if (!Buffer->FindGroup("STATPT")) EndOfGroup = true;
374 }
375 } while (!EndOfGroup);
376 }
377 Buffer->SetFilePos(0); //restart search from beginning of file
378 EndOfGroup = false;
379 if (Buffer->FindGroup("DFT")) {
380 do {
381 Buffer->GetLine(Line);
382 if (ReadStringKeyword(Line, "METHOD", token))
383 MainData->InputOptions->DFT.SetMethodGrid(
384 strncasecmp(token, "GRIDFREE", 8) != 0);
385
386 if (-1 < FindKeyWord(Line, "$END", 4)) { //End of this group
387 //scan for multiple occurances of this group
388 if (!Buffer->FindGroup("DFT")) EndOfGroup = true;
389 }
390 } while (!EndOfGroup);
391 }
392 //Now can save the functional that is read from the contrl group
393 if (strlen(DFTTYP) > 0) {
394 MainData->InputOptions->DFT.SetFunctional(DFTTYP);
395 if (MainData->InputOptions->DFT.GetFunctional() > 0)
396 MainData->InputOptions->Control->UseDFT(true);
397 else
398 wxLogMessage(_("Unknown DFTTYP detected, ignored."));
399 }
400
401 Buffer->SetFilePos(0); //restart search from beginning of file
402 EndOfGroup = false;
403 if (Buffer->FindGroup("FMO")) {
404 MainData->InputOptions->FMO.FMOActive(true);
405 do {
406 Buffer->GetLine(Line);
407 if (ReadLongKeyword(Line, "NFRAG", &nAtoms))
408 MainData->InputOptions->FMO.SetNumberFragments(nAtoms);
409 //The rest of the items in this group depend on the # of atoms so parse them after the coordinates
410
411 if (-1 < FindKeyWord(Line, "$END", 4)) { //End of this group
412 //scan for multiple occurances of this group
413 if (!Buffer->FindGroup("FMO")) EndOfGroup = true;
414 }
415 } while (!EndOfGroup);
416 }
417 float unitConversion = 1.0f;
418 if (MainData->InputOptions->Data->GetUnits()) unitConversion = kBohr2AngConversion;
419 Buffer->SetFilePos(0); //restart search from beginning of file
420 Frame * lFrame = MainData->GetCurrentFramePtr();
421 if (Buffer->FindGroup("DATA")) {
422 Buffer->SkipnLines(1);
423 Buffer->GetLine(Line); //1st line is a title line
424 MainData->InputOptions->Data->SetTitle(Line, strlen(Line));
425 Buffer->GetLine(Line); //2nd line contains the point group
426 if (FindKeyWord(Line, "$END", 4) < 0) { // Make sure we're not at $END
427 scanerr = sscanf(Line, "%s %ld", token, &nAtoms);
428 MainData->InputOptions->Data->SetPointGroup(token);
429 if (scanerr == 2) //if a number was read in set the order
430 MainData->InputOptions->Data->SetPointGroupOrder(nAtoms);
431 //If !C1 then skip the blank line well I guess rarely it isn't blank...
432 if (-1 == FindKeyWord(token, "C1", 2)) Buffer->SkipnLines(1);
433 StartPos = Buffer->GetFilePos();
434 if (!Buffer->LocateKeyWord("$END", 4)) throw DataError();
435 EndPos = Buffer->GetFilePos() - 1;
436 Buffer->SetFilePos(StartPos);
437 nAtoms = Buffer->GetNumLines(EndPos - StartPos);
438 if (MainData->InputOptions->FMO.IsFMOActive()) nAtoms=0; //FMO coordinates are in $FMOXYZ
439 if (nAtoms > 0) {
440 if (MainData->InputOptions->Data->GetCoordType() <= CartesianCoordType) {
441 if (!MainData->SetupFrameMemory(nAtoms, 0)) throw MemoryError();
442 while (Buffer->GetFilePos() < EndPos) {
443 CPoint3D pos;
444 float AtomType=-1;
445 Buffer->GetLine(Line);
446 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
447 { throw UserCancel();}
448 pos.x = pos.y = pos.z = 0.0f;
449 int linecount = sscanf(Line, "%s %f %f %f %f", token, &AtomType, &pos.x, &pos.y, &pos.z);
450 pos *= unitConversion;
451 if ((linecount!=5)||(AtomType<1)) {
452 wxString msg;
453 msg.Printf(_("Warning: Parsing issue with the line: %s"), Line);
454 wxLogMessage(msg);
455 }
456 lFrame->AddAtom((long) AtomType, pos);
457 StartPos = Buffer->FindBlankLine();
458 if ((StartPos <= EndPos)&&(StartPos>-1)) { //basis set is inlined in $DATA
459 Buffer->SetFilePos(StartPos); //just skip over it
460 Buffer->SkipnLines(1);
461 }
462 }
463 if (((MainData->InputOptions->Data->GetCoordType() == UniqueCoordType)||
464 (MainData->InputOptions->Data->GetCoordType() == 0))&&
465 (MainData->InputOptions->Data->GetPointGroup()>GAMESS_C1)&&
466 (lFrame->GetNumAtoms() > 0)) {
467 //Generate symmetry dependant atoms
468 for (int i=0; i<lFrame->GetNumAtoms(); ++i)
469 lFrame->Atoms[i].IsSymmetryUnique(true);
470 MainData->GenerateSymmetryDependentAtoms();
471 }
472 } else if (MainData->InputOptions->Data->GetCoordType() <= ZMTCoordType) {
473 wxFileOffset bPos = Buffer->FindBlankLine();
474 if ((bPos > 0)&&(bPos < EndPos)) {
475 nAtoms = Buffer->GetNumLines(bPos - StartPos);
476 }
477 if (nAtoms > 0) {
478 if (!MainData->SetupFrameMemory(nAtoms, 0)) throw MemoryError();
479 } else {
480 wxLogMessage(_("No atoms found in your $DATA group!"));
481 throw DataError();
482 }
483 MainData->ParseZMatrix(Buffer, nAtoms, Prefs);
484 } else if (MainData->InputOptions->Data->GetCoordType() <= ZMTMPCCoordType) {
485 if (nAtoms > 0) {
486 if (!MainData->SetupFrameMemory(nAtoms, 0)) throw MemoryError();
487 } else {
488 wxLogMessage(_("No atoms found in your $DATA group!"));
489 throw DataError();
490 }
491 MainData->ParseMOPACZMatrix(Buffer, nAtoms, Prefs);
492 }
493 if (Prefs->GetAutoBond()) //setup bonds, if needed
494 lFrame->SetBonds(Prefs, false, ProgressInd);
495 }
496 }
497 }
498 Buffer->SetFilePos(0); //restart search from beginning of file
499 if (MainData->InputOptions->FMO.IsFMOActive() && Buffer->FindGroup("FMOXYZ")) {
500 Buffer->SkipnLines(1);
501 StartPos = Buffer->GetFilePos();
502 if (!Buffer->LocateKeyWord("$END", 4)) throw DataError();
503 EndPos = Buffer->GetFilePos() - 1;
504 Buffer->SetFilePos(StartPos);
505 nAtoms = Buffer->GetNumLines(EndPos - StartPos);
506 if (nAtoms > 0) {
507 ProgressInd->ChangeText("Reading FMO Coordinates...");
508 if (!MainData->SetupFrameMemory(nAtoms, 0)) throw MemoryError();
509 while (Buffer->GetFilePos() < EndPos) {
510 CPoint3D pos;
511 float AtomType=-1;
512 char token2[kMaxLineLength];
513 Buffer->GetLine(Line);
514 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
515 { throw UserCancel();}
516 pos.x = pos.y = pos.z = 0.0f;
517 //The form is token (skip) atomic charge or symbol, x y z coords
518 int linecount = sscanf(Line, "%s %s %f %f %f", token, token2, &pos.x, &pos.y, &pos.z);
519 int inum = 1;
520 if (isdigit(token2[0])) inum = sscanf(token2, "%f", &AtomType);
521 else AtomType = SetAtomType((unsigned char *) token2);
522 if ((linecount!=5)||(AtomType<1)) {
523 wxString msg;
524 msg.Printf(_("Warning: Parsing issue with the line: %s"), Line);
525 wxLogMessage(msg);
526 }
527 pos *= unitConversion;
528 lFrame->AddAtom((long) AtomType, pos);
529 }
530 if (Prefs->GetAutoBond()) { //setup bonds, if needed
531 lFrame->SetBonds(Prefs, false, ProgressInd);
532 }
533 }
534 }
535 Buffer->SetFilePos(0); //restart search from beginning of file
536 if (Buffer->FindGroup("EFRAG")) {
537 Buffer->SkipnLines(1);
538 Buffer->GetLine(Line); //1st line has all of the options
539 if (ReadStringKeyword(Line, "METHOD", token)) {
540 MainData->InputOptions->EFP.SetCoordinatesType(token);
541 }
542 if (ReadStringKeyword(Line, "POLMETHD", token)) {
543 MainData->InputOptions->EFP.SetPolMethod(token);
544 }
545 if (ReadStringKeyword(Line, "POSITION", token)) {
546 MainData->InputOptions->EFP.SetPositionType(token);
547 }
548 long tag;
549 if (ReadLongKeyword(Line, "COORD", &tag))
550 MainData->InputOptions->EFP.SetMaxMOs(tag);
551 if (ReadLongKeyword(Line, "MXBF", &tag))
552 MainData->InputOptions->EFP.SetMaxBasisFunctions(tag);
553 if (ReadLongKeyword(Line, "NBUFFMO", &tag))
554 MainData->InputOptions->EFP.SetNumBufferMOs(tag);
555
556 wxFileOffset former_pos, start_pos, found_it;
557 //Now tackle the individual fragment definitions
558 //These should consist of 4 line blocks of Fragname=xxx followed by three atom lines
559 //For now I am only going to deal with cartesian coordinates
560 if (MainData->InputOptions->EFP.UseCartesianCoordinates()) {
561 mpAtom *atm;
562 CPoint3D dst_locs[3];
563 CPoint3D pos;
564 int fstart;
565 int match[3] = {0, 0, 0};
566 CPoint3D src_locs[3];
567 std::string labels[3];
568 long fragNum;
569 int i;
570 CPoint3D new_pos;
571 CPoint3D rot_pos;
572 CPoint3D curr_pos;
573 CPoint3D orig;
574 Matrix4D vec2vec;
575 CPoint3D src_vec;
576 CPoint3D dst_vec;
577 CPoint3D dst_vec2;
578 CPoint3D dst_norm;
579 CPoint3D mid_norm;
580 CPoint3D mid_vec1, mid_vec2;
581 float dot;
582
583 Buffer->GetLine(Line);
584 while (ReadStringKeyword(Line, "FRAGNAME", token)) {
585 if (!strcasecmp(token, "H2ORHF") || !strcasecmp(token, "H2ODFT")) { //builtin EFP1 style is limited to H2O with known labels
586 MainData->FragmentNames.push_back(std::string(token));
587 long fragNum = MainData->FragmentNames.size();
588 CPoint3D pos;
589 int AtomType;
590 for (int i=0; i<3; ++i) {
591 AtomType = -1;
592 Buffer->GetLine(Line);
593 //lines have format "label x, y, z"
594 sscanf(Line, "%s %f %f %f", token, &pos.x, &pos.y, &pos.z);
595 pos *= unitConversion;
596 if (!strcasecmp(token, "O1")) AtomType = 8;
597 else if (!strcasecmp(token, "H2")||!strcasecmp(token, "H3")) AtomType = 1;
598 if (AtomType > 0) {
599 mpAtom * atm = lFrame->AddAtom(AtomType, pos);
600 atm->SetFragmentNumber(fragNum);
601 }
602 }
603 }
604
605 // Custom fragment type.
606 else {
607
608 // Read the three atoms that setup the fragment. These
609 // should be in angstroms.
610 MainData->FragmentNames.push_back(std::string(token));
611 fragNum = MainData->FragmentNames.size();
612 char label[kMaxLineLength];
613 for (i = 0; i < 3; ++i) {
614 Buffer->GetLine(Line);
615 sscanf(Line, "%s %f %f %f", label,
616 &(dst_locs[i].x), &(dst_locs[i].y),
617 &(dst_locs[i].z));
618 dst_locs[i] *= unitConversion;
619 labels[i] = label;
620 /* std::cout << "Line: " << Line << std::endl; */
621 /* atm = lFrame->AddAtom(1, dst_locs[i]); */
622 /* atm->SetFragmentNumber(fragNum); */
623 }
624
625 // See if the fragment template has been loaded in already.
626 // If so, go ahead and parse it.
627 std::map<std::string, EFrag>::iterator frag;
628 frag = MainData->efrags.find(token);
629 if (frag == MainData->efrags.end()) {
630 // save current position
631 former_pos = Buffer->GetFilePos();
632
633 // look for fragment definition
634 found_it = Buffer->FindGroup(token);
635 if (!found_it) {
636 std::cout << "didn't find group " << token << std::endl;
637 wxString msg;
638 msg.Printf(_("Unable to locate correct EFP2 fragment definition group named %s"), token);
639 wxLogMessage(msg);
640 throw DataError();
641 }
642 start_pos = Buffer->GetFilePos();
643
644 // get definition text
645 std::string running_text;
646 Buffer->GetLine(Line);
647 while (FindKeyWord(Line, "$END", 4) < 0) {
648 running_text += Line;
649 running_text += "\n";
650 Buffer->GetLine(Line);
651 }
652 running_text += Line;
653
654 // restore file position
655 Buffer->SetFilePos(former_pos);
656
657 // get text
658 MainData->efrags.insert(std::pair<std::string, EFrag>(token, EFrag(running_text)));
659 frag = MainData->efrags.find(token);
660 }
661
662 fstart = lFrame->NumAtoms;
663 const std::vector<EFragAtom>& labeled_atoms = frag->second.GetAtoms();
664 std::vector<EFragAtom>::const_iterator efrag_atom;
665
666 for (efrag_atom = labeled_atoms.begin();
667 efrag_atom != labeled_atoms.end();
668 ++efrag_atom) {
669
670 if (efrag_atom->GetLabel().compare(labels[0]) == 0) {
671 match[0] = lFrame->NumAtoms;
672 src_locs[0] = efrag_atom->GetCoords();
673 } else if (efrag_atom->GetLabel().compare(labels[1]) == 0) {
674 match[1] = lFrame->NumAtoms;
675 src_locs[1] = efrag_atom->GetCoords();
676 } else if (efrag_atom->GetLabel().compare(labels[2]) == 0) {
677 match[2] = lFrame->NumAtoms;
678 src_locs[2] = efrag_atom->GetCoords();
679 }
680
681 atm = lFrame->AddAtom(efrag_atom->GetAtomicNumber(),
682 efrag_atom->GetCoords());
683 atm->SetFragmentNumber(fragNum);
684 }
685
686 // We first find a rotation that one will align a vector
687 // in the fragment template to the corresponding vector in
688 // the destination space.
689 dst_vec = dst_locs[1] - dst_locs[0];
690 Normalize3D(&dst_vec);
691
692 src_vec = src_locs[1] - src_locs[0];
693 Normalize3D(&src_vec);
694
695 SetRotationMatrix(vec2vec, &src_vec, &dst_vec);
696
697 // The common vector now serves as an axis of rotation. We
698 // need to rotate the fragment template plane so that it
699 // coincides with the destination plane. The angle of rotation
700 // can be determined by the angle between the two planes'
701 // normals.
702 lFrame->GetAtomPosition(match[0], orig);
703 Rotate3DOffset(vec2vec, src_locs[1] - orig, &mid_vec1);
704 Rotate3DOffset(vec2vec, src_locs[2] - orig, &mid_vec2);
705 UnitCrossProduct3D(&mid_vec1, &mid_vec2, &mid_norm);
706
707 dst_vec2 = dst_locs[2] - dst_locs[0];
708 UnitCrossProduct3D(&dst_vec, &dst_vec2, &dst_norm);
709
710 Matrix4D tri2tri;
711 dot = DotProduct3D(&mid_norm, &dst_norm);
712
713 // Technically, the axis of rotation (the aligned vector)
714 // might be facing a different direction than we think it
715 // is. To be consistent, we instead use the axis that is
716 // normal to both planes' normals. It points in the same
717 // or opposite direction as dst_vec.
718 CPoint3D axis;
719 UnitCrossProduct3D(&mid_norm, &dst_norm, &axis);
720 RotateAroundAxis(tri2tri, axis, acos(dot) * 180.0 / kPi);
721
722 // We concatenate the two rotation matrices.
723 Matrix4D transform;
724 MultiplyMatrix(vec2vec, tri2tri, transform);
725
726 // Okay, for each atom we added for this fragment instance,
727 // we move all fragment atoms into destination space. We
728 // translate to make the base fragment atom the origin and
729 // then rotate to align the fragment with the destination
730 // plane, and then translate by the base destination atom.
731 for (long i = fstart; i < lFrame->NumAtoms; ++i) {
732 lFrame->GetAtomPosition(i, curr_pos);
733 new_pos = curr_pos - orig;
734 Rotate3DOffset(transform, new_pos, &rot_pos);
735 new_pos = rot_pos + dst_locs[0];
736 lFrame->SetAtomPosition(i, new_pos);
737 }
738 }
739
740 Buffer->GetLine(Line);
741 //At some point GAMESS started printing out all fragment atoms instead of the first three,
742 //since the code above has already properly obtained the full fixed fragment geometry just
743 //skip the user provided set which could be incorrect.
744 while (((0>FindKeyWord(Line, "FRAGNAME", 8))&&(0>FindKeyWord(Line, "$END", 4)))) {
745 Buffer->GetLine(Line);
746 }
747 }
748 }
749
750 lFrame->SetBonds(Prefs, true, NULL, false);
751
752 }
753 if (MainData->InputOptions->FMO.IsFMOActive()) {
754 Buffer->SetFilePos(0); //restart search from beginning of file
755 if (Buffer->FindGroup("FMO")) {
756 wxFileOffset startFMO = Buffer->GetFilePos();
757 wxFileOffset EndOfGroup;
758 if (Buffer->LocateKeyWord("$END", 4)) {
759 EndOfGroup = Buffer->GetFilePos();
760 } else {
761 EndOfGroup = -1;
762 wxLogMessage(_("The FMO group does not have proper termination."));
763 }
764 Buffer->SetFilePos(startFMO);
765 //Parse the items that depend on the # of atoms
766 //The rest of the items in this group depend on the # of atoms so parse them after the coordinates
767
768 if (Buffer->LocateKeyWord("INDAT", 5, EndOfGroup)) {
769 MainData->ParseFMOIds(Buffer, lFrame->GetNumAtoms(), EndOfGroup);
770 }
771 }
772 }
773 return 1;
774 }
775 /**
776 * Parses the MDL Mol Format (just atoms).
777 * @param Buffer A BufferFileObject which the MDL mol file is buffered into
778 * @return Returns 1 upon open success or 0 on error or failure to open
779 */
OpenMDLMolFile(BufferFile * Buffer)780 long MolDisplayWin::OpenMDLMolFile(BufferFile * Buffer) {
781 char Line[kMaxLineLength], partA[16], partB[16], partC[16];
782 long nAtoms, nBonds;
783 short scanerr;
784 // parts of this are a bit gross since the MDL format is fixed format without
785 // whitespace in between the fields.
786
787 ProgressInd->ChangeText("Reading MDL MolFile...");
788 Frame * lFrame = MainData->cFrame;
789
790 Buffer->GetLine(Line); //The first Line is a comment/compound name line
791 MainData->SetDescription(Line);
792 Buffer->GetLine(Line); //The second line can (optionally) contain program and energy data
793 long LineLength = strlen(Line);
794 if (LineLength > 34) {
795 double energy;
796 if (1==sscanf(&(Line[34]), "%lf", &energy))
797 lFrame->Energy = energy;
798 }
799 Buffer->SkipnLines(1); //third line for comments (unused here)
800 Buffer->GetLine(Line); //atom/bond counts
801 partA[0] = Line[0]; partA[1] = Line[1]; partA[2]=Line[2]; partA[3]='\0';
802 partB[0] = Line[3]; partB[1] = Line[4]; partB[2]=Line[5]; partB[3]='\0';
803 scanerr = sscanf(partA, "%3ld", &nAtoms);
804 scanerr += sscanf(partB, "%3ld", &nBonds);
805 if (scanerr!=2 || nAtoms <= 0) {
806 wxLogMessage(_("Error parsing MDL MolFile."));
807 throw DataError();
808 }
809 MainData->SetupFrameMemory(nAtoms, nBonds);
810 long i;
811 for (i=0; i<nAtoms; ++i) {
812 CPoint3D tPt;
813 char token[5];
814 //Atom line format: "%10f%10f%10f %3s"
815 Buffer->GetLine(Line);
816 for (int i=0; i<10; ++i) partA[i] = Line[i];
817 partA[10] = '\0';
818 scanerr = sscanf(partA, "%10f", &tPt.x);
819 for (int i=0; i<10; ++i) partB[i] = Line[i+10];
820 partB[10] = '\0';
821 scanerr += sscanf(partB, "%10f", &tPt.y);
822 for (int i=0; i<10; ++i) partC[i] = Line[i+20];
823 partC[10] = '\0';
824 scanerr += sscanf(partC, "%10f", &tPt.z);
825 scanerr += sscanf(&(Line[31]), "%3s", token);
826 if (scanerr == 4) {
827 long AtomType;
828 AtomType = SetAtomType((unsigned char *) token);
829 lFrame->AddAtom(AtomType, tPt);
830 } else break;
831 }
832 if (i==nAtoms && nBonds > 0) { //Read in bonds if all atom were read successfully
833 for (i=0; i<nBonds; ++i) {
834 long type, a1, a2;
835 Buffer->GetLine(Line); //Bonds format: "%3ld%3ld%3ld"
836 partA[0] = Line[0]; partA[1] = Line[1]; partA[2]=Line[2]; partA[3]='\0';
837 partB[0] = Line[3]; partB[1] = Line[4]; partB[2]=Line[5]; partB[3]='\0';
838 partC[0] = Line[6]; partC[1] = Line[7]; partC[2]=Line[8]; partC[3]='\0';
839 scanerr = sscanf(partA, "%3ld", &a1);
840 scanerr += sscanf(partB, "%3ld", &a2);
841 scanerr += sscanf(partC, "%3ld", &type);
842 if (scanerr == 3 && a1>0 && a2>0 && a1<=nAtoms && a2<=nAtoms && a1!=a2) {
843 lFrame->AddBond(a1-1, a2-1);
844 if (type>3) type = 1;
845 if (type<1) type = 1;
846 lFrame->SetBondOrder(lFrame->GetNumBonds()-1, (BondOrder) type);
847 } else break;
848 }
849 }
850
851 return 1;
852 }
853 /**
854 * Parses the Protein Databank Format (just atoms).
855 * @param Buffer A BufferFileObject which the PDB file is buffered into
856 * @return Returns 1 upon open success or 0 on error or failure to open
857 */
OpenPDBFile(BufferFile * Buffer)858 long MolDisplayWin::OpenPDBFile(BufferFile * Buffer) {
859 char Line[kMaxLineLength];
860 long nAtoms, nModels = 0;
861 short scanerr;
862
863 ProgressInd->ChangeText("Reading PDB file...");
864 Frame * lFrame = MainData->cFrame;
865 //First scan the file to determine the atoms
866 nAtoms = 0;
867 while (Buffer->GetFilePos() < Buffer->GetFileLength()) {
868 Buffer->GetLine(Line);
869 if (0==FindKeyWord(Line, "MODEL", 5)) ++nModels;
870 if (0==FindKeyWord(Line, "ATOM", 4)) ++nAtoms;
871 if (0==FindKeyWord(Line, "HETATM", 4)) ++nAtoms;
872 }
873 Buffer->SetFilePos(0);
874 if (nAtoms>0) {
875 //allocate memory for the atoms
876 if (!MainData->SetupFrameMemory(nAtoms, 0)) throw MemoryError();
877
878 CPoint3D Pos;
879 long AtomType, LinePos;
880 nAtoms = 0;
881 //Scan for Atom or hetAtm lines
882 //Format is: a6,i5,2x,a4,a3,2x,i4,4x,3F8.3,2f6.2
883 //1 - 6 Record name "ATOM "
884 //7 - 11 Integer serial Atom serial number.
885 //13 - 16 Atom name Atom name.
886 //17 Character altLoc Alternate location indicator.
887 //18 - 20 Residue name resName Residue name.
888 //22 Character chainID Chain identifier.
889 //23 - 26 Integer resSeq Residue sequence number.
890 //27 AChar iCode Code for insertion of residues.
891 //31 - 38 Real(8.3) x Orthogonal coordinates for X in Angstroms.
892 //39 - 46 Real(8.3) y Orthogonal coordinates for Y in Angstroms.
893 //47 - 54 Real(8.3) z Orthogonal coordinates for Z in Angstroms.
894 //55 - 60 Real(6.2) occupancy Occupancy.
895 //61 - 66 Real(6.2) tempFactor Temperature factor.
896 //77 - 78 LString(2) element Element symbol, right-justified.
897 //79 - 80 LString(2) charge Charge on the atom.
898 //This routine only parses simple pdb files. It probably gets many files atom types wrong
899 //and it always reads in all atoms including duplicates
900 while (Buffer->GetFilePos() < Buffer->GetFileLength()) {
901 Buffer->GetLine(Line);
902 int LineLength = strlen(Line);
903 //Only read in the first model in a file
904 if (0==FindKeyWord(Line, "ENDMDL", 6)) {
905 bool modelFound=false;
906 while (Buffer->GetFilePos() < Buffer->GetFileLength()) {
907 Buffer->GetLine(Line);
908 if (0==FindKeyWord(Line, "MODEL", 5)) {
909 modelFound = true;
910 break;
911 }
912 }
913 if (!modelFound) break;
914 if (Prefs->GetAutoBond()) //setup bonds, if needed
915 lFrame->SetBonds(Prefs, false, ProgressInd);
916 lFrame = MainData->AddFrame(lFrame->GetNumAtoms(), lFrame->GetNumBonds());
917 }
918 long atomTest = FindKeyWord(Line, "ATOM", 4);
919 long HetTest = FindKeyWord(Line, "HETATM", 4);
920 if ((0==atomTest)||(0==HetTest)) {
921 AtomType = -1;
922 if (LineLength >= 78) { //Use the element symbol if present
923 unsigned char label[4];
924 bool test=false;
925 if (isalpha(Line[76])) {
926 label[0] = Line[76];
927 label[1] = Line[77];
928 label[2] = '\0';
929 test = true;
930 } else if (isalpha(Line[77])) {
931 label[0] = Line[77];
932 label[1] = '\0';
933 test = true;
934 }
935 if (test)
936 AtomType = SetAtomType(label);
937 }
938 if (AtomType <= 0) {//If no symbol attempt to use the "name"
939 LinePos = 13;
940 if (atomTest==0) Line[14] = ' ';
941 else if (Line[12] != ' ') LinePos = 12;
942 AtomType = SetAtomType((unsigned char *) &(Line[LinePos]));
943 }
944 if (AtomType > 0) {
945 scanerr = sscanf(&(Line[30]), "%8e%8e%8e", &(Pos.x), &(Pos.y), &(Pos.z));
946 if (scanerr == 3) {
947 lFrame->AddAtom(AtomType, Pos);
948 MainData->MaxSize = MAX(MainData->MaxSize, fabs(Pos.x));
949 MainData->MaxSize = MAX(MainData->MaxSize, fabs(Pos.y));
950 MainData->MaxSize = MAX(MainData->MaxSize, fabs(Pos.z));
951 ++nAtoms;
952 }
953 }
954 }
955 }
956 if (Prefs->GetAutoBond()) //setup bonds, if needed
957 lFrame->SetBonds(Prefs, false, ProgressInd);
958 }
959 return 1;
960 }
961
962 /**
963 * Adds support for opening the MKL file extension.
964 * @param Buffer A BufferFileObject which the .MKL file is buffered into
965 * to make parsing the file easier. See the BufferFile object for valid
966 * BufferFile operations.
967 * @return Returns 1 upon open success or 0 on error or failure to open
968 */
OpenMKLFile(BufferFile * Buffer)969 long MolDisplayWin::OpenMKLFile(BufferFile * Buffer){
970 // buffer line for text to be scanned while parsing
971 char Line[kMaxLineLength];
972 // number of atomes in the structure described by this file
973 long nAtoms = 0;
974 // Placeholders for traversing file sections in Buffer
975 wxFileOffset startOfSection = 0;
976 wxFileOffset endOfSection = -1;
977 // counters for line-by-line text input:
978 // # of tokens sucessfully read in a sscanf call, # bytes total in line,
979 // current position in line, and the # of bytes read through one sscanf call
980 int scanCount, lineBytes, bytesRead, bytesConsumed;
981 // flags to indicate $KEYWORD section completion and order-of-dependency
982 // following. Also used to enforce data parsing in-order (doesn't guarantee
983 // that the file's data was in-order, only that it is parsed in-order)
984 bool BasisDone = false, CoefAlphaDone = false, CoefBetaDone = false;
985 bool OccAlphaDone = false, OccBetaDone = false;
986
987 ProgressInd->ChangeText("Reading MKL file...");
988 Frame * lFrame = MainData->cFrame;
989 // first scan the file to determine the number of atoms
990 //look throughout the file for the $COORD or the last $$
991 //and count the number of lines between the two keywords
992 //(each line is another atom in the molecule)
993 while (Buffer->GetFilePos() < Buffer->GetFileLength()
994 && Buffer->LocateKeyWord("$COORD", 6)) {
995 Buffer->SkipnLines(1); // skip $COORD line
996 startOfSection = Buffer->GetFilePos();
997 if (Buffer->LocateKeyWord("$END", 4)) {
998 endOfSection = Buffer->GetFilePos();
999 Buffer->SetFilePos(startOfSection);
1000 } else endOfSection = Buffer->GetFileSize();
1001 while (Buffer->GetFilePos() < endOfSection) {
1002 wxFileOffset startOfFramePos = Buffer->GetFilePos();
1003 wxFileOffset endOfFramePos = endOfSection;
1004 //individual geometries are separated by the "$$" line
1005 if (Buffer->LocateKeyWord("$$", 2, endOfSection)) {
1006 endOfFramePos = Buffer->GetFilePos();
1007 Buffer->SetFilePos(startOfFramePos);
1008 }
1009 nAtoms = (long) Buffer->GetNumLines(endOfFramePos);
1010 if (lFrame->GetNumAtoms()>0)
1011 lFrame = MainData->AddFrame(nAtoms, 0);
1012 for (long i=0; i<nAtoms; ++i) {
1013 CPoint3D Pos;
1014 long AtomType;
1015 if (Buffer->GetFilePos() >= endOfFramePos) {
1016 nAtoms = i;
1017 break;
1018 }
1019 Buffer->GetLine(Line);
1020 //parse line for atom type and x,y,z positions
1021 scanCount = sscanf(Line,"%ld %f %f %f",&AtomType,&Pos.x,&Pos.y,&Pos.z);
1022 if (scanCount == 0) {
1023 nAtoms = i;
1024 break;
1025 }
1026 if (scanCount != 4) {
1027 MessageAlert("Error while reading coordinates.");
1028 return 0;
1029 }
1030 //add atom to the molecule
1031 lFrame->AddAtom(AtomType, Pos);
1032 }
1033 if (Buffer->GetFilePos() < endOfSection) Buffer->SkipnLines(1);
1034 //setup bonds, if needed
1035 if (Prefs->GetAutoBond() && (nAtoms > 0))
1036 lFrame->SetBonds(Prefs, false, ProgressInd);
1037 }
1038 } // Coords done
1039
1040 // now look for Basis data
1041 if ((0<lFrame->GetNumAtoms())&&(Buffer->LocateKeyWord("$BASIS", 6))) {
1042 bool error = false;
1043 // totals counters
1044 unsigned long nShells = 0, linesInBasis = 0;
1045 // other counters; may be set to -1 as a reset to offset an increment
1046 // thus placing back at 0 for a subsequent iteration
1047 long iShell = 0, iAtom = 0, shellsPeriAtom = 0;
1048 // temp vars for line-at-a-time read
1049 long nFunc;
1050 char IType[5];
1051 float Sc;
1052 Buffer->SkipnLines(1);
1053 startOfSection = Buffer->GetFilePos();
1054
1055 // count total number of shells in Basis section by counting
1056 // the number of lines formatted according to the sscanf below
1057 while ((Buffer->GetFilePos()<Buffer->GetFileSize())) {
1058 Buffer->GetLine(Line);
1059 ++linesInBasis;
1060 // continue until we find the end of the group / start of next
1061 if (FindKeyWord(Line, "$END", 4)<0 && FindKeyWord(Line, "$COEFF", 6)<0
1062 && FindKeyWord(Line, "$OCC", 4)<0) {
1063 lineBytes = strlen(Line);
1064 bytesRead = 0;
1065 while (bytesRead < lineBytes) {
1066 scanCount = sscanf(&(Line[bytesRead]), "%ld %4[lLsSpPdDfF] %f%n",
1067 &nFunc, IType, &Sc, &bytesConsumed);
1068 if (scanCount == 3) {
1069 bytesRead+=bytesConsumed;
1070 ++nShells;
1071 } else
1072 break;
1073 }
1074 }
1075 else // end of group has been determined
1076 break;
1077 }
1078
1079 // Now that shells are counted, we can create the BasisSet and parse data
1080 MainData->Basis = new BasisSet(nAtoms, nShells);
1081 if (MainData->Basis == NULL) error = true;
1082
1083 // go back to the line right after $BASIS so we can parse the data
1084 Buffer->SetFilePos(startOfSection);
1085 // reiterate through Basis section to get and save BasisSet data
1086 while (iShell < nShells && iAtom < nAtoms && !error) {
1087 Buffer->GetLine(Line);
1088
1089 // we only use IType read; nFunc is redundant; Sc(ale Factor) we don't use
1090 scanCount = sscanf(Line, "%ld %4[lLsSpPdDfF] %f%n",
1091 &nFunc, IType, &Sc, &bytesConsumed);
1092 if (3==scanCount) {
1093 // create this BasisShell in the BasisSet
1094 MainData->Basis->Shells.push_back(BasisShell());
1095 // increment the shell count in the BasisSet (how many shells parsed)
1096 MainData->Basis->NumShells++;
1097 // cast "SP" to L for simplicity
1098 if ('S'==toupper(IType[0]) && 'P'==toupper(IType[1])) {
1099 IType[0] = 'L';
1100 IType[1] = '\0';
1101 }
1102 // save the type of this BasisShell
1103 switch (toupper(IType[0])) {
1104 case 'L':
1105 MainData->Basis->Shells[iShell].ShellType = LShell;
1106 break;
1107 case 'S':
1108 MainData->Basis->Shells[iShell].ShellType = SShell;
1109 break;
1110 case 'P':
1111 MainData->Basis->Shells[iShell].ShellType = PShell;
1112 break;
1113 case 'D':
1114 MainData->Basis->Shells[iShell].ShellType = DShell;
1115 break;
1116 case 'F':
1117 MainData->Basis->Shells[iShell].ShellType = FShell;
1118 break;
1119 }
1120 // add first shell of this atom to BasisMap and save NuclearCharge
1121 if (0==shellsPeriAtom) {
1122 MainData->Basis->BasisMap[2*iAtom]=iShell;
1123 MainData->Basis->NuclearCharge[iAtom] = (long)(lFrame->GetAtomType(iAtom));
1124 }
1125 MainData->Basis->NumFuncs += MainData->Basis->Shells[iShell].GetNumFuncs(false);
1126 // read in functions for this shell (kinda dumb: grab rows of floats if
1127 // the line isn't formatted like the lines we grab ITypes from)
1128 char tmpStr[5];
1129 float tmpFloat[3];
1130 bool stopReadingShell = false;
1131 while ( !stopReadingShell ) {
1132 Buffer->GetLine(Line);
1133 if (3==sscanf(Line, "%ld %4[lLsSpPdDfF] %f", &nFunc, IType, &Sc)) {
1134 Buffer->BackupnLines(1);
1135 break;
1136 }
1137 scanCount = sscanf(Line, "%f %f %f", &tmpFloat[0], &tmpFloat[1], &tmpFloat[2]);
1138 // non-SP (L) case: one exponent, one coef per line
1139 if (2==scanCount && LShell!=MainData->Basis->Shells[iShell].ShellType) {
1140 MainData->Basis->Shells[iShell].NumPrims++;
1141 MainData->Basis->Shells[iShell].Exponent.push_back(tmpFloat[0]);
1142 MainData->Basis->Shells[iShell].NormCoef.push_back(tmpFloat[1]);
1143 }
1144 // SP (L) case: one exp, two coeff's per line
1145 else if (3==scanCount && LShell==MainData->Basis->Shells[iShell].ShellType) {
1146 MainData->Basis->Shells[iShell].NumPrims++;
1147 MainData->Basis->Shells[iShell].Exponent.push_back(tmpFloat[0]);
1148 MainData->Basis->Shells[iShell].NormCoef.push_back(tmpFloat[1]);
1149 MainData->Basis->Shells[iShell].NormCoef.push_back(tmpFloat[2]);
1150 }
1151 // We've found the end of this Atom's Basis Set, end of the $BASIS section
1152 // or else we've hit an error
1153 else if (1==sscanf(Line, "%4s%n", tmpStr, &bytesConsumed)) {
1154 if (2==bytesConsumed && 0==strncmp(tmpStr, "$$", 3)) {
1155 // add ending shell of this atom to BasisMap
1156 MainData->Basis->BasisMap[2*iAtom+1]=iShell;
1157 // we'll move on to next atom (or be done with Basis)
1158 ++iAtom;
1159 shellsPeriAtom = -1; // reset for next atom;
1160 stopReadingShell = true;
1161 break;
1162 }
1163 else if (4==bytesConsumed && 0==strncmp(tmpStr, "$END", 5)) {
1164 // same as above, but need to break out of basis parsing
1165 MainData->Basis->BasisMap[2*iAtom+1]=iShell;
1166 ++iAtom;
1167 stopReadingShell = true;
1168 // BasisDone = true;
1169 // possibly needed when trying to make parser more intelligent when the
1170 // file isn't formatted perfectly; eg, there is a blank line after $END
1171 break;
1172 }
1173 else {
1174 error = true;
1175 }
1176 } else { // likely hit a blank line
1177 MainData->Basis->BasisMap[2*iAtom+1]=iShell;
1178 ++iAtom;
1179 stopReadingShell = true;
1180 }
1181 }
1182 // move on to next shell in next iteration
1183 ++iShell;
1184 ++shellsPeriAtom;
1185 }
1186 else if (FindKeyWord(Line, "$END", 4) >-1) {
1187 BasisDone = true;
1188 break;
1189 }
1190 else {
1191 error = true;
1192 break;
1193 }
1194
1195 } // creating BasisSet
1196 if (error && !BasisDone) {
1197 // Free what we have and set it NULL so dependent functions won't crash
1198 if (MainData->Basis != NULL) delete MainData->Basis;
1199 MainData->Basis = NULL;
1200 MessageAlert("Error while reading. No basis set created.");
1201 } else {
1202 BasisDone = true;
1203 MainData->Basis->NuclearChargesAreValid(true);
1204 }
1205 }
1206 // now look for Alpha Coefficients (Orbitals; depends on BasisSet)
1207 if (BasisDone&&(MainData->Basis != NULL)&&(Buffer->LocateKeyWord("$COEFF_ALPHA", 12))) {
1208 Buffer->GetLine(Line); // skip $COEFF_ALPHA line
1209 bool error = false;
1210 char tmpStr[5];
1211 // counters for within iterations and overall in this section
1212 unsigned long iSymCount, symCount = 0, eigenvecCount = 0;
1213
1214 // we assume that the number of Basis Functions is the number
1215 // coefficients. Otherwise we should throw an error
1216 long nOrbs = MainData->Basis->GetNumBasisFuncs(false);
1217 // create the OrbitalRec and save it if successful
1218 OrbitalRec *OrbSet = new OrbitalRec(nOrbs, nOrbs, nOrbs);
1219 if (OrbSet != NULL) lFrame->Orbs.push_back(OrbSet);
1220
1221 // read the section until we hit the end. should be modified to halt on EOF
1222 while ((Buffer->GetFilePos()<Buffer->GetFileSize())&&!error) {
1223 Buffer->GetLine(Line);
1224 // continue until we find the end of the group
1225 if (FindKeyWord(Line, "$", 1)<0 && 0!=strncmp(Line, "\0", kMaxLineLength)) {
1226 lineBytes = strlen(Line);
1227 bytesRead = 0;
1228 iSymCount = 0;
1229
1230 // get the Alpha symmetry symbols a line at a time (should be 5 per line,
1231 // except possibly the last block may have fewer per line)
1232 while (bytesRead < lineBytes) {
1233 scanCount = sscanf(&Line[bytesRead], "%s%n", tmpStr, &bytesConsumed);
1234 if (1==scanCount) {
1235 tmpStr[4] = '\0'; // SymType is 5 chars wide and must be null-terminated
1236 strncpy(&OrbSet->SymType[5*symCount], tmpStr, 4);
1237 bytesRead+=bytesConsumed;
1238 ++iSymCount;
1239 ++symCount;
1240 } else
1241 break;
1242 } // got sym line
1243
1244 // next come Alpha eigenvectors (Energy; first row of data after syms)
1245 Buffer->GetLine(Line);
1246 lineBytes = strlen(Line);
1247 bytesRead = 0;
1248 float tmpEigenvec;
1249 // get a line of the values at a time (should be 5 per line, except possibly
1250 // the last block may have fewer per line)
1251 while (bytesRead < lineBytes) {
1252 scanCount = sscanf(&Line[bytesRead], "%f%n", &tmpEigenvec, &bytesConsumed);
1253 if (scanCount == 1) {
1254 lFrame->Orbs[0]->Energy[eigenvecCount] = tmpEigenvec;
1255 bytesRead += bytesConsumed;
1256 ++eigenvecCount;
1257 } else
1258 break;
1259 } //got eigenvector line
1260
1261 // now get the Alpha coefficients
1262 for (long iLine=0; iLine < nOrbs; ++iLine) {
1263 Buffer->GetLine(Line);
1264 // each line should contain up to 5 orbitals
1265 lineBytes = strlen(Line);
1266 bytesRead = 0;
1267 long iCoef = 0;
1268 float tmpCoef;
1269 // get coefficients line at a time, "symCount" times
1270 while (bytesRead < lineBytes && iCoef < symCount) {
1271 scanCount = sscanf(&Line[bytesRead], "%f%n", &tmpCoef, &bytesConsumed);
1272 if (scanCount == 1) {
1273 OrbSet->Vectors[(symCount-iSymCount)*nOrbs+iCoef*nOrbs+iLine] = tmpCoef;
1274 bytesRead += bytesConsumed;
1275 ++iCoef;
1276 } else
1277 break;
1278 }
1279 if (iCoef < iSymCount) error = true;
1280 if (error) break;
1281 } // got coefs block
1282 if (error) break;
1283 }
1284 else
1285 break; // found $END of $COEFF_ALPHA
1286 }
1287 if (error) {
1288 // free what we have and set NULL so dependent functions won't crash
1289 if (OrbSet != NULL) delete OrbSet;
1290 lFrame->Orbs[0] = NULL;
1291 MessageAlert("Error while reading. No orbital set created.");
1292 }
1293 else
1294 CoefAlphaDone = true;
1295 } // Alpha Coefficients (Orbitals) done
1296
1297 // now look for Beta Coefficients (Orbitals; optional; depends on Alpha Coefficients)
1298 if (CoefAlphaDone&&(Buffer->LocateKeyWord("$COEFF_BETA", 11))) {
1299 Buffer->GetLine(Line); // skip $COEFF_BETA line
1300 bool error = false;
1301 char tmpStr[5];
1302 // counters for within iterations and overall in this section
1303 unsigned long iSymCount, symCount = 0, eigenvecCount = 0;
1304 // we assume that the number of Basis Functions is the number
1305 // coefficients. Otherwise wei should throw an error
1306 long nOrbs = MainData->Basis->GetNumBasisFuncs(false);
1307
1308 while ((Buffer->GetFilePos()<Buffer->GetFileSize())&&!error) {
1309 Buffer->GetLine(Line);
1310 // continue until we find the end of the group
1311 if (FindKeyWord(Line, "$", 1)<0 && 0!=strncmp(Line, "\0", kMaxLineLength)) {
1312 lineBytes = strlen(Line);
1313 bytesRead = 0;
1314 iSymCount = 0;
1315
1316 // get the Beta symmetry symbols a line at a time (should be 5 per line,
1317 // except possibly the last block may have fewer per line)
1318 while (bytesRead < lineBytes) {
1319 scanCount = sscanf(&Line[bytesRead], "%s%n", tmpStr, &bytesConsumed);
1320 if (1==scanCount) {
1321 tmpStr[4] = '\0'; // SymType is 5 chars wide and must be null-terminated
1322 strncpy(&lFrame->Orbs[0]->SymTypeB[5*symCount], tmpStr, 4);
1323 bytesRead+=bytesConsumed;
1324 ++iSymCount;
1325 ++symCount;
1326 } else
1327 break;
1328 } // get sym line
1329
1330 // next come Beta eigenvectors (Energy; first row of data after syms)
1331 Buffer->GetLine(Line);
1332 lineBytes = strlen(Line);
1333 bytesRead = 0;
1334 float tmpEigenvec;
1335 // get a line of the values at a time (should be 5 per line, except possibly
1336 // the last block may have fewer per line)
1337 while (bytesRead < lineBytes) {
1338 scanCount = sscanf(&Line[bytesRead], "%f%n", &tmpEigenvec, &bytesConsumed);
1339 if (scanCount == 1) {
1340 lFrame->Orbs[0]->EnergyB[eigenvecCount] = tmpEigenvec;
1341 bytesRead += bytesConsumed;
1342 ++eigenvecCount;
1343 } else
1344 break;
1345 } //get eigenvector line
1346
1347 // now get the Beta coefficients
1348 for (long iLine=0; iLine < nOrbs; ++iLine) {
1349 Buffer->GetLine(Line);
1350 // each line will contain up to 5 orbitals
1351 lineBytes = strlen(Line);
1352 bytesRead = 0;
1353 long iCoef = 0;
1354 float tmpCoef;
1355 // get coefficients line at a time, "symCount" times
1356 while (bytesRead < lineBytes && iCoef < symCount) {
1357 scanCount = sscanf(&Line[bytesRead], "%f%n", &tmpCoef, &bytesConsumed);
1358 if (scanCount == 1) {
1359 lFrame->Orbs[0]->VectorsB[(symCount-iSymCount)*nOrbs+iCoef*nOrbs+iLine] = tmpCoef;
1360 bytesRead += bytesConsumed;
1361 ++iCoef;
1362 } else
1363 break;
1364 }
1365 if (iCoef < iSymCount) error = true;
1366 if (error) break;
1367 } // get coef block
1368 if (error) break;
1369 }
1370 else
1371 // if not found $END??
1372 break; // found $END of $COEFF_BETA
1373 }
1374 if (error) {
1375 // If we got to this point, Alpha was done correctly, so we don't delete the
1376 // OrbitalRec -just resize it to exclude Beta (check for NULL to be safe)
1377 if (lFrame->Orbs[0] != NULL)
1378 lFrame->Orbs[0]->ReSize(MainData->Basis->GetNumBasisFuncs(false), 0);
1379 MessageAlert("Error while reading. No beta orbital set added.");
1380 }
1381 else
1382 CoefBetaDone = true;
1383 } // Beta Coefficients (orbitals) done
1384 else if (BasisDone && CoefAlphaDone) // no Beta Coeffs
1385 lFrame->Orbs[0]->ReSize(MainData->Basis->GetNumBasisFuncs(false), 0);
1386
1387 // now look for Alpha Orbital Occupations (optional; depends on COEFF_ALPHA)
1388 if (CoefAlphaDone&&(Buffer->LocateKeyWord("$OCC_ALPHA", 10))) {
1389 Buffer->SkipnLines(1); // skip $OCC_ALPHA line
1390 bool error = false;
1391 // the number of orbital occupations should be the number of basis functions
1392 long nOrbs = MainData->Basis->GetNumBasisFuncs(false);
1393 lFrame->Orbs[0]->OrbOccupation = new float[nOrbs];
1394 // if the array was allocated fine, we can continue
1395 if (lFrame->Orbs[0]->OrbOccupation != NULL) {
1396 // counters and a temporary slot for data read one item at a time
1397 long occCount = 0, lineOccs;
1398 float tmpOcc;
1399 // read the occupation numbers end $END; should have a case for EOF read
1400 while ((Buffer->GetFilePos()<Buffer->GetFileSize())&&!error) {
1401 Buffer->GetLine(Line);
1402 // continue until we find the end of the group
1403 if (FindKeyWord(Line, "$", 1)<0 && 0!=strncmp(Line, "\0", kMaxLineLength)) {
1404 lineBytes = strlen(Line);
1405 bytesRead = 0;
1406 lineOccs = 0;
1407 //read line at a time, up to 5, and within number of orb's defined above
1408 while (bytesRead < lineBytes && lineOccs < 5 && occCount < nOrbs) {
1409 scanCount = sscanf(&Line[bytesRead], "%f%n", &tmpOcc, &bytesConsumed);
1410 if (scanCount == 1) {
1411 bytesRead+=bytesConsumed;
1412 lFrame->Orbs[0]->OrbOccupation[occCount] = tmpOcc;
1413 ++lineOccs;
1414 ++occCount;
1415 }
1416 else
1417 break;
1418 }
1419 if (error) break;
1420 }
1421 else
1422 break;
1423 }
1424 // insufficient data
1425 if (occCount < nOrbs)
1426 error = true;
1427 // else set the number occupied to what we read.
1428 else
1429 lFrame->Orbs[0]->NumOccupiedAlphaOrbs = occCount;
1430 }
1431 if (error) {
1432 // free what we have and set NULL so dependent functions won't crash
1433 if (lFrame->Orbs[0]->OrbOccupation != NULL)
1434 delete lFrame->Orbs[0]->OrbOccupation;
1435 lFrame->Orbs[0]->OrbOccupation = NULL;
1436 MessageAlert("Error while reading. No Alpha Occupations added.");
1437 }
1438 else
1439 OccAlphaDone = true;
1440 }// Occ_Alpha done
1441
1442 // now look for Beta Orbital Occupations (optional; depends on COEFF_BETA)
1443 if (CoefBetaDone&&OccAlphaDone&&(Buffer->LocateKeyWord("$OCC_BETA", 9))) {
1444 Buffer->SkipnLines(1); // skip $OCC_BETA line
1445 bool error = false;
1446
1447 lFrame->Orbs[0]->setOrbitalWavefunctionType(UHF);
1448 long nOrbs = MainData->Basis->GetNumBasisFuncs(false);
1449 lFrame->Orbs[0]->OrbOccupationB = new float[nOrbs];
1450 if (lFrame->Orbs[0]->OrbOccupationB != NULL) {
1451 // counters and a temporary slot for data read one item at a time
1452 long occCount = 0, lineOccs;
1453 float tmpOcc;
1454
1455 while ((Buffer->GetFilePos()<Buffer->GetFileSize())&&!error) {
1456 Buffer->GetLine(Line);
1457 // continue until we find the end of the group
1458 if (FindKeyWord(Line, "$", 1)<0 && 0!=strncmp(Line, "\0", kMaxLineLength)) {
1459 lineBytes = strlen(Line);
1460 bytesRead = 0;
1461 lineOccs = 0;
1462 //read line at a time, up to 5, and within number of orb's defined above
1463 while (bytesRead < lineBytes && lineOccs < 5 && occCount < nOrbs) {
1464 scanCount = sscanf(&Line[bytesRead], "%f%n", &tmpOcc, &bytesConsumed);
1465 if (scanCount == 1) {
1466 bytesRead+=bytesConsumed;
1467 lFrame->Orbs[0]->OrbOccupationB[occCount] = tmpOcc;
1468 ++lineOccs;
1469 ++occCount;
1470 }
1471 else
1472 break;
1473 }
1474 if (error) break;
1475 }
1476 else
1477 break;
1478 }
1479 // insufficient data
1480 if (occCount < nOrbs)
1481 error = true;
1482 // else set the number occupied to what we read.
1483 else
1484 lFrame->Orbs[0]->NumOccupiedBetaOrbs = occCount;
1485 }
1486 if (error) {
1487 // free what we have and set NULL so dependent functions won't crash
1488 if (lFrame->Orbs[0]->OrbOccupationB != NULL)
1489 delete lFrame->Orbs[0]->OrbOccupationB;
1490 lFrame->Orbs[0]->OrbOccupationB = NULL;
1491 MessageAlert("Error while reading. No Beta Occupations added.");
1492 }
1493 else
1494 OccBetaDone = true;
1495 }// Occ_Beta Done
1496
1497 // now look for vibrational frequencies for the last frame (independent)
1498 if ((0<lFrame->GetNumAtoms())&&(Buffer->LocateKeyWord("$FREQ", 5))) {
1499 Buffer->SkipnLines(1); // skip $FREQ line
1500 // create the VibRec
1501 lFrame->Vibs = new VibRec(3*lFrame->NumAtoms, lFrame->NumAtoms);
1502 //continue only if we're successful
1503 if (lFrame->Vibs != NULL) {
1504 long nModes=0;
1505 char freq[kMaxLineLength];
1506 bool error = false; //Use the error flag to bail out once we hit an error
1507 while ((Buffer->GetFilePos())<(Buffer->GetFileSize())&&!error) {
1508 Buffer->GetLine(Line);
1509 //continue until we find the end of the group
1510 if (FindKeyWord(Line, "$", 1)<0 && 0!=strncmp(Line, "\0", kMaxLineLength)) {
1511 //the first line is the symmetry symbolis which we ignore
1512 // (we should've gotten those from the Alpha/Beta Coefficients)
1513 Buffer->GetLine(Line); //next line is the frequencies
1514 long lineModes=0;
1515 lineBytes = strlen(Line);
1516 bytesRead = 0;
1517 // read Frequencies as strings one at a time in one line
1518 while (bytesRead < lineBytes) {
1519 scanCount = sscanf(&Line[bytesRead], "%s%n", freq, &bytesConsumed);
1520 if (scanCount == 1) {
1521 lFrame->Vibs->Frequencies.push_back(freq);
1522 bytesRead += bytesConsumed;
1523 ++lineModes;
1524 } else
1525 break;
1526 }
1527 //Next come the vibrational offsets
1528 for (long iatm=0; iatm<lFrame->NumAtoms; ++iatm) {
1529 Buffer->GetLine(Line);
1530 //each line will normally contain x, y, z for one atom for 3 modes
1531 bytesRead = 0;
1532 for (long imode=0; imode<lineModes; ++imode) {
1533 CPoint3D temp;
1534 int scanCount = sscanf(&Line[bytesRead], "%f %f %f%n",
1535 &temp.x, &temp.y, &temp.z, &bytesConsumed);
1536 if (scanCount == 3) {
1537 lFrame->Vibs->NormMode[iatm + lFrame->NumAtoms*(nModes+imode)] = temp;
1538 bytesRead += bytesConsumed;
1539 } else {
1540 lineModes = imode;
1541 error = true;
1542 break;
1543 }
1544 }
1545 if (error) break;
1546 }
1547 nModes += lineModes;
1548 } else
1549 break;
1550 }// end while in file and not error
1551 lFrame->Vibs->NumModes = nModes;
1552 lFrame->Vibs->Resize(nModes);
1553 }
1554 } // vibrational frequencies done
1555 // Don't need an else, case, since lFrame->Vibs would be NULL, anyway
1556 // We don't handle the $DIPOLE section in MKL files
1557 // OpenMKLFile() can return "success" because we are done parsing the file
1558 return 1;
1559 }
1560
1561 /**
1562 * Adds support for opening the MoPac zMatrix MOP and mop file types, and
1563 * MoPac archive output ARC and arc files.
1564 * @param Buffer A BufferFileObject that the .MOP or .mop file is buffereid.
1565 * @param fileType A char indicating whether the file is a MOP or ARC file.
1566 * into to make parsing the file easier. See the BufferFile object for
1567 * valid BufferFile operations. Parsing code adapted from
1568 * MoleculeData::ParseMOPACZMatrix.
1569 * @return Returns 1 upon open success or 0 on error or failure to open
1570 */
OpenMOPACFile(BufferFile * Buffer,TextFileType fileType)1571 long MolDisplayWin::OpenMOPACFile(BufferFile * Buffer, TextFileType fileType) {
1572 // buffer line for text to be scanned while parsing
1573 char Line[kMaxLineLength];
1574 // placeholder for traversing file sections in Buffer
1575 wxFileOffset startOfAtoms = 1;
1576 // # of tokens sucessfully read in a sscanf call, # line of atoms read
1577 int scanCount = 0, iLine = 0;
1578 // vars for holding sscanf read, borrowing some from ParseMOPACZMatrix()
1579 CPoint3D pos = CPoint3D(0.0f, 0.0f, 0.0f); // just a placeholder
1580 char symbol[4]; // This could probably safely be 2-3 chars long
1581 float bondLength = -0.1f, bondAngle = 0.0f, bondDihedral = 0.0f;
1582 // sane defaults to avoid accessing unassigned variables
1583 long AtomType = -1, nAtoms = 0;
1584 int j1 = -1, j2 = -1, j3 = -1, con1, con2, con3;
1585 bool error = false;
1586
1587 ProgressInd->ChangeText("Reading MOPAC file...");
1588 Frame *lFrame = MainData->cFrame;
1589 //zero out initial symbol
1590 memset((void *)symbol, 0, (size_t)(4*sizeof(char)));
1591
1592 // file is of type ARC
1593 if (fileType == MOPACarcFile) {
1594 // Get to the right part of the file
1595 Buffer->LocateKeyWord("DATE:", 5);
1596 Buffer->SkipnLines(1);
1597 Buffer->LocateKeyWord("DATE:", 5);
1598 Buffer->SkipnLines(1);
1599 }
1600 // file is of type MOP
1601 else if (fileType == MOPACmopFile)
1602 // skip descriptions, MoPac parms and goto start of atoms
1603 Buffer->SkipnLines(3);
1604 else
1605 return 0; // quit 'cause we don't know what kind of file we were passed
1606
1607 startOfAtoms = Buffer->GetFilePos();
1608 // Count the number of Atoms
1609 while (Buffer->GetFilePos() < Buffer->GetFileLength()) {
1610 Buffer->GetLine(Line);
1611 scanCount = sscanf(Line, "%3s %f %d %f %d %f %d %d %d %d", symbol, &bondLength,
1612 &j1, &bondAngle, &j2, &bondDihedral, &j3, &con1, &con2, &con3);
1613 // The last atom in the list may be a duplicate of the
1614 // first atom in the list and needs to be ignored
1615 if (scanCount > 2 && nAtoms > 1 && bondLength < 0.00001) break;
1616 // otherwise, it is [probably] a new atom
1617 if ( (scanCount > 9 && nAtoms > 2) || (scanCount > 8 && nAtoms == 2) ||
1618 (scanCount > 6 && nAtoms == 1) || (scanCount > 4 && nAtoms == 0) )
1619 ++nAtoms;
1620 else
1621 break;
1622 }
1623 // atoms are now counted; go back to atoms' start for actual parsing
1624 Buffer->SetFilePos(startOfAtoms);
1625
1626 // data in this file will be treated as a zMatrix
1627 // cartesian mop files exist, but usually have a different extension
1628 if (!(MainData->IntCoords))
1629 MainData->IntCoords = new Internals;
1630 MOPacInternals * mInts = MainData->IntCoords->GetMOPacStyle();
1631 if (!mInts) {
1632 MainData->IntCoords->CreateMOPacInternals(3*nAtoms);
1633 mInts = MainData->IntCoords->GetMOPacStyle();
1634 }
1635 float unitConversion = 1.0f;
1636 if (MainData->InputOptions && MainData->InputOptions->Data->GetUnits())
1637 unitConversion = kBohr2AngConversion;
1638
1639 // Get and add atoms (parsing) loop
1640 while (iLine < nAtoms) {
1641 con1 = -1; // Default Values
1642 con2 = -1;
1643 con3 = -1;
1644 Buffer->GetLine(Line);
1645 scanCount = sscanf(Line, "%3s %f %d %f %d %f %d %d %d %d", symbol, &bondLength,
1646 &j1, &bondAngle, &j2, &bondDihedral, &j3, &con1, &con2, &con3);
1647 if (scanCount < 1) {
1648 error = true;
1649 break; //failed to get anything
1650 }
1651 // Get type of atom by atomic symbol and add it to fram (dummy position 0,0,0)
1652 AtomType = SetAtomType((unsigned char *)symbol);
1653 lFrame->AddAtom(AtomType, pos);
1654 if (iLine > 0) {
1655 if (scanCount < 2) {
1656 error = true;
1657 break;
1658 }
1659 if (iLine == 1) //the second atom will specify only the bond length
1660 con1 = 1;
1661 // 3rd Line and beyond (iLine == 2 and up)
1662 else {
1663 if (iLine == 2) { //For the third atom the connectivity is optional
1664 if ((scanCount >= 5)&&(scanCount <= 7)) {
1665 con1 = 2;
1666 con2 = 1; //The default allows the connections to be assumed
1667 if (scanCount >= 6) {
1668 con1 = (int) bondDihedral;
1669 con2 = j3;
1670 }
1671 }
1672 else if (scanCount < 5) break; // in this case the line is invalid
1673 }
1674 }
1675 if (bondLength < 0.00001)
1676 break; // bad value or dupe of first atom
1677 // reduce values by 1 because our indexing starts at 0 not 1
1678 con1--;
1679 con2--;
1680 con3--;
1681 if (con1 >= iLine)
1682 break;
1683 // store connections and coordinates
1684 mInts->AddInternalCoordinate(iLine, con1, 0, bondLength*unitConversion);
1685 if (iLine > 1) {
1686 mInts->AddInternalCoordinate(iLine, con2, 1, bondAngle);
1687 if (iLine > 2)
1688 mInts->AddInternalCoordinate(iLine, con3, 2, bondDihedral);
1689 }
1690 }
1691 ++iLine;
1692 } // end parsing loop
1693 if (error)
1694 return 0; // failure due to an error: quit!
1695 // if we punted after the AddAtom call delete off the
1696 // atom without internal coordinate information
1697 if (iLine > lFrame->NumAtoms)
1698 lFrame->DeleteAtom(iLine-1);
1699 // now convert the set of internals into cartesians
1700 // this caused some segfaults in testing, but probably due to bad files
1701 mInts->InternalsToCartesians(MainData, Prefs, 0);
1702 // Setup bonds, if needed
1703 if (Prefs->GetAutoBond())
1704 lFrame->SetBonds(Prefs, true, ProgressInd);
1705 return 1; // OpenMOPACFile success
1706 }
1707
OpenXYZFile(BufferFile * Buffer)1708 long MolDisplayWin::OpenXYZFile(BufferFile * Buffer) {
1709 char Line[kMaxLineLength];
1710 long nAtoms,i;
1711 short scanerr;
1712
1713 ProgressInd->ChangeText("Reading XYZ file...");
1714 Frame * lFrame = MainData->cFrame;
1715 //1st line contains the number of atoms
1716 Buffer->GetLine(Line);
1717 scanerr = sscanf(Line, "%ld", &nAtoms);
1718 if ((scanerr!=1)||(nAtoms<=0)) {
1719 wxLogMessage(_("XYZ files must have an integer representing the number of atoms on the first line of the file."));
1720 throw DataError();
1721 }
1722 //allocate memory for the atoms
1723 if (lFrame->NumAtoms > 0) { //If there are already atoms treat as an append
1724 lFrame = MainData->AddFrame(nAtoms,0);
1725 } else {
1726 if (!MainData->SetupFrameMemory(nAtoms, 0)) throw MemoryError();
1727 Buffer->GetLine(Line);
1728 MainData->SetDescription(Line);
1729 }
1730 long DRCnSkip = Prefs->GetDRCSkip(), nSkip=0;
1731 bool Done=false;
1732 bool RdPoint = true;
1733 try {
1734 while (!Done) {
1735 Done = true;
1736 if (RdPoint) {
1737 VibRec * lVibs = NULL;
1738 for (i=0; i<nAtoms; ++i) {
1739 long AtomType, test;
1740 CPoint3D Pos, Vector;
1741
1742 Buffer->GetLine(Line);
1743 test = ParseCartLine(Line, &AtomType, &Pos, &Vector, -1);
1744
1745 if (test==-1) { //invalid atom type
1746 wxLogMessage(_("Error: An invalid Atom Type was encountered in the atom list."));
1747 throw DataError();
1748 } else if (test<0) {//other invalid data was encountered
1749 wxLogMessage(_("An error occured while reading the file. Open File Aborted!"));
1750 throw DataError();
1751 }
1752 if (AtomType > 115) {
1753 if (AtomType > 255) {
1754 if (((AtomType - 255) < 1)||((AtomType - 255) > nAtoms)) {
1755 wxLogMessage(_("Invalid atom number detected in special atom list."));
1756 throw DataError();
1757 }
1758 }
1759 if (!lFrame->AddSpecialAtom(Vector, i)) {
1760 throw MemoryError();
1761 }
1762 } else if (test == 7) { //mass weight the normal mode
1763 if (i==0) {
1764 lVibs = new VibRec(1, nAtoms);
1765 if (!lVibs) throw MemoryError();
1766 }
1767 if (lVibs) {
1768 lVibs->NormMode[i].x = Vector.x*Prefs->GetSqrtAtomMass(AtomType-1);
1769 lVibs->NormMode[i].y = Vector.y*Prefs->GetSqrtAtomMass(AtomType-1);
1770 lVibs->NormMode[i].z = Vector.z*Prefs->GetSqrtAtomMass(AtomType-1);
1771 }
1772 }
1773 lFrame->AddAtom(AtomType, Pos);
1774 MainData->MaxSize = MAX(MainData->MaxSize, fabs(Pos.x));
1775 MainData->MaxSize = MAX(MainData->MaxSize, fabs(Pos.y));
1776 MainData->MaxSize = MAX(MainData->MaxSize, fabs(Pos.z));
1777 }
1778 if (lVibs) lFrame->Vibs = lVibs;
1779 if (Prefs->GetAutoBond()) //setup bonds, if needed
1780 lFrame->SetBonds(Prefs, false, ProgressInd);
1781 }
1782 wxFileOffset cPos = Buffer->GetFilePos();
1783 wxFileOffset fileLength = Buffer->GetFileLength();
1784 if (cPos < fileLength) { //If we haven't reached the end of the file
1785 Buffer->GetLine(Line); //check to see if another frame is available
1786 scanerr = sscanf(Line, "%ld", &nAtoms);
1787 if ((scanerr==1)&&(nAtoms>0)) {
1788 if (nSkip >= DRCnSkip) {
1789 nSkip = 0;
1790 RdPoint = true;
1791 lFrame = MainData->AddFrame(nAtoms,0);
1792 if (!lFrame) throw MemoryError();
1793 Buffer->GetLine(Line);
1794 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
1795 { throw UserCancel();}
1796 } else {
1797 ++nSkip;
1798 Buffer->SkipnLines(nAtoms+1);
1799 RdPoint = false;
1800 }
1801 Done = false;
1802 }
1803 }
1804 }
1805 }
1806 catch (DataError /*Error*/) {
1807 //attempt to save part of file
1808 if (MainData->GetNumFrames() > 1) {
1809 MainData->DeleteFrame();
1810 }
1811 wxLogMessage(_("Error while parsing file. Partial file may be valid."));
1812 }
1813 return 1;
1814 }
1815
OpenMolPltFile(BufferFile * Buffer)1816 long MolDisplayWin::OpenMolPltFile(BufferFile *Buffer) {
1817 long j,ii, nkinds=0, catm, iscanerr=0, LineLength, LinePos=0, fileAtoms=0,
1818 fileBonds=0;
1819 int nchar;
1820 long test=0, Mode=0;
1821 float BondLength=0.0f;
1822 char LineText[kMaxLineLength+1], KeyWord[kMaxLineLength+1], token[5];
1823
1824 ProgressInd->ChangeText("Reading MolPlt format file...");
1825 Frame * lFrame = MainData->cFrame;
1826 /*Now interpert the file data */
1827 // Grab the first line (containing all keywords)
1828 Buffer->GetLine(LineText);
1829 LineLength = strlen(LineText);
1830
1831 LinePos = FindKeyWord(LineText, "NATOMS", 6);
1832 if (LinePos >= 0) {
1833 LinePos += 6;
1834 iscanerr = sscanf(&LineText[LinePos], "%1s%ld", token, &fileAtoms);
1835 if (iscanerr != 2) return 0;
1836 } else return 0; // NATOMS keyword not found!
1837 LinePos = FindKeyWord(LineText, "NKINDS", 6);
1838 if (LinePos >= 0) {
1839 LinePos += 6;
1840 sscanf(&LineText[LinePos], "%1s%ld", token, &nkinds);
1841 }
1842 LinePos = FindKeyWord(LineText, "NBONDS", 6);
1843 if (LinePos >= 0) {
1844 LinePos += 6;
1845 sscanf(&LineText[LinePos], "%1s%ld", token, &fileBonds);
1846 }
1847 LinePos = FindKeyWord(LineText, "MODE", 4);
1848 if (LinePos >= 0) {
1849 LinePos += 4;
1850 sscanf(&LineText[LinePos], "%1s%ld", token, &Mode);
1851 }
1852 LinePos = FindKeyWord(LineText, "BNDLENGTH", 9);
1853 if (LinePos >= 0) {
1854 LinePos += 9;
1855 sscanf(&LineText[LinePos], "%1s%f", token, &BondLength);
1856 }
1857 LinePos = FindKeyWord(LineText, "BONDLENGTH", 10);
1858 if (LinePos >= 0) {
1859 LinePos += 10;
1860 sscanf(&LineText[LinePos], "%1s%f", token, &BondLength);
1861 }
1862
1863 if (fileAtoms <= 0) { /* There don't appear to be any atoms to read in ???*/
1864 AbortOpen("NATOMS keyword missing. Are you sure this is a Molplt file\? Open file aborted.");
1865 return 0;
1866 }
1867 //Allocate frame memory
1868 if (!MainData->SetupFrameMemory(fileAtoms, fileBonds)) throw MemoryError();
1869 // The second line is just a description so copy it to a string
1870 Buffer->GetLine(LineText);
1871 MainData->SetDescription(LineText);
1872
1873 //Need to keep the single mode storage separated off as the AddAtom function will delete it
1874 //from the Frame record otherwise.
1875 VibRec * Mode1Vibs = NULL;
1876 if (Mode == -1) {
1877 Mode1Vibs = new VibRec(1, fileAtoms);
1878 if (!Mode1Vibs) throw MemoryError();
1879 }
1880 Buffer->SkipnLines(nkinds);
1881
1882 // read in the coords and atomtypes
1883 for (j=0; j<fileAtoms; ++j) { // loop over the number of atoms
1884 long AtomType;
1885 CPoint3D Pos, Vector;
1886
1887 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
1888 { throw UserCancel();}
1889 Buffer->GetLine(LineText);
1890 test = ParseCartLine(LineText, &AtomType, &Pos, &Vector, Mode);
1891
1892 if (AtomType==-1) { //invalid atom type
1893 //Choices would seem to be to punt and abort or change to some sort of valid type
1894 wxLogMessage(_("Error: An invalid Atom Type was encountered in the atom list."));
1895 if (Mode1Vibs) delete Mode1Vibs;
1896 throw DataError();
1897 }
1898 if (test<0) {
1899 wxLogMessage(_("An error occured while reading the file. Open File Aborted!"));
1900 if (Mode1Vibs) delete Mode1Vibs;
1901 throw DataError();
1902 }
1903 if (AtomType > 115) {
1904 if (Mode < 0) {
1905 wxLogMessage(_("Error: Special Atom types may not be used with Normal Modes!"));
1906 if (Mode1Vibs) delete Mode1Vibs;
1907 throw DataError();
1908 }
1909 if (AtomType > 255) {
1910 if (((AtomType - 255) < 1)||((AtomType - 255) > fileAtoms)) {
1911 wxLogMessage(_("Invalid atom number detected in special atom list."));
1912 if (Mode1Vibs) delete Mode1Vibs;
1913 throw DataError();
1914 }
1915 }
1916 if (!lFrame->AddSpecialAtom(Vector, j)) throw MemoryError();
1917 }
1918 if (Mode == -1) { //mass weight the normal mode
1919 Mode1Vibs->NormMode[j].x = Vector.x*Prefs->GetSqrtAtomMass(AtomType-1);
1920 Mode1Vibs->NormMode[j].y = Vector.y*Prefs->GetSqrtAtomMass(AtomType-1);
1921 Mode1Vibs->NormMode[j].z = Vector.z*Prefs->GetSqrtAtomMass(AtomType-1);
1922 }
1923 lFrame->AddAtom(AtomType, Pos);
1924 MainData->MaxSize = MAX(MainData->MaxSize, fabs(Pos.x));
1925 MainData->MaxSize = MAX(MainData->MaxSize, fabs(Pos.y));
1926 MainData->MaxSize = MAX(MainData->MaxSize, fabs(Pos.z));
1927 }
1928 if (Mode1Vibs) lFrame->Vibs = Mode1Vibs;
1929
1930 if (fileBonds > 0) { /* read in the array of bonds */
1931 long ibond=-1, temp;
1932 Buffer->GetLine(LineText);
1933 LinePos = FindKeyWord(LineText, "BONDATOMS", 9);
1934 if (LinePos >= 0) {
1935 LinePos += 9;
1936 LineLength = strlen(LineText);
1937 for (j=0; j<(2*fileBonds); ++j) {
1938 while (LineText[LinePos] && ((LineText[LinePos] < '0')||
1939 (LineText[LinePos] > '9'))) ++LinePos;
1940 while (LinePos >= LineLength) { //EOL reached try getting a new line
1941 wxFileOffset CurrentPos = Buffer->GetFilePos();
1942 Buffer->GetLine(LineText);
1943 if ((-1<FindKeyWord(LineText, "ATOMIC", 6))||
1944 (-1<FindKeyWord(LineText, "MODE", 4))) {
1945 Buffer->SetFilePos(CurrentPos);
1946 break;
1947 }
1948 LinePos = 0;
1949 LineLength = strlen(LineText);
1950 while (LineText[LinePos] && ((LineText[LinePos] < '0')||
1951 (LineText[LinePos] > '9'))) ++LinePos;
1952 }
1953 if (LinePos < LineLength) {
1954 iscanerr = sscanf(&LineText[LinePos], "%ld%n", &temp, &nchar);
1955 if (iscanerr != 1)
1956 return 1;
1957 LinePos += nchar;
1958 if ((temp >= 1)&&(temp <= lFrame->NumAtoms)) {
1959 temp--;
1960 if (ibond == -1) ibond = temp;
1961 else {
1962 lFrame->AddBond(ibond, temp);
1963 ibond = -1; //reset ibond for the next bond pair
1964 }
1965 } else // Bad bonded atom number
1966 return 1;
1967 } else break; //and break since we've run out of bond #'s
1968 }
1969 } else {
1970 return 1;
1971 }
1972 }
1973 if ((BondLength > 0.0)||(Prefs->GetAutoBond())) {
1974 Prefs->SetMaxBondLength(BondLength);
1975 lFrame->SetBonds(Prefs, false, ProgressInd);
1976 }
1977 if (Mode > 0) {
1978 nkinds = 3*(lFrame->NumAtoms); /* In general there will be 3N normal modes */
1979 VibRec * lVibs = MainData->cFrame->Vibs = new VibRec(nkinds, fileAtoms);
1980 if (!lVibs) throw MemoryError();
1981 catm = 0;
1982 ii=0;
1983 try {
1984 /* Now locate the first frequency (skipping the atomic masses) */
1985 wxFileOffset CurrentPos = Buffer->GetFilePos();
1986 Buffer->GetLine(LineText);
1987 while (-1>=FindKeyWord(LineText, "MODE", 4)) {
1988 CurrentPos = Buffer->GetFilePos();
1989 Buffer->GetLine(LineText);
1990 }
1991 Buffer->SetFilePos(CurrentPos);
1992
1993 for (; ii < (3*(lFrame->NumAtoms)); ++ii) {
1994 /* Allow user cancels */
1995 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
1996 { throw UserCancel();}
1997 Buffer->GetLine(LineText);
1998 for (j=0; LineText[j] && (LineText[j] != '='); ++j) ;
1999 if (LineText[j] != '=') break; /* no more frequencies so quit */
2000 sscanf(&LineText[j+1], "%s", KeyWord);
2001 LineLength = strlen(KeyWord);
2002 /*Check to see if the first character is a '-' if so change it to an 'i' since it really is an
2003 imaginary mode and because the menu manager will think it means create a divider in the menu instead
2004 of a regular text item */
2005 if (KeyWord[0] == '-') KeyWord[0] = 'i';
2006 lVibs->Frequencies.push_back(std::string(KeyWord));
2007
2008 for (j=0; j < (lFrame->NumAtoms); ++j) {
2009 Buffer->GetLine(LineText);
2010 iscanerr = sscanf(LineText, "%f%f%f", &((lVibs->NormMode[catm]).x),
2011 &((lVibs->NormMode[catm]).y), &((lVibs->NormMode[catm]).z));
2012 if (iscanerr != 3) { /*Uh Ohh looks like there was a problem reading the file*/
2013 wxLogMessage(_("Error reading the Normal Mode input. Open file aborted."));
2014 throw DataError();
2015 }
2016 (lVibs->NormMode[catm]).x *= (Prefs->GetSqrtAtomMass((lFrame->Atoms[j].Type)-1));
2017 (lVibs->NormMode[catm]).y *= (Prefs->GetSqrtAtomMass((lFrame->Atoms[j].Type)-1));
2018 (lVibs->NormMode[catm]).z *= (Prefs->GetSqrtAtomMass((lFrame->Atoms[j].Type)-1));
2019 ++catm;
2020 }
2021 }
2022 }
2023 catch (FileError) { //We've hit the end of file so truncate the Mode list
2024 }
2025 lVibs->NumModes = ii;
2026 if (lVibs->NumModes < 3*lFrame->NumAtoms) /* Downsize the frequency storage to the size actually used */
2027 lVibs->Resize(lFrame->NumAtoms);
2028 }
2029 if (lFrame->Vibs) {
2030 lFrame->Vibs->CurrentMode = Mode - 1;
2031 if (lFrame->Vibs->CurrentMode < 0) lFrame->Vibs->CurrentMode = 0;
2032 MainData->SetDrawMode(true);
2033 }
2034 if (lFrame->SpecialAtoms) MainData->SetSpecialAtomDrawMode(true);
2035
2036 return 1;
2037 } /* OpenMolPlt */
OpenMoldenFile(BufferFile * Buffer)2038 long MolDisplayWin::OpenMoldenFile(BufferFile * Buffer) {
2039 char LineText[kMaxLineLength];
2040 Frame * lFrame = MainData->cFrame;
2041 Buffer->SetFilePos(0);
2042 if (Buffer->LocateKeyWord("[GEOMETRIES]", 12, -1)) { //both formats use Angstroms
2043 Buffer->GetLine(LineText);
2044 if (FindKeyWord(LineText, "XYZ", 3) >= 0) { //cartesian coordinates
2045 // XYZ format looks like
2046 // #_of_atoms
2047 // title often containing "scf done: energy"
2048 // one line for each atom in the form "symbol x y z"
2049 while (Buffer->GetFilePos() < Buffer->GetFileSize()) {
2050 Buffer->GetLine(LineText);
2051 int atmCount=0;
2052 if (sscanf(LineText, "%d", &atmCount) == 1) {
2053 if (atmCount <= 0) break;
2054 Buffer->GetLine(LineText);
2055 if (lFrame->NumAtoms > 0) {
2056 float t = lFrame->time;
2057 lFrame = MainData->AddFrame(atmCount, 0);
2058 lFrame->time = t+1;
2059 }
2060 int epos = FindKeyWord(LineText, "done:", 5);
2061 if (epos > 0) {
2062 sscanf(&(LineText[epos+5]), "%lf", &(lFrame->Energy));
2063 }
2064 for (int iatm=0; iatm<atmCount; ++iatm) {
2065 unsigned char token[kMaxLineLength];
2066 CPoint3D pos;
2067 Buffer->GetLine(LineText);
2068 int rdcount = sscanf(LineText, "%s %f %f %f", token, &(pos.x), &(pos.y), &(pos.z));
2069 if (rdcount == 4) {
2070 long atomnum = SetAtomType(token);
2071 if (atomnum>0)
2072 lFrame->AddAtom(atomnum, pos);
2073 }
2074 }
2075 if (Prefs->GetAutoBond())
2076 lFrame->SetBonds(Prefs, false, ProgressInd);
2077 } else break;
2078 }
2079 } else if (FindKeyWord(LineText, "ZMAT", 4) >= 0) { //GAMESS-UK style z matrix
2080 while (Buffer->GetFilePos() < Buffer->GetFileSize()) {
2081 Buffer->GetLine(LineText);
2082 if (FindKeyWord(LineText, "ZMAT", 4) >= 0) {
2083 Buffer->BackupnLines(1);
2084 if (lFrame->NumAtoms > 0) {
2085 float t = lFrame->time;
2086 lFrame = MainData->AddFrame(lFrame->NumAtoms, 0);
2087 lFrame->time = t+1;
2088 }
2089 MainData->ParseGAMESSUKZMatrix(Buffer, Prefs);
2090 if (lFrame->NumAtoms == 0) break;
2091 if (Prefs->GetAutoBond())
2092 lFrame->SetBonds(Prefs, false, ProgressInd);
2093 } else break;
2094 }
2095 } //else there is some undocumented type...
2096 Buffer->SetFilePos(0);
2097 if (Buffer->LocateKeyWord("[GEOCONV]", 9, -1)) {
2098 Buffer->SkipnLines(1);
2099 bool good = true;
2100 while (good) {
2101 good = false;
2102 Buffer->GetLine(LineText);
2103 if (FindKeyWord(LineText, "energy", 6) == 0) {
2104 good = true;
2105 int iframe = 1;
2106 MainData->SetCurrentFrame(iframe);
2107 Buffer->GetLine(LineText);
2108 while (sscanf(LineText, "%lf", &MainData->cFrame->Energy) == 1) {
2109 ++iframe;
2110 if (iframe > MainData->GetNumFrames()) break;
2111 MainData->SetCurrentFrame(iframe);
2112 Buffer->GetLine(LineText);
2113 }
2114 if (iframe <= MainData->GetNumFrames()) Buffer->BackupnLines(1);
2115 } else if (FindKeyWord(LineText, "max-force", 9) == 0) {
2116 good = true;
2117 int iframe = 1;
2118 MainData->SetCurrentFrame(iframe);
2119 Buffer->GetLine(LineText);
2120 float val;
2121 while (sscanf(LineText, "%f", &val) == 1) {
2122 MainData->cFrame->SetRMSGradient(val);
2123 ++iframe;
2124 if (iframe > MainData->GetNumFrames()) break;
2125 MainData->SetCurrentFrame(iframe);
2126 Buffer->GetLine(LineText);
2127 }
2128 if (iframe <= MainData->GetNumFrames()) Buffer->BackupnLines(1);
2129 } else if (FindKeyWord(LineText, "rms-force", 9) == 0) {
2130 good = true;
2131 int iframe = 1;
2132 MainData->SetCurrentFrame(iframe);
2133 Buffer->GetLine(LineText);
2134 float val;
2135 while (sscanf(LineText, "%f", &val) == 1) {
2136 MainData->cFrame->SetMaximumGradient(val);
2137 ++iframe;
2138 if (iframe > MainData->GetNumFrames()) break;
2139 MainData->SetCurrentFrame(iframe);
2140 Buffer->GetLine(LineText);
2141 }
2142 if (iframe <= MainData->GetNumFrames()) Buffer->BackupnLines(1);
2143 }
2144 }
2145 MainData->SetCurrentFrame(MainData->GetNumFrames());
2146 }
2147 }
2148 Buffer->SetFilePos(0);
2149 // Now look for the ATOMS keyword to use as coordinates for any MOs
2150 if (Buffer->LocateKeyWord("[ATOMS]", 7, -1)) {
2151 float unitConv = 1.0f; //default to angstroms
2152 Buffer->GetLine(LineText);
2153 if (FindKeyWord(LineText, "AU", 2) > 0) unitConv = kBohr2AngConversion;
2154 if (lFrame->NumAtoms > 0) lFrame = MainData->AddFrame(lFrame->NumAtoms, 0);
2155 //ugh why does everybody have to create their own cartesian format...
2156 Buffer->GetLine(LineText);
2157 while ((FindKeyWord(LineText, "[", 1) < 0)&&(Buffer->GetFilePos()<Buffer->GetFileSize())) {
2158 char token[kMaxLineLength];
2159 long atomNum, junk;
2160 CPoint3D pos;
2161 //name # atomic_# x y z
2162 int count = sscanf(LineText, "%s %ld %ld %f %f %f", token, &junk, &atomNum,
2163 &(pos.x), &(pos.y), &(pos.z));
2164 pos *= unitConv;
2165 if ((count == 6)&&((atomNum>0)&&(atomNum<120))) {
2166 lFrame->AddAtom(atomNum, pos);
2167 } else {
2168 throw DataError();
2169 }
2170 Buffer->GetLine(LineText);
2171 }
2172 Buffer->SetFilePos(0);
2173 if (Prefs->GetAutoBond())
2174 lFrame->SetBonds(Prefs, false, ProgressInd);
2175 //Now look for a basis set
2176 //MacMolPlt only supports GTOs so we don't even look for the STO keyword
2177 if (Buffer->LocateKeyWord("[GTO]", 5, -1)) {
2178 //We really don't know how many shells there will be so this is just
2179 //a rough estimate.
2180 BasisSet * lbasis = new BasisSet(lFrame->NumAtoms, 5*lFrame->NumAtoms);
2181 if (lbasis->ReadMolDenBasisSet(Buffer, lFrame->NumAtoms)) {
2182 if (MainData->Basis) delete MainData->Basis;
2183 MainData->Basis = lbasis;
2184 lbasis->Normalize(false, false);
2185 } else
2186 delete lbasis;
2187 }
2188 bool sphericalHarmonics=false;
2189 //Should look for [5D], [5D10F], [5D7F] to catch unsupported spherical harmonics
2190 if (Buffer->LocateKeyWord("[5D]", 4, -1)||Buffer->LocateKeyWord("[5D7F]", 6, -1)) {
2191 wxLogMessage(_("Spherical harmonic basis sets are not supported. Molecular orbitals will be skipped."));
2192 sphericalHarmonics = true;
2193 }
2194 if (MainData->Basis && !sphericalHarmonics) { //look for orbitals if we have a basis set
2195 if (Buffer->LocateKeyWord("[MO]", 4, -1)) {
2196 Buffer->SkipnLines(1);
2197 lFrame->ReadMolDenOrbitals(Buffer, MainData->Basis->GetNumBasisFuncs(false));
2198 }
2199 }
2200 }
2201 Buffer->SetFilePos(0);
2202 if (Buffer->LocateKeyWord("[FR-COORD]", 10, -1)) { //FR-COORD section is coordinates for frequencies
2203 //The units are bohr throughout
2204 if (lFrame->NumAtoms > 0) lFrame = MainData->AddFrame(lFrame->NumAtoms, 0);
2205 Buffer->SkipnLines(1);
2206 Buffer->GetLine(LineText);
2207 while ((LineText[0] != '[')&&(Buffer->GetFilePos()<Buffer->GetFileSize())) {
2208 unsigned char token[kMaxLineLength];
2209 CPoint3D pos;
2210 //name x y z
2211 int rdcount = sscanf(LineText, "%s %f %f %f", token, &(pos.x), &(pos.y), &(pos.z));
2212 pos *= kBohr2AngConversion;
2213 if (rdcount == 4) {
2214 long atomnum = SetAtomType(token);
2215 if (atomnum>0)
2216 lFrame->AddAtom(atomnum, pos);
2217 }
2218 Buffer->GetLine(LineText);
2219 }
2220 Buffer->SetFilePos(0);
2221 if (lFrame->NumAtoms > 0) {
2222 if (Prefs->GetAutoBond())
2223 lFrame->SetBonds(Prefs, false, ProgressInd);
2224 if (Buffer->LocateKeyWord("[FREQ]", 6, -1)) {
2225 lFrame->ParseMolDenFrequencies(Buffer, Prefs);
2226 }
2227 }
2228 }
2229
2230 return 1;
2231 }
2232
ParseECPotentials(BufferFile * Buffer)2233 long MoleculeData::ParseECPotentials(BufferFile * Buffer) {
2234 long ElectronsRemoved = 0, ProtonsRemoved=0, LinePos, atom;
2235 char LineText[kMaxLineLength];
2236 if (cFrame->NumAtoms <= 0) {
2237 Buffer->SkipnLines(1);
2238 return 0;
2239 }
2240 long * zcore = new long[cFrame->NumAtoms];
2241 if (!zcore) throw MemoryError();
2242 for (atom=0; atom<cFrame->NumAtoms; ++atom) zcore[atom]=0;
2243
2244 wxFileOffset StartPos = Buffer->GetFilePos();
2245 //This works for both ECPs and MCPs
2246 if (!Buffer->LocateKeyWord("CP RUN REMOVES", 14, -1)) {
2247 delete [] zcore;
2248 return 0;
2249 }
2250 wxFileOffset EndPos = Buffer->GetFilePos();
2251 Buffer->GetLine(LineText); //read in the number of electrons removed
2252 sscanf(&(LineText[15]),"%ld", &ElectronsRemoved);
2253
2254 //Now read in the number of protons removed from each atom
2255 Buffer->SetFilePos(StartPos);
2256 if (Buffer->LocateKeyWord("MODEL-POTENTIALS", 16, EndPos)) {
2257 while (Buffer->LocateKeyWord("THE MCP PLACED ON ATOM", 22, EndPos)) {
2258 Buffer->GetLine(LineText);
2259 LinePos = FindKeyWord(LineText, "ON ATOM", 7)+7;
2260 sscanf(&(LineText[LinePos]), "%ld", &atom);
2261 atom--;
2262 if (atom>=0 && atom<cFrame->NumAtoms) {
2263 LinePos = FindKeyWord(LineText, "REMOVES ZCORE=", 14)+14;
2264 if (LinePos>=14) {
2265 sscanf(&(LineText[LinePos]), "%ld", &(zcore[atom]));
2266 if (zcore[atom]>0 && zcore[atom] <= cFrame->Atoms[atom].GetNuclearCharge()) {
2267 Basis->NuclearCharge[atom] -= zcore[atom];
2268 ProtonsRemoved += zcore[atom];
2269 }
2270 }
2271 }
2272 }
2273 } else {
2274 while (Buffer->LocateKeyWord("PARAMETERS FOR", 14, EndPos)) {
2275 Buffer->GetLine(LineText);
2276 LinePos = FindKeyWord(LineText, "ON ATOM", 7)+7;
2277 sscanf(&(LineText[LinePos]), "%ld", &atom);
2278 atom--;
2279 if (atom>=0 && atom<cFrame->NumAtoms) {
2280 LinePos = FindKeyWord(LineText, "WITH ZCORE", 10)+10;
2281 if (LinePos>=10) {
2282 sscanf(&(LineText[LinePos]), "%ld", &(zcore[atom]));
2283 if (zcore[atom]>0 && zcore[atom] <= cFrame->Atoms[atom].GetNuclearCharge()) {
2284 Basis->NuclearCharge[atom] -= zcore[atom];
2285 ProtonsRemoved += zcore[atom];
2286 }
2287 } else {
2288 LinePos = FindKeyWord(LineText, "ARE THE SAME AS ATOM", 20)+20;
2289 if (LinePos>=20) {
2290 long OtherAtom;
2291 sscanf(&(LineText[LinePos]), "%ld", &OtherAtom);
2292 OtherAtom --;
2293 if (OtherAtom>=0 && OtherAtom<atom) {
2294 zcore[atom] = zcore[OtherAtom];
2295 Basis->NuclearCharge[atom] -= zcore[atom];
2296 ProtonsRemoved += zcore[atom];
2297 }
2298 }
2299 }
2300 }
2301 }
2302 }
2303 delete [] zcore;
2304 if (ProtonsRemoved != ElectronsRemoved) {
2305 Basis->NuclearChargesAreValid(false);
2306 // MessageAlert("Parse Error while reading ECP Potential Data. Use with caution!");
2307 }
2308 return ElectronsRemoved;
2309 }
ParseTinkerCoordinates(BufferFile * Buffer)2310 long MoleculeData::ParseTinkerCoordinates(BufferFile *Buffer) {
2311 char LineText[kMaxLineLength];
2312
2313 Frame * lFrame = cFrame;
2314 if (!Buffer->LocateKeyWord("Cartesian Coordinates of Atoms in Bulk Model", 44)) {
2315 return 0;
2316 }
2317 //Grab the tinker coordinate output
2318
2319 Buffer->SkipnLines(3);
2320 wxFileOffset StartPos = Buffer->GetFilePos();
2321 if (!(Buffer->LocateKeyWord("-----------", 11, -1))) throw DataError();
2322 wxFileOffset test = Buffer->GetFilePos() - StartPos;
2323 Buffer->SetFilePos(StartPos);
2324 long numlines = Buffer->GetNumLines(test) - 1;
2325 if (numlines > 0) {
2326 if (!SetupFrameMemory(numlines, 0)) throw std::bad_alloc();
2327 } else {
2328 wxLogMessage(_("Unable to locate Tinker coordinates in file."));
2329 throw DataError();
2330 }
2331 for (long i=0; i<numlines; ++i) {
2332 long linenum;
2333 CPoint3D position;
2334 unsigned char Label[kMaxLineLength];
2335
2336 Buffer->GetLine(LineText);
2337 int scannum = sscanf(LineText, "%ld %s %f %f %f", &linenum, Label, &(position.x),
2338 &(position.y), &(position.z));
2339 if (scannum != 5) {
2340 wxLogMessage(_("Error encountered while parsing coordinates."));
2341 throw DataError();
2342 }
2343 long atomtype = SetAtomType(Label);
2344 mpAtom * newAtom = lFrame->AddAtom(atomtype, position);
2345 if (newAtom) newAtom->IsSIMOMMAtom(true);
2346 }
2347 return 1;
2348 }
ParseSIMMOMLogFile(BufferFile * Buffer,long EnergyPos)2349 long MolDisplayWin::ParseSIMMOMLogFile(BufferFile *Buffer, long EnergyPos) {
2350 char LineText[kMaxLineLength];
2351
2352 Frame * lFrame = MainData->cFrame;
2353 if (!Buffer->LocateKeyWord("Cartesian Coordinates of Atoms in Bulk Model", 44, EnergyPos)) {
2354 return 0;
2355 }
2356 //Grab the tinker coordinate output from the top of the file
2357 ProgressInd->ChangeText("Reading Tinker Coordinates");
2358 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
2359 {throw UserCancel();}
2360
2361 Buffer->SkipnLines(3);
2362 wxFileOffset StartPos = Buffer->GetFilePos();
2363 if (!(Buffer->LocateKeyWord("-----------", 11, -1))) throw DataError();
2364 wxFileOffset test = Buffer->GetFilePos() - StartPos;
2365 Buffer->SetFilePos(StartPos);
2366 long numlines = Buffer->GetNumLines(test) - 1;
2367 if (numlines > 0) {
2368 if (!MainData->SetupFrameMemory(numlines, 0)) throw std::bad_alloc();
2369 } else {
2370 wxLogMessage(_("Unable to locate Tinker coordinates in file."));
2371 throw DataError();
2372 }
2373 for (long i=0; i<numlines; ++i) {
2374 long linenum;
2375 CPoint3D position;
2376 unsigned char Label[kMaxLineLength];
2377
2378 Buffer->GetLine(LineText);
2379 int scannum = sscanf(LineText, "%ld %s %f %f %f", &linenum, Label, &(position.x),
2380 &(position.y), &(position.z));
2381 if (scannum != 5) {
2382 wxLogMessage(_("Error encountered while parsing coordinates."));
2383 throw DataError();
2384 }
2385 long atomtype = SetAtomType(Label);
2386 mpAtom * newAtom = lFrame->AddAtom(atomtype, position);
2387 if (newAtom) newAtom->IsSIMOMMAtom(true);
2388 }
2389 //Now add the full ab initio atoms
2390 if (Buffer->LocateKeyWord("COORDINATES (BOHR)", 16, -1)) { //first normal (ab initio) atoms
2391 ProgressInd->ChangeText("Reading Coordinates");
2392 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
2393 { AbortOpen("File open canceled by user"); return 0;}
2394
2395 Buffer->SkipnLines(2);
2396 StartPos = Buffer->GetFilePos();
2397 test = Buffer->FindBlankLine() - StartPos;
2398 numlines = Buffer->GetNumLines(test);
2399 if (numlines > 0) {
2400 if (!MainData->SetupFrameMemory(numlines+lFrame->NumAtoms, 0)) throw MemoryError();
2401 } else {
2402 wxLogMessage(_("Unable to locate coordinates in the file."));
2403 throw DataError();
2404 }
2405 if (!ParseGLogLine(Buffer, lFrame, numlines, 0, &(MainData->MaxSize))) {
2406 wxLogMessage(_("Unable to interpret coordinates."));
2407 throw DataError();
2408 }
2409 lFrame->toggleAbInitioVisibility();
2410 }
2411 if (Prefs->GetAutoBond())
2412 lFrame->SetBonds(Prefs, false, ProgressInd);
2413 //attempt to read in the atomic basis set
2414 if (Buffer->LocateKeyWord("ATOMIC BASIS SET", 16)) {
2415 ProgressInd->ChangeText("Reading atomic basis set");
2416 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
2417 { throw UserCancel();}
2418 try {
2419 MainData->ParseGAMESSBasisSet(Buffer);
2420 BasisSet * Basis = MainData->Basis;
2421 if (Basis) { //generate the nuclear charge array
2422 if (Basis->NuclearCharge[0] == -1) {
2423 if (MainData->cFrame->NumAtoms == Basis->MapLength) {
2424 //for the purpose of the basis set, set the charge of mm atoms to 0
2425 for (long iatom=0; iatom<MainData->cFrame->NumAtoms; ++iatom) {
2426 if (! MainData->cFrame->Atoms[iatom].IsSIMOMMAtom() )
2427 Basis->NuclearCharge[iatom] = MainData->cFrame->Atoms[iatom].GetNuclearCharge();
2428 else
2429 Basis->NuclearCharge[iatom] = 0;
2430 }
2431 }
2432 }
2433 }
2434 }
2435 catch (MemoryError) {
2436 if (MainData->Basis) delete MainData->Basis;
2437 MainData->Basis = NULL;
2438 MessageAlert("Insufficient Memory to read the Basis Set.");
2439 }
2440 catch (std::bad_alloc) {
2441 if (MainData->Basis) delete MainData->Basis;
2442 MainData->Basis = NULL;
2443 MessageAlert("Insufficient Memory to read the Basis Set.");
2444 }
2445 catch (DataError) {
2446 MessageAlert("An error occured while reading the basis set, basis set skipped.");
2447 if (MainData->Basis) delete MainData->Basis;
2448 MainData->Basis = NULL;
2449 }
2450 }
2451
2452 if (Buffer->LocateKeyWord("QM+MM Energy (Hartree):", 23)) {
2453 Buffer->GetLine(LineText);
2454 double FrameEnergy;
2455 sscanf(&(LineText[24]), "%lf", &FrameEnergy);
2456 lFrame->Energy = FrameEnergy;
2457 }
2458
2459 //Read in normal modes, if present
2460 MainData->cFrame->ParseNormalModes(Buffer, ProgressInd, Prefs);
2461
2462 return 1;
2463 }
OpenGAMESSlog(BufferFile * Buffer,bool Append,long flip,float offset)2464 long MolDisplayWin::OpenGAMESSlog(BufferFile *Buffer, bool Append, long flip, float offset) {
2465 Frame * lpFrame;
2466 long test=0, numlines=0, OccupiedOrbCount=0, NumFragmentAtoms=0,
2467 NumOccAlpha=0, NumOccBeta=0, NumBetaUHFOrbs=0, LinePos,
2468 NumCoreOrbs, NumOpenOrbs, NumGVBPairs,
2469 ReadMP2Orbitals=1;
2470 wxFileOffset EnergyPos, NextFinalPos, SavedPos, StartPos;
2471 float *Occupancy = NULL;
2472 bool KeyWordFound, SIMOMM=false;
2473 char LineText[kMaxLineLength], token[kMaxLineLength];
2474 BufferFile * DatBuffer=NULL;
2475
2476 ProgressInd->ChangeText("Reading GAMESS log file...");
2477 Frame * lFrame = MainData->cFrame;
2478
2479 EnergyPos = -1;
2480 NextFinalPos = -1;
2481 //First Skip over all of the input card lines, the lines are near the beginning of the file and one after another
2482 while (Buffer->LocateKeyWord("INPUT CARD>", 11, (Buffer->GetFilePos()+50000)))
2483 Buffer->SkipnLines(1);
2484 wxFileOffset HeaderEndPos = Buffer->GetFilePos(); //We don't care about anything earlier than this pos.
2485 // Buffer->LocateKeyWord("RUN TITLE", 9); //find and skip over run title since
2486 // Buffer->SkipnLines(3); //it can contain any arbitrary text
2487 // if (Buffer->LocateKeyWord("FINAL", 5)) {//locate initial energy since all options are before it
2488 // EnergyPos = Buffer->GetFilePos();
2489 // Buffer->SetFilePos(HeaderEndPos);
2490 // }
2491 std::vector<std::pair <std::string, int> > OptKeywords; //search tokens for optimizations
2492 OptKeywords.push_back(make_pair (std::string("BEGINNING GEOMETRY SEARCH POINT"), 0));
2493 OptKeywords.push_back(make_pair (std::string("1NSERCH"), 1));
2494
2495 if (Append) {
2496 Buffer->LocateKeyWord("RUN TITLE", 9); //find and skip over run title since
2497 Buffer->SkipnLines(3); //it can contain any arbitrary text
2498 if (Buffer->LocateFinalEnergy()) {//locate initial energy since all options are before it
2499 EnergyPos = Buffer->GetFilePos();
2500 Buffer->SetFilePos(HeaderEndPos);
2501 }
2502 if (!MainData->InputOptions) throw MemoryError();
2503 //Determine the number of occupied alpha and beta orbitals
2504 if (Buffer->LocateKeyWord("NUMBER OF OCCUPIED ORBITALS (ALPHA)", 35, EnergyPos)) {
2505 Buffer->GetLine(LineText);
2506 LinePos = FindKeyWord(LineText, "=", 1) + 1;
2507 sscanf(&(LineText[LinePos]),"%ld", &NumOccAlpha);
2508 }
2509 if (Buffer->LocateKeyWord("NUMBER OF OCCUPIED ORBITALS (BETA )", 35, EnergyPos)) {
2510 Buffer->GetLine(LineText);
2511 LinePos = FindKeyWord(LineText, "=", 1) + 1;
2512 sscanf(&(LineText[LinePos]),"%ld", &NumOccBeta);
2513 }
2514 SavedPos = Buffer->GetFilePos();
2515 //Check for ECP/MCP type run which reduces the number of occupied orbitals
2516 if (Buffer->LocateKeyWord("CP RUN REMOVES", 14, EnergyPos)) {
2517 Buffer->GetLine(LineText); //read in the number of electrons removed
2518 sscanf(&(LineText[15]),"%ld", &test);
2519 test /= 2;
2520 NumOccAlpha -= test;
2521 if (NumOccAlpha < 0) NumOccAlpha = 0; //Oops!
2522 if (NumOccBeta) NumOccBeta -= test;
2523 if (NumOccBeta<0) NumOccBeta = 0;
2524 Buffer->SetFilePos(SavedPos);
2525 }
2526 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_MCSCF) { //Calculate the # of occupied MOs by parsing the DRT info
2527 if (Buffer->LocateKeyWord("GUGA DISTINCT ROW TABLE", 23, EnergyPos)) {
2528 long nfzc=0, ndoc=0, nmcc=0, naos=0, nbos=0, nalp=0, nval=0;
2529 if (Buffer->LocateKeyWord("NFZC=",5, EnergyPos)) {
2530 Buffer->GetLine(LineText);
2531 sscanf(&(LineText[6]), "%ld NDOC= %ld", &nfzc, &ndoc);
2532 Buffer->GetLine(LineText);
2533 sscanf(LineText, " NMCC= %ld NAOS= %ld", &nmcc, &naos);
2534 Buffer->GetLine(LineText);
2535 sscanf(LineText, " NBOS= %ld", &nbos);
2536 Buffer->GetLine(LineText);
2537 sscanf(LineText, " NALP= %ld", &nalp);
2538 Buffer->GetLine(LineText);
2539 sscanf(LineText, " NVAL= %ld", &nval);
2540 OccupiedOrbCount = nfzc + ndoc + nmcc + naos + nbos + nalp + nval;
2541 }
2542 }//GAMESS wasn't nice enough to punch out the # of occupied MO's
2543 if (!OccupiedOrbCount) OccupiedOrbCount = MainData->GetNumBasisFunctions();
2544 NumOccAlpha = OccupiedOrbCount; //setup for localized orbs
2545 }
2546 // test = MainData->InputOptions->Control->SetSCFType(&(LineText[LinePos]));
2547 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_UHF)
2548 NumBetaUHFOrbs = NumOccBeta; //Only seperate Beta spin orbs for UHF wavefunctions
2549 else NumOccBeta = 0;
2550 if (IRCRun==MainData->InputOptions->Control->GetRunType())
2551 return this->OpenGAMESSIRCLog(Buffer, flip, offset, NumOccAlpha, NumOccBeta, NumFragmentAtoms);
2552 if (DRCRun==MainData->InputOptions->Control->GetRunType())
2553 return this->OpenGAMESSDRC(Buffer, true, Append, flip,offset);
2554 else
2555 while (lFrame->NextFrame) lFrame = lFrame->NextFrame;
2556 if (MainData->InputOptions->Control->GetRunType() == GLOBOPRun)
2557 return OpenGAMESSGlobOpLog(Buffer, NumOccAlpha, NumOccBeta, NumFragmentAtoms);
2558 } else {
2559 MainData->InputOptions = new InputData;
2560 if (!MainData->InputOptions) throw MemoryError();
2561 enum {
2562 final=0,
2563 headerEnd,
2564 basisOptions,
2565 runTitle,
2566 pointGroup,
2567 QMMM,
2568 coords,
2569 EFRAG,
2570 basisSet,
2571 molCharge,
2572 multiplicity,
2573 occAlphaOrbs,
2574 occBetaOrbs,
2575 ECPoptions,
2576 gridDFT,
2577 gridFreeDFT,
2578 controlOptions,
2579 systemOptions,
2580 GVBOptions,
2581 abnormalTerm
2582 };
2583 std::vector<std::pair <std::string, int> > HeaderKeywords;
2584 // HeaderKeywords.push_back(make_pair (std::string("FINAL"), (int) final));
2585 HeaderKeywords.push_back(make_pair (std::string("DONE SETTING UP THE RUN"), (int) headerEnd));
2586 HeaderKeywords.push_back(make_pair (std::string("BASIS OPTIONS"), (int) basisOptions));
2587 HeaderKeywords.push_back(make_pair (std::string("RUN TITLE"), (int) runTitle));
2588 HeaderKeywords.push_back(make_pair (std::string("POINT GROUP"), (int) pointGroup));
2589 HeaderKeywords.push_back(make_pair (std::string("QMMM PROCEDURE IS ON"), (int) QMMM));
2590 HeaderKeywords.push_back(make_pair (std::string("COORDINATES (BOHR)"), (int) coords));
2591 HeaderKeywords.push_back(make_pair (std::string("READING $EFRAG GROUP"), (int) EFRAG));
2592 HeaderKeywords.push_back(make_pair (std::string("ATOMIC BASIS SET"), (int) basisSet));
2593 HeaderKeywords.push_back(make_pair (std::string("CHARGE OF MOLECULE"), (int) molCharge));
2594 HeaderKeywords.push_back(make_pair (std::string("MULTIPLICITY"), (int) multiplicity));
2595 HeaderKeywords.push_back(make_pair (std::string("NUMBER OF OCCUPIED ORBITALS (ALPHA)"), (int) occAlphaOrbs));
2596 HeaderKeywords.push_back(make_pair (std::string("NUMBER OF OCCUPIED ORBITALS (BETA )"), (int) occBetaOrbs));
2597 HeaderKeywords.push_back(make_pair (std::string("ECP POTENTIALS"), (int) ECPoptions));
2598 HeaderKeywords.push_back(make_pair (std::string("MODEL-POTENTIALS"), (int) ECPoptions));
2599 HeaderKeywords.push_back(make_pair (std::string("GRID-BASED DFT"), (int) gridDFT));
2600 HeaderKeywords.push_back(make_pair (std::string("MODEL-POTENTIALS"), (int) gridFreeDFT));
2601 HeaderKeywords.push_back(make_pair (std::string("CONTRL OPTIONS"), (int) controlOptions));
2602 HeaderKeywords.push_back(make_pair (std::string("JOB OPTIONS"), (int) controlOptions));
2603 HeaderKeywords.push_back(make_pair (std::string("SYSTEM OPTIONS"), (int) systemOptions));
2604 HeaderKeywords.push_back(make_pair (std::string("EXECUTION OF GAMESS TERMINATED -ABNORMALLY- AT"), (int) abnormalTerm));
2605
2606 bool headerDone=false;
2607 bool controlOptionsFound = false;
2608 while (! Buffer->Eof() && ! headerDone) {
2609 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
2610 { throw UserCancel();}
2611 int kw;
2612 if (-1 < (kw = Buffer->LocateKeyWord(HeaderKeywords))) {
2613 wxFileOffset keywordPosition = Buffer->GetFilePos();
2614 switch (kw) {
2615 case final:
2616 headerDone = true;
2617 EnergyPos = Buffer->GetFilePos();
2618 break;
2619 case headerEnd:
2620 //Until recently this was printed out at the beginning of the header output - useless!
2621 //To account for that only consider this done if we've found the coordinates
2622 if (lFrame->NumAtoms > 0) headerDone = true;
2623 Buffer->SkipnLines(1);
2624 break;
2625 case basisOptions:
2626 // KeyWordFound = Buffer->LocateKeyWord("BASIS OPTIONS", 13, EnergyPos);
2627 // if (KeyWordFound) { //Read in the basis set information (for user reference)
2628 ProgressInd->ChangeText("Reading Basis information");
2629 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
2630 { throw UserCancel();}
2631 MainData->ReadBasisOptions(Buffer);
2632 // }
2633 break;
2634 case runTitle:
2635 // if (Buffer->LocateKeyWord("RUN TITLE", 9, EnergyPos)) { //Read the 1 line run label
2636 Buffer->SkipnLines(2);
2637 Buffer->GetLine(LineText);
2638 MainData->InputOptions->Data->SetTitle(LineText, strlen(LineText));
2639 // }
2640 break;
2641 case pointGroup:
2642 // if (Buffer->LocateKeyWord("POINT GROUP", 11, EnergyPos)) { //Setup molecular point group
2643 Buffer->GetLine(LineText);
2644 LinePos = FindKeyWord(LineText, "MOLECULE IS", 11);
2645 if (LinePos > -1) {
2646 sscanf(&(LineText[LinePos+12]), "%s", token);
2647 MainData->InputOptions->Data->SetPointGroup(token);
2648 }
2649
2650 Buffer->GetLine(LineText);
2651 LinePos = FindKeyWord(LineText, "AXIS IS", 7);
2652 if (LinePos > -1) {
2653 sscanf(&(LineText[LinePos+8]),"%ld", &test);
2654 MainData->InputOptions->Data->SetPointGroupOrder(test);
2655 }
2656 // }
2657 break;
2658 case QMMM:
2659 // Buffer->SetFilePos(HeaderEndPos);
2660 // if (Buffer->LocateKeyWord("QMMM PROCEDURE IS ON", 20, EnergyPos)) {
2661 //If this is a simmom type run then switch to that routine since the format is
2662 //significantly different
2663 // return (ParseSIMMOMLogFile(Buffer, EnergyPos));
2664 SIMOMM=true;
2665 ProgressInd->ChangeText("Reading Tinker Coordinates");
2666 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
2667 {throw UserCancel();}
2668 MainData->ParseTinkerCoordinates(Buffer);
2669 //The ab initio atoms will be added below
2670 // }
2671 break;
2672 case coords:
2673 //locate the input set of coordinates (present in every file)
2674 // if (Buffer->LocateKeyWord("COORDINATES (BOHR)", 16, EnergyPos)) { //first normal (ab initio) atoms
2675 ProgressInd->ChangeText("Reading Coordinates");
2676 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
2677 { AbortOpen("File open canceled by user"); return 0;}
2678
2679 Buffer->SkipnLines(2);
2680 StartPos = Buffer->GetFilePos();
2681 test = Buffer->FindBlankLine() - StartPos;
2682 numlines = Buffer->GetNumLines(test);
2683 if (numlines > 0) {
2684 if (!MainData->SetupFrameMemory(numlines+lFrame->NumAtoms, 0)) throw MemoryError();
2685 } else {
2686 wxLogMessage(_("Unable to locate coordinates in the file."));
2687 throw DataError();
2688 }
2689 if (!ParseGLogLine(Buffer, lFrame, numlines, 0, &(MainData->MaxSize))) {
2690 wxLogMessage(_("Unable to interpret coordinates."));
2691 throw DataError();
2692 }
2693 // }
2694 break;
2695 case EFRAG:
2696 // StartPos = Buffer->GetFilePos(); //next look for fragments
2697 // if (Buffer->LocateKeyWord("READING $EFRAG GROUP", 20, EnergyPos)) { //ughh fragments!
2698 NumFragmentAtoms = MainData->ReadInitialFragmentCoords(Buffer);
2699 // Buffer->SetFilePos(StartPos);
2700 // }
2701 break;
2702 case basisSet:
2703 //Read in the atomic basis set (if present) and keep it in case we find MO vectors later
2704 //if it is not located and read in correctly MO vectors will also be skipped
2705 // if (Buffer->LocateKeyWord("ATOMIC BASIS SET", 16, EnergyPos)) {
2706 {
2707 ProgressInd->ChangeText("Reading atomic basis set");
2708 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
2709 { throw UserCancel();}
2710 try {
2711 MainData->ParseGAMESSBasisSet(Buffer);
2712 BasisSet * Basis = MainData->Basis;
2713 if (Basis && SIMOMM) { //generate the nuclear charge array
2714 if (Basis->NuclearCharge[0] == -1) {
2715 if (MainData->cFrame->NumAtoms == Basis->MapLength) {
2716 //for the purpose of the basis set, set the charge of mm atoms to 0
2717 for (long iatom=0; iatom<MainData->cFrame->NumAtoms; ++iatom) {
2718 if (! MainData->cFrame->Atoms[iatom].IsSIMOMMAtom() )
2719 Basis->NuclearCharge[iatom] = MainData->cFrame->Atoms[iatom].GetNuclearCharge();
2720 else
2721 Basis->NuclearCharge[iatom] = 0;
2722 }
2723 }
2724 }
2725 }
2726 }
2727 catch (MemoryError) {
2728 if (MainData->Basis) delete MainData->Basis;
2729 MainData->Basis = NULL;
2730 MessageAlert("Insufficient Memory to read the Basis Set.");
2731 }
2732 catch (std::bad_alloc) {
2733 if (MainData->Basis) delete MainData->Basis;
2734 MainData->Basis = NULL;
2735 MessageAlert("Insufficient Memory to read the Basis Set.");
2736 }
2737 catch (DataError) {
2738 MessageAlert("An error occured while reading the basis set, basis set skipped.");
2739 if (MainData->Basis) delete MainData->Basis;
2740 MainData->Basis = NULL;
2741 }
2742 }
2743 break;
2744 case molCharge:
2745 //Read in charge and multiplicity
2746 // if (Buffer->LocateKeyWord("CHARGE OF MOLECULE", 18, EnergyPos)) {
2747 Buffer->GetLine(LineText);
2748 LinePos = FindKeyWord(LineText, "=", 1) + 1;
2749 long charge;
2750 sscanf(&(LineText[LinePos]),"%ld", &charge);
2751 MainData->InputOptions->Control->SetCharge(charge);
2752 // }
2753 break;
2754 case multiplicity:
2755 //There are now two forms of this, "SPIN MULTIPLICITY" and "STATE MULTIPLICITY"
2756 //however, either should appear soon after the CHARGE.
2757 // if (Buffer->LocateKeyWord("MULTIPLICITY", 12, Buffer->GetFilePos()+100)) {
2758 Buffer->GetLine(LineText);
2759 LinePos = FindKeyWord(LineText, "=", 1) + 1;
2760 long Multiplicity;
2761 sscanf(&(LineText[LinePos]),"%ld", &Multiplicity);
2762 MainData->InputOptions->Control->SetMultiplicity(Multiplicity);
2763 // }
2764 break;
2765 case occAlphaOrbs:
2766 //Determine the number of occupied alpha and beta orbitals
2767 // if (Buffer->LocateKeyWord("NUMBER OF OCCUPIED ORBITALS (ALPHA)", 35, EnergyPos)) {
2768 Buffer->GetLine(LineText);
2769 LinePos = FindKeyWord(LineText, "=", 1) + 1;
2770 sscanf(&(LineText[LinePos]),"%ld", &NumOccAlpha);
2771 // }
2772 break;
2773 case occBetaOrbs:
2774 // if (Buffer->LocateKeyWord("NUMBER OF OCCUPIED ORBITALS (BETA )", 35, EnergyPos)) {
2775 Buffer->GetLine(LineText);
2776 LinePos = FindKeyWord(LineText, "=", 1) + 1;
2777 sscanf(&(LineText[LinePos]),"%ld", &NumOccBeta);
2778 // }
2779 break;
2780 case ECPoptions:
2781 // SavedPos = Buffer->GetFilePos();
2782 //Check for ECP type run which reduces the number of occupied orbitals
2783 // if (Buffer->LocateKeyWord("ECP POTENTIALS", 14, EnergyPos)||
2784 // Buffer->LocateKeyWord("MODEL-POTENTIALS", 16, EnergyPos)) {
2785 test = MainData->ParseECPotentials(Buffer);
2786 test /= 2;
2787 NumOccAlpha -= test;
2788 if (NumOccAlpha < 0) NumOccAlpha = 0; //Oops!
2789 if (NumOccBeta) NumOccBeta -= test;
2790 if (NumOccBeta<0) NumOccBeta = 0;
2791 // Buffer->SetFilePos(SavedPos);
2792 // }
2793 break;
2794 case gridDFT:
2795 //DFT options
2796 // if (Buffer->LocateKeyWord("GRID-BASED DFT", 14, EnergyPos))
2797 {
2798 Buffer->SkipnLines(2);
2799 Buffer->GetLine(LineText);
2800 char DFTTYP[kMaxLineLength];
2801 if (ReadStringKeyword(LineText, "DFTTYP", DFTTYP)) {
2802 MainData->InputOptions->DFT.SetFunctional(DFTTYP);
2803 if (MainData->InputOptions->DFT.GetFunctional() > 0)
2804 MainData->InputOptions->Control->UseDFT(true);
2805 else
2806 wxLogMessage(_("Unknown DFTTYP detected, ignored."));
2807 }
2808 }
2809 break;
2810 case gridFreeDFT:
2811 // else if (Buffer->LocateKeyWord("GRID-FREE DFT", 13, EnergyPos))
2812 {
2813 Buffer->SkipnLines(2);
2814 Buffer->GetLine(LineText);
2815 char DFTTYP[kMaxLineLength];
2816 MainData->InputOptions->DFT.SetMethodGrid(false);
2817 if (ReadStringKeyword(LineText, "DFTTYP", DFTTYP)) {
2818 MainData->InputOptions->DFT.SetFunctional(DFTTYP);
2819 if (MainData->InputOptions->DFT.GetFunctional() > 0)
2820 MainData->InputOptions->Control->UseDFT(true);
2821 else
2822 wxLogMessage(_("Unknown DFTTYP detected, ignored."));
2823 }
2824 }
2825 break;
2826 case controlOptions:
2827 //Now read other Control options
2828 // if (!Buffer->LocateKeyWord("CONTRL OPTIONS", 14, EnergyPos)) {
2829 // // $CONTRL OPTIONS used to be JOB OPTIONS so check for it too
2830 // if (!Buffer->LocateKeyWord("JOB OPTIONS", 11, EnergyPos)) {
2831 // //Unable to locate the job options, perhaps the run terminated abnormally?
2832 // if (Buffer->LocateKeyWord("EXECUTION OF GAMESS TERMINATED -ABNORMALLY- AT", 46))
2833 // wxLogMessage(_("GAMESS terminated abnormally. Please check the log file for details."));
2834 // wxLogMessage(_("Unable to locate run options."));
2835 // return 0;
2836 // }
2837 // }
2838 MainData->ReadControlOptions(Buffer);
2839 controlOptionsFound = true;
2840 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_GVB)
2841 HeaderKeywords.push_back(make_pair (std::string("ROHF-GVB INPUT PARAMETERS"), (int) GVBOptions));
2842 break;
2843 case systemOptions:
2844 //System group is immediately after the control group
2845 // if (Buffer->LocateKeyWord("SYSTEM OPTIONS", 14, EnergyPos)) {
2846 MainData->InputOptions->System->ReadSystemOptions(Buffer);
2847 // }
2848 break;
2849 case GVBOptions:
2850 Buffer->SkipnLines(3);
2851 Buffer->GetLine(LineText);
2852 sscanf(LineText, " NORB =%ld NCO =%ld", &test, &NumCoreOrbs);
2853 MainData->InputOptions->SCF->SetGVBNumCoreOrbs(NumCoreOrbs);
2854 NumOccAlpha = test;
2855 Buffer->GetLine(LineText);
2856 sscanf(LineText, " NPAIR =%ld NSETO =%ld", &NumGVBPairs, &NumOpenOrbs);
2857 MainData->InputOptions->SCF->SetGVBNumPairs(NumGVBPairs);
2858 if (NumOpenOrbs>0) {
2859 //If there are Open Shells we need to parse the degeneracy of each shell
2860 //This is a space separated list starting with NO =
2861 //In theory it could be more than a line, but that is highly unlikely
2862 Buffer->GetLine(LineText);
2863 int nchar = 0;
2864 if (sscanf(LineText, " NO =%n", &nchar) == 0) {
2865 for (int ishell=0; ishell<NumOpenOrbs; ishell++) {
2866 int nchar2=0;
2867 long shellDeg;
2868 if (sscanf(&(LineText[nchar]), "%ld%n", &shellDeg, &nchar2) == 1) {
2869 nchar += nchar2;
2870 MainData->InputOptions->SCF->AddGVBOpenShellDeg(shellDeg);
2871 } else
2872 break;
2873 }
2874 }
2875 //Set this after reading in NO so no need to clear the NO array
2876 MainData->InputOptions->SCF->SetGVBNumOpenShells(NumOpenOrbs);
2877 }
2878 Occupancy = new float[MainData->GetNumBasisFunctions()];
2879 if (!Occupancy) throw MemoryError();
2880 for (test=0; test<MainData->GetNumBasisFunctions(); ++test) Occupancy[test] = 0.0f;
2881 for (test=0; test<NumCoreOrbs; ++test) Occupancy[test] = 2.0f;
2882 if (NumOpenOrbs > 0) { //Parse the occupancies of the open shells
2883 if (Buffer->LocateKeyWord("F VECTOR (OCCUPANCIES)", 23)) {
2884 //Next find the first row indicating the doubly occupied orbitals
2885 Buffer->SkipnLines(1);
2886 bool foundPos=false;
2887 int lineCount=0;
2888 while (!foundPos) {
2889 int test;
2890 Buffer->GetLine(LineText);
2891 sscanf(LineText, "%d", &test);
2892 if (test == 1) { //If there are no cores then the first line is needed below.
2893 if (NumCoreOrbs<=0) {
2894 Buffer->BackupnLines(1);
2895 }
2896 foundPos = true;
2897 }
2898 lineCount++;
2899 if (lineCount > 10) {
2900 wxLogMessage(_("Warning: Unable to parse GVB F Vector Occupancies."));
2901 break;
2902 }
2903 }
2904 if (foundPos) {
2905 int iorb = NumCoreOrbs;
2906 for (int nShell=0; nShell<NumOpenOrbs; ++nShell) {
2907 Buffer->GetLine(LineText);
2908 float occTemp;
2909 sscanf(LineText, "%ld %f", &test, &occTemp);
2910 for (int jj=0; jj<MainData->InputOptions->SCF->GetGVBOpenShellDeg(nShell); jj++) {
2911 Occupancy[iorb] = occTemp * 2; //occupancies are listed as % of orbital filled
2912 iorb++;
2913 }
2914 }
2915 }
2916 }
2917 }
2918 // }
2919 break;
2920 case abnormalTerm:
2921 // if (Buffer->LocateKeyWord("EXECUTION OF GAMESS TERMINATED -ABNORMALLY- AT", 46))
2922 wxLogMessage(_("GAMESS terminated abnormally. Please check the log file for details."));
2923 return 0;
2924 break;
2925 }
2926 //If still positioned at the keyword, must advance or there will be a loop.
2927 if (keywordPosition == Buffer->GetFilePos()) Buffer->SkipnLines(1);
2928 } else break;
2929 }
2930 if (lFrame->NumAtoms <= 0) { //initial coordinates not found! Abort!
2931 wxLogMessage(_("Unable to locate coordinates in the file."));
2932 throw DataError();
2933 }
2934 if (Prefs->GetAutoBond())
2935 lFrame->SetBonds(Prefs, false, ProgressInd);
2936
2937 if (!controlOptionsFound) wxLogMessage(_("Unable to locate run options. Attempting to continue"));
2938
2939 //Now that the $control options are read in normalize the basis set (normf and normp are needed)
2940 if (MainData->Basis) MainData->Basis->Normalize(MainData->InputOptions->Control->GetNormP(),
2941 MainData->InputOptions->Control->GetNormF());
2942 //plot the rms gradient by default for run types: gradient, optimize, and sadpoint
2943 if ((MainData->InputOptions->Control->GetRunType()==4)||
2944 // (MainData->InputOptions->Control->GetRunType()==2)|| could add gradient, but output is different
2945 (MainData->InputOptions->Control->GetRunType()==6)) {
2946 GraphOptions * lPOpts = Prefs->GetGraphOptions();
2947 EnergyOptions * lEOpts = Prefs->GetEnergyOptions();
2948 lEOpts->SetPlotOther(true);
2949 lPOpts->SetPlotRMSGradient(true);
2950 }
2951 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_UHF)
2952 //Only seperate Beta spin orbs for UHF wavefunctions
2953 NumBetaUHFOrbs = MainData->GetNumBasisFunctions();
2954 else if (MainData->InputOptions->Control->GetSCFType()!=GAMESS_ROHF)
2955 NumOccBeta = 0;
2956
2957 if (MainData->InputOptions->Control->GetRunType() == GLOBOPRun)
2958 return OpenGAMESSGlobOpLog(Buffer, NumOccAlpha, NumOccBeta, NumFragmentAtoms);
2959
2960 HeaderEndPos = Buffer->GetFilePos();
2961 if (Buffer->LocateFinalEnergy()) {//locate initial energy
2962 EnergyPos = Buffer->GetFilePos();
2963 Buffer->SetFilePos(HeaderEndPos);
2964 }
2965
2966 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_MCSCF) { //Calculate the # of occupied MOs by parsing the DRT info
2967 wxFileOffset filePos = Buffer->GetFilePos();
2968 if (Buffer->LocateKeyWord("GUGA DISTINCT ROW TABLE", 23, EnergyPos)) {
2969 long nfzc=0, ndoc=0, nmcc=0, naos=0, nbos=0, nalp=0, nval=0;
2970 if (Buffer->LocateKeyWord("NFZC=",5)) {
2971 Buffer->GetLine(LineText);
2972 sscanf(&(LineText[6]), "%ld NDOC= %ld", &nfzc, &ndoc);
2973 Buffer->GetLine(LineText);
2974 sscanf(LineText, " NMCC= %ld NAOS= %ld", &nmcc, &naos);
2975 Buffer->GetLine(LineText);
2976 sscanf(LineText, " NBOS= %ld", &nbos);
2977 Buffer->GetLine(LineText);
2978 sscanf(LineText, " NALP= %ld", &nalp);
2979 Buffer->GetLine(LineText);
2980 sscanf(LineText, " NVAL= %ld", &nval);
2981 OccupiedOrbCount = nfzc + ndoc + nmcc + naos + nbos + nalp + nval;
2982 }
2983 } else if ((Buffer->LocateKeyWord("AMES LABORATORY DETERMINANTAL FULL CI", 37,
2984 EnergyPos))||(Buffer->LocateKeyWord("DIRECT DETERMINANT ORMAS-CI INPUT SORTER", 40, EnergyPos))) {
2985 if (Buffer->LocateKeyWord("NUMBER OF OCCUPIED ORBITALS",27,800+Buffer->GetFilePos())) {
2986 Buffer->GetLine(LineText);
2987 sscanf(&(LineText[30]), " = %ld", &OccupiedOrbCount);
2988 }
2989 }//GAMESS wasn't nice enough to punch out the # of occupied MO's
2990 if (!OccupiedOrbCount) OccupiedOrbCount = MainData->GetNumBasisFunctions();
2991 NumOccAlpha = OccupiedOrbCount; //setup for localized orbs
2992 Buffer->SetFilePos(filePos); //reset the file position
2993 }
2994 //Could read GUESS options here...
2995 //Look for the initial guess orbitals in case the user requested them
2996 if (MainData->GetNumBasisFunctions() > 0) {
2997 if (Buffer->LocateKeyWord(" INITIAL GUESS ORBITALS", 28, EnergyPos)) {
2998 lFrame->ParseGAMESSGuessVectors(Buffer, MainData->GetNumBasisFunctions(),
2999 (TypeOfWavefunction)MainData->InputOptions->Control->GetSCFType(),
3000 ProgressInd);
3001 }
3002 }
3003
3004 // Switch to DRC routine if neccessary
3005 if (MainData->InputOptions->Control->GetRunType() == DRCRun) {
3006 lFrame->NumAtoms = lFrame->NumBonds = 0;
3007 return this->OpenGAMESSDRC(Buffer, true, Append, flip,offset);
3008 } else if (MainData->InputOptions->Control->GetRunType() == IRCRun) {
3009 //Confirm that the first energy is before the start of the IRC
3010 if (Buffer->LocateKeyWord("JUMPING OFF SADDLE POINT ALONG THE IMAGINARY NORMAL MODE", 55)) {
3011 wxFileOffset test = Buffer->GetFilePos();
3012 if (EnergyPos > test) {
3013 return OpenGAMESSIRCLog(Buffer, flip, offset, NumOccAlpha, NumOccBeta, NumFragmentAtoms);
3014 }
3015 }
3016 } else if (MainData->InputOptions->Control->GetRunType() == VSCFRun) {
3017 //Read in normal modes, if present
3018 if (Buffer->LocateKeyWord("NORMAL COORDINATE ANALYSIS", 25, EnergyPos))
3019 MainData->cFrame->ParseNormalModes(Buffer, ProgressInd, Prefs);
3020 }
3021
3022 if (EnergyPos > 0) {
3023 Buffer->SetFilePos(EnergyPos);
3024 Buffer->GetLine(LineText);
3025 LinePos = FindKeyWord(LineText, "ENERGY", 6);
3026 if (LinePos > -1) {
3027 int k = sscanf(&(LineText[LinePos+10]), "%lf", &(lFrame->Energy));
3028 if (k == 0) { //Crappy fragment output is different
3029 k = FindKeyWord(&(LineText[LinePos]), "=", 1);
3030 if (LinePos > -1)
3031 sscanf(&(LineText[LinePos+k+1]), "%lf", &(lFrame->Energy));
3032 }
3033 if (MainData->InputOptions->Control->GetMPLevel()) { //MP2 run so look for MP2 energy
3034 StartPos = Buffer->GetFilePos();
3035 if (Buffer->LocateKeyWord("E(MP2)=", 7)) {
3036 double mpE;
3037 Buffer->GetLine(LineText);
3038 sscanf(&(LineText[8]), "%lf", &(mpE));
3039 lFrame->Energies.push_back(EnergyValue(mpE, PT2Energy));
3040 }
3041 Buffer->SetFilePos(StartPos);
3042 }
3043 }
3044 //Attempt to read in orbitals for first geometry
3045 SavedPos = Buffer->GetFilePos();
3046 NextFinalPos = -1;
3047 if (Buffer->LocateFinalEnergy()) NextFinalPos = Buffer->GetFilePos();
3048 Buffer->SetFilePos(SavedPos);
3049 if (MainData->Basis) {
3050 try {
3051 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_MCSCF) {
3052 bool ReadOrbs = false;
3053 if (Buffer->LocateKeyWord("MCSCF NATURAL ORBITALS", 22, NextFinalPos)) {
3054 if ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos()))
3055 ReadOrbs = true;
3056 else Buffer->SetFilePos(SavedPos);
3057 } else if (Buffer->LocateKeyWord("MCSCF OPTIMIZED ORBITALS", 24, NextFinalPos)) {
3058 if ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos()))
3059 ReadOrbs = true;
3060 else Buffer->SetFilePos(SavedPos);
3061 } else if (Buffer->LocateKeyWord("-MCHF- NATURAL ORBITALS", 23, NextFinalPos)) {
3062 if ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos()))
3063 ReadOrbs = true;
3064 else Buffer->SetFilePos(SavedPos);
3065 } else if (Buffer->LocateKeyWord("-MCHF- OPTIMIZED ORBITALS", 25, NextFinalPos)) {
3066 if ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos()))
3067 ReadOrbs = true;
3068 else Buffer->SetFilePos(SavedPos);
3069 } else if (Buffer->LocateKeyWord("MOLECULAR ORBITALS", 18, NextFinalPos)) {
3070 Buffer->SetFilePos(Buffer->FindBlankLine());
3071 Buffer->SkipnLines(1);
3072 lFrame->ParseGAMESSEigenVectors(Buffer, MainData->GetNumBasisFunctions(),
3073 MainData->GetNumBasisFunctions(), 0, NumOccAlpha, NumOccBeta,
3074 (TypeOfWavefunction)(MainData->InputOptions->Control->GetSCFType()), ProgressInd);
3075 // lFrame->ExchangeEigenVectors();
3076 }
3077 if (ReadOrbs)
3078 lFrame->ParseGAMESSMCSCFVectors(Buffer, MainData->GetNumBasisFunctions(),
3079 OccupiedOrbCount, ProgressInd);
3080 } else {
3081 if (MainData->InputOptions->Control->GetSCFType() == GAMESS_GVB) {
3082 if (Buffer->LocateKeyWord("PAIR INFORMATION", 16, NextFinalPos)) {
3083 ReadGVBOccupancy(Buffer, NumGVBPairs, MainData->GetNumBasisFunctions(),
3084 Occupancy);
3085 }
3086 }
3087 // if (MainData->InputOptions->Control->GetCIType() == CI_CIS) {
3088 // //CIS output includes the EIGENVECTORS token
3089 // //I think the regular EIGENVECTORS would be before the CIS line???
3090 // long bp = Buffer->GetFilePos();
3091 // KeyWordFound = Buffer->LocateKeyWord("EIGENVECTORS", 12, NextFinalPos);
3092 // Buffer->BackupnLines(1);
3093 // if (Buffer->LocateKeyWord("CIS EIGENVALUES", 14, 80+Buffer->GetFilePos())) {
3094 // Buffer->SkipnLines(1);
3095 // KeyWordFound = Buffer->LocateKeyWord("EIGENVECTORS", 12, NextFinalPos);
3096 // if (!KeyWordFound) {
3097 // Buffer->SetFilePos(bp);
3098 // KeyWordFound = Buffer->LocateKeyWord("MOLECULAR ORBITALS", 18, NextFinalPos);
3099 // Buffer->BackupnLines(1);
3100 // if (Buffer->LocateKeyWord("# MOLECULAR ORBITALS =", 22)) {
3101 // Buffer->SkipnLines(1);
3102 // KeyWordFound = Buffer->LocateKeyWord("MOLECULAR ORBITALS", 18, NextFinalPos);
3103 // if (!KeyWordFound) Buffer->SetFilePos(bp);
3104 // }
3105 // }
3106 // }
3107 // } else {
3108 KeyWordFound = Buffer->LocateKeyWord(" EIGENVECTORS", 15, NextFinalPos);
3109 if (!KeyWordFound)
3110 KeyWordFound = Buffer->LocateKeyWord("MOLECULAR ORBITALS", 18, NextFinalPos);
3111 // }
3112 if (KeyWordFound) {
3113 //skip over the line to the start of the orbital blocks
3114 //There is always a blank line before the orbs, but there may a '---' divider line after the key line just found
3115 if ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos())) {
3116 Buffer->SetFilePos(Buffer->FindBlankLine());
3117 Buffer->SkipnLines(1);
3118 ProgressInd->ChangeText("Reading eigenvectors");
3119 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3120 { AbortOpen("File open canceled by user"); return 0;}
3121 OrbitalRec * OrbSet = lFrame->ParseGAMESSEigenVectors(Buffer, MainData->GetNumBasisFunctions(),
3122 MainData->GetNumBasisFunctions(), NumBetaUHFOrbs, NumOccAlpha, NumOccBeta,
3123 (TypeOfWavefunction)(MainData->InputOptions->Control->GetSCFType()), ProgressInd);
3124 if ((MainData->InputOptions->Control->GetSCFType() == GAMESS_GVB)&&(OrbSet!=NULL)) {
3125 //Add the Occupancy vector for GVB wavefunctions
3126 OrbSet->SetOccupancy(Occupancy, MainData->GetNumBasisFunctions());
3127 }
3128 } else Buffer->SetFilePos(SavedPos);
3129 }
3130 }
3131 if (MainData->InputOptions->Control->GetSCFType() == GAMESS_GVB) {
3132 KeyWordFound = Buffer->LocateKeyWord("GI ORBITALS", 11, NextFinalPos);
3133 if (KeyWordFound && ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos()))) {
3134 Buffer->SkipnLines(4);
3135 lFrame->ParseGVBGIOrbitals(Buffer, MainData->GetNumBasisFunctions(), NumGVBPairs, ProgressInd);
3136 }
3137 } else if (MainData->InputOptions->Control->GetSCFType() == GAMESS_UHF) {
3138 if (Buffer->LocateKeyWord("UHF NATURAL ORBITALS AND OCCUPATION NUMBERS",
3139 43, NextFinalPos)) {
3140 lFrame->ParseUHFNOs(Buffer, MainData->GetNumBasisFunctions(), ProgressInd);
3141 }
3142 }
3143 // if (MainData->InputOptions->Control->GetSCFType() == GAMESS_TDDFT) {
3144 //I don't have the right control keywords yet. Possibilities are TDDFT=EXCITE in
3145 //$CONTRL or TDPRP=.t. in $TDDFT
3146 if (Buffer->LocateKeyWord("TDDFT NATURAL ORBITALS",
3147 23, NextFinalPos)) {
3148 lFrame->ParseTDDFTNOs(Buffer, MainData->GetNumBasisFunctions(), ProgressInd);
3149 }
3150 // }
3151 if (MainData->InputOptions->Control->GetMPLevel()) {
3152 if (Buffer->LocateKeyWord("MP2 NATURAL ORBITAL OCCUPATION NUMBERS",
3153 38, NextFinalPos) && ReadMP2Orbitals) {
3154 lFrame->ReadMP2Vectors(Buffer, DatBuffer, MainData->GetNumBasisFunctions(),
3155 ProgressInd, &ReadMP2Orbitals);
3156 }
3157 }
3158 if (MainData->InputOptions->Control->GetCCType()) {
3159 if (Buffer->LocateKeyWord("EOM-CC NATURAL ORBITALS",
3160 23, NextFinalPos)) {
3161 lFrame->ParseGAMESSEOM_CC_Vectors(Buffer, MainData->GetNumBasisFunctions(), ProgressInd);
3162 }
3163 }
3164 if (MainData->InputOptions->Control->GetCIType()) { //Look for CI Natural orbitals
3165 //loop to add multiple CI NOs, one set for each eigenstate.
3166 //This would be the place to read in each eigenstate's energy
3167 if (MainData->InputOptions->Control->GetCIType() == CI_CIS) {
3168 //The spaces are important since the phrase appears elsewhere....
3169 if (Buffer->LocateKeyWord(" CIS NATURAL ORBITALS",
3170 26, NextFinalPos)) {
3171 lFrame->ParseGAMESSCIVectors(Buffer, MainData->GetNumBasisFunctions(), ProgressInd);
3172 }
3173 } else {
3174 while (Buffer->LocateKeyWord("NATURAL ORBITALS IN ATOMIC ORBITAL BASIS",
3175 40, NextFinalPos)) {
3176 lFrame->ParseGAMESSCIVectors(Buffer, MainData->GetNumBasisFunctions(), ProgressInd);
3177 }
3178 }
3179 }
3180 }
3181 catch (std::bad_alloc) {
3182 MessageAlert("Insufficient memory to read in eigenvectors.");
3183 }
3184 catch (MemoryError) {
3185 MessageAlert("Insufficient memory to read in eigenvectors.");
3186 }
3187 catch (DataError) {
3188 MessageAlert("Error reading eigenvectors, orbitals skipped.");
3189 }
3190 }
3191 //MRMP2 - Only energy is supported
3192 if ((MainData->InputOptions->Control->GetSCFType()==GAMESS_MCSCF)&&
3193 (MainData->InputOptions->Control->GetMPLevel())) { //MP2 run so look for MP2 energy
3194 if (Buffer->LocateKeyWord("TOTAL MRPT2, E(MP2) 0TH + 1ST + 2ND ORDER ENERGY", 48)) {
3195 double mpE;
3196 Buffer->GetLine(LineText);
3197 sscanf(&(LineText[51]), "%lf", &(mpE));
3198 //This should be changed to MRMP2Energy, but that isn't recognized elsewhere currently
3199 lFrame->Energies.push_back(EnergyValue(mpE, PT2Energy));
3200 }
3201 }
3202 if (SIMOMM) { //See if we have MM energies and new coords
3203 //could also grab the MM energy here
3204 if (Buffer->LocateKeyWord("QM+MM Energy (Hartree):", 23)) {
3205 Buffer->GetLine(LineText);
3206 double FrameEnergy;
3207 sscanf(&(LineText[24]), "%lf", &FrameEnergy);
3208 lFrame->Energy = FrameEnergy;
3209 }
3210 //now update the coordinates with the new MM list
3211 Frame * preserve = MainData->cFrame;
3212 lFrame = MainData->AddFrame(MainData->cFrame->NumAtoms,0);
3213 MainData->ParseTinkerCoordinates(Buffer);
3214 if (MainData->cFrame->NumAtoms > 0) {
3215 //update the coordinates in the first frame
3216 for (int iatom=0; iatom<MainData->cFrame->NumAtoms; ++iatom) {
3217 if (MainData->cFrame->Atoms[iatom].IsSIMOMMAtom()) {
3218 preserve->Atoms[iatom].Position.x = MainData->cFrame->Atoms[iatom].Position.x;
3219 preserve->Atoms[iatom].Position.y = MainData->cFrame->Atoms[iatom].Position.y;
3220 preserve->Atoms[iatom].Position.z = MainData->cFrame->Atoms[iatom].Position.z;
3221 }
3222 }
3223 }
3224 // delete off the temporary frame
3225 MainData->DeleteFrame();
3226 lFrame = preserve;
3227 }
3228 //look for gradient data
3229 if (Buffer->LocateKeyWord(OptKeywords) >= 0) {
3230 KeyWordFound = true;
3231 NextFinalPos = Buffer->GetFilePos();
3232 Buffer->SetFilePos(EnergyPos);
3233 }
3234 lFrame->ReadGradient(Buffer, NextFinalPos);
3235 } else if (NumFragmentAtoms > 0) {
3236 if (Buffer->LocateKeyWord("TOT. INTER. ENERGY", 18, NextFinalPos)) {
3237 Buffer->GetLine(LineText);
3238 LinePos = FindKeyWord(LineText, "=", 1);
3239 if (LinePos > -1) {
3240 sscanf(&(LineText[LinePos+1]), "%lf", &(lFrame->Energy));
3241 }
3242 }
3243 } else if (MainData->InputOptions->Control->GetCIType()) {
3244 // If this is just a CI grab CI energy and orbitals
3245 if (Buffer->LocateKeyWord("CI EIGENSTATE", 13)) {
3246 Buffer->GetLine(LineText);
3247 sscanf(&(LineText[35]), "%lf", &(lFrame->Energy));
3248 while (Buffer->LocateKeyWord("NATURAL ORBITALS IN ATOMIC ORBITAL BASIS",
3249 40, NextFinalPos)) {
3250 lFrame->ParseGAMESSCIVectors(Buffer, MainData->GetNumBasisFunctions(), ProgressInd);
3251 }
3252 }
3253 }
3254 // Switch to IRC routine if neccessary
3255 if (MainData->InputOptions->Control->GetRunType() == IRCRun) {
3256 //If this is an MP2 run need to copy the MP2 energy to the total energy as the IRC
3257 //parsing routine only finds the single total energy
3258 if (MainData->InputOptions->Control->GetMPLevel()) {
3259 lFrame->SetEnergy(lFrame->GetEnergy(PT2Energy));
3260 }
3261 return this->OpenGAMESSIRCLog(Buffer, flip, offset, NumOccAlpha, NumOccBeta, NumFragmentAtoms);
3262 }
3263 }
3264 KeyWordFound = true;
3265 // if (SIMOMM) KeyWordFound = false; //only grab a single geometry for SIMOMM
3266 double FrameEnergy, MP2FrameEnergy;
3267 // bool NewStyleGeometryKeyWord=true;
3268 // char GeoSearchToken[] = "BEGINNING GEOMETRY SEARCH POINT";
3269 // if (!(Buffer->LocateKeyWord(GeoSearchToken, 31))) {
3270 // NewStyleGeometryKeyWord = false;
3271 // strcpy(GeoSearchToken, "1NSERCH");
3272 // }
3273 while (KeyWordFound) {
3274 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3275 { throw UserCancel();}
3276 KeyWordFound = false;
3277 //Advance to the start of the next geometry step BEGINNING GEOMETRY SEARCH POINT
3278 //If there isn't one then we are done with the geometries
3279 if (Buffer->LocateKeyWord(OptKeywords) < 0) break;
3280 StartPos = Buffer->GetFilePos();
3281 if (Buffer->LocateFinalEnergy()) { //Search for final and energy on the same line
3282 Buffer->GetLine(LineText); //since final also appears in LMO calcs.
3283 LinePos = FindKeyWord(LineText, "ENERGY", 6);
3284 if (LinePos > -1) {
3285 EnergyPos = Buffer->GetFilePos();
3286 KeyWordFound = true;
3287 int k = sscanf(&(LineText[LinePos+10]), "%lf", &FrameEnergy);
3288 if (k == 0) { //Crappy fragment output is different
3289 k = FindKeyWord(&(LineText[LinePos]), "=", 1);
3290 if (LinePos > -1)
3291 sscanf(&(LineText[LinePos+k+1]), "%lf", &FrameEnergy);
3292 }
3293 if (MainData->InputOptions->Control->GetMPLevel()==2) { //MP2 run so look for MP2 energy
3294 wxFileOffset temp = Buffer->GetFilePos();
3295 if (Buffer->LocateKeyWord("E(MP2)=", 7)) {
3296 Buffer->GetLine(LineText);
3297 sscanf(&(LineText[8]), "%lf", &MP2FrameEnergy);
3298 }
3299 Buffer->SetFilePos(temp);
3300 } else MP2FrameEnergy = 0.0;
3301 } else Buffer->SetFilePos(StartPos);
3302 }
3303 if (!KeyWordFound && (NumFragmentAtoms > 0)) { //Look for old style fragment output
3304 if (Buffer->LocateKeyWord("TOT. INTER. ENERGY", 18)) {
3305 Buffer->GetLine(LineText);
3306 LinePos = FindKeyWord(LineText, "=", 1);
3307 if (LinePos > -1) {
3308 sscanf(&(LineText[LinePos+1]), "%lf", &FrameEnergy);
3309 KeyWordFound = true;
3310 EnergyPos = Buffer->GetFilePos();
3311 }
3312 }
3313 }
3314 if (!KeyWordFound) { //This is a last resort in case normal GAMESS energies are missing
3315 if (MainData->InputOptions->Control->GetRunType() == OptimizeRun) {
3316 if (Buffer->LocateKeyWord(" NSERCH=", 9)) {
3317 Buffer->GetLine(LineText);
3318 LinePos = FindKeyWord(LineText, "ENERGY=", 7);
3319 sscanf(&(LineText[LinePos+7]), "%lf", &FrameEnergy);
3320 KeyWordFound = true;
3321 EnergyPos = Buffer->GetFilePos();
3322 }
3323 }
3324 }
3325
3326 if (KeyWordFound) {
3327 //Let the user know we are still making progress
3328 sprintf(LineText, "Reading Coordinates: frame %ld", MainData->NumFrames);
3329 ProgressInd->ChangeText(LineText);
3330 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3331 { throw UserCancel();}
3332 EnergyPos = Buffer->GetFilePos();
3333
3334 Buffer->SkipnLines(1);
3335 NextFinalPos = -1;
3336 if (lFrame->NumAtoms - NumFragmentAtoms > 0) {
3337 // if (NewStyleGeometryKeyWord&&Buffer->LocateKeyWord("BEGINNING GEOMETRY SEARCH POINT", 31)) {
3338 if (Buffer->LocateKeyWord(OptKeywords) >= 0) {
3339 // KeyWordFound = true;
3340 NextFinalPos = Buffer->GetFilePos();
3341 //this doesn't seem to be needed and it messes up the last point in a numerical opt.
3342 // } else {
3343 // KeyWordFound = Buffer->LocateKeyWord("FINAL", 5);
3344 }
3345 // if (KeyWordFound) NextFinalPos = Buffer->GetFilePos();
3346 Buffer->SetFilePos(EnergyPos);
3347 }
3348 // The output for optimizations was changed in 1/1998 to print all coordinates
3349 // at the top of an optimization step, but the older style is also still possible
3350 //Look for ab initio atoms first
3351 Buffer->SetFilePos(StartPos); //reset pos to last frame to begin search
3352 if (Buffer->LocateKeyWord(OptKeywords) >= 0) {
3353 lpFrame = lFrame;
3354 lFrame = MainData->AddFrame(lpFrame->NumAtoms,0);
3355
3356 if (SIMOMM) { //copy over the MM atoms so that they will be in the same order
3357 for (int iatom=0; iatom<lpFrame->NumAtoms; ++iatom) {
3358 if (lpFrame->Atoms[iatom].IsSIMOMMAtom()) {
3359 lFrame->AddAtom(lpFrame->Atoms[iatom].Type,
3360 lpFrame->Atoms[iatom].Position);
3361 lFrame->Atoms[iatom].IsSIMOMMAtom(true);
3362 }
3363 }
3364 }
3365
3366 try {
3367 if (lpFrame->NumAtoms-NumFragmentAtoms > 0) {
3368
3369 //Look for new style with all atoms at top of step first
3370 if (Buffer->LocateKeyWord("COORDINATES OF ALL ATOMS ARE (ANGS)", 35, EnergyPos)) {
3371 Buffer->SkipnLines(3);
3372 test = ParseGLogLine(Buffer, lFrame, lpFrame->NumAtoms-NumFragmentAtoms, 10, &(MainData->MaxSize));
3373 if (test==-1) { //Something was wrong with this set of coordinates
3374 MainData->DeleteFrame();
3375 break;
3376 }
3377 } else if (Buffer->LocateKeyWord(" NSERCH", 7, NextFinalPos)) {
3378 //Otherwise look for the coordinates at the end of the
3379 //geometry step (pre 1998 style)
3380 wxFileOffset npos = Buffer->GetFilePos();
3381 Buffer->SkipnLines(9);
3382 test = ParseGLogLine(Buffer, lFrame, lpFrame->NumAtoms-NumFragmentAtoms, 1, &(MainData->MaxSize));
3383 if (test==-1) { //Something was wrong with this set of coordinates
3384 MainData->DeleteFrame();
3385 break;
3386 }
3387 Buffer->SetFilePos(npos);//reset position back to beginning of gradient data
3388 }
3389 }
3390 if (NumFragmentAtoms > 0) {
3391 wxFileOffset tempPos = Buffer->GetFilePos();
3392 Buffer->SetFilePos(StartPos);
3393 if (Buffer->LocateKeyWord(OptKeywords) >= 0) {
3394 if (Buffer->LocateKeyWord("COORDINATES OF FRAGMENT MULTIPOLE CENTERS", 41, NextFinalPos)) {
3395 Buffer->SkipnLines(3);
3396 MainData->ReadFragmentCoordinates(Buffer, NumFragmentAtoms);
3397 }
3398 Buffer->SetFilePos(tempPos);
3399 }
3400 }
3401 lFrame->ReadGradient(Buffer, NextFinalPos);
3402 }
3403 catch (...) { //Error occured while parsing coordinates, delete this frame
3404 MainData->DeleteFrame();
3405 Buffer->SetFilePos(StartPos);
3406 break;
3407 }
3408 } else {
3409 Buffer->SetFilePos(StartPos);
3410 break;
3411 } //Make sure we actually found the coordinates
3412 if (lFrame->GetNumAtoms()==0) {Buffer->SetFilePos(StartPos); break;}
3413 lFrame->Energy = FrameEnergy;
3414 if (MainData->InputOptions->Control->GetMPLevel()==2)
3415 lFrame->Energies.push_back(EnergyValue(MP2FrameEnergy, PT2Energy));
3416 lFrame->IRCPt = lpFrame->IRCPt + flip;
3417 lFrame->time = lpFrame->time + flip + offset;
3418
3419 if (SIMOMM) {
3420 Buffer->SetFilePos(EnergyPos);
3421 //could also grab the MM energy here
3422 if (Buffer->LocateKeyWord("QM+MM Energy (Hartree):", 23)) {
3423 Buffer->GetLine(LineText);
3424 double FrameEnergy;
3425 sscanf(&(LineText[24]), "%lf", &FrameEnergy);
3426 lFrame->Energy = FrameEnergy;
3427 }
3428 //now update the coordinates with the new MM list
3429 Frame * preserve = MainData->cFrame;
3430 lFrame = MainData->AddFrame(MainData->cFrame->NumAtoms,0);
3431 MainData->ParseTinkerCoordinates(Buffer);
3432 if (MainData->cFrame->NumAtoms > 0) {
3433 //update the coordinates in the first frame
3434 for (int iatom=0; iatom<MainData->cFrame->NumAtoms; ++iatom) {
3435 if (MainData->cFrame->Atoms[iatom].IsSIMOMMAtom()) {
3436 preserve->Atoms[iatom].Position.x = MainData->cFrame->Atoms[iatom].Position.x;
3437 preserve->Atoms[iatom].Position.y = MainData->cFrame->Atoms[iatom].Position.y;
3438 preserve->Atoms[iatom].Position.z = MainData->cFrame->Atoms[iatom].Position.z;
3439 }
3440 }
3441 }
3442 // delete off the temporary frame
3443 MainData->DeleteFrame();
3444 lFrame = preserve;
3445 }
3446
3447 if (Prefs->GetAutoBond())
3448 lFrame->SetBonds(Prefs, false, ProgressInd);
3449 // NextFinalPos = -1;
3450 Buffer->SetFilePos(EnergyPos);
3451 // long SavedPos = Buffer->GetFilePos();
3452 // if (lFrame->NumAtoms - NumFragmentAtoms > 0) {
3453 // KeyWordFound = Buffer->LocateKeyWord("FINAL", 5);
3454 // if (KeyWordFound) NextFinalPos = Buffer->GetFilePos();
3455 // Buffer->SetFilePos(SavedPos);
3456 // }
3457 //Attempt to read in orbitals for this geometry
3458 if (MainData->Basis) {
3459 Buffer->SetFilePos(EnergyPos);
3460 try {
3461 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_MCSCF) {
3462 bool ReadOrbs = false;
3463 if (Buffer->LocateKeyWord("MCSCF NATURAL ORBITALS", 22, NextFinalPos)) {
3464 if ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos()))
3465 ReadOrbs = true;
3466 else Buffer->SetFilePos(SavedPos);
3467 } else if (Buffer->LocateKeyWord("MCSCF OPTIMIZED ORBITALS", 24, NextFinalPos)) {
3468 if ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos()))
3469 ReadOrbs = true;
3470 else Buffer->SetFilePos(SavedPos);
3471 } else if (Buffer->LocateKeyWord("-MCHF- NATURAL ORBITALS", 23, NextFinalPos)) {
3472 if ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos()))
3473 ReadOrbs = true;
3474 else Buffer->SetFilePos(SavedPos);
3475 } else if (Buffer->LocateKeyWord("-MCHF- OPTIMIZED ORBITALS", 25, NextFinalPos)) {
3476 if ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos()))
3477 ReadOrbs = true;
3478 else Buffer->SetFilePos(SavedPos);
3479 } else if (Buffer->LocateKeyWord("MOLECULAR ORBITALS", 18, NextFinalPos)) {
3480 Buffer->SetFilePos(Buffer->FindBlankLine());
3481 Buffer->SkipnLines(1);
3482 lFrame->ParseGAMESSEigenVectors(Buffer, MainData->GetNumBasisFunctions(),
3483 MainData->GetNumBasisFunctions(), 0, NumOccAlpha, NumOccBeta,
3484 (TypeOfWavefunction)(MainData->InputOptions->Control->GetSCFType()), ProgressInd);
3485 // lFrame->ExchangeEigenVectors();
3486 }
3487 if (ReadOrbs)
3488 lFrame->ParseGAMESSMCSCFVectors(Buffer, MainData->GetNumBasisFunctions(),
3489 OccupiedOrbCount, ProgressInd);
3490 } else {
3491 if (MainData->InputOptions->Control->GetSCFType() == GAMESS_GVB) {
3492 if (Buffer->LocateKeyWord("PAIR INFORMATION", 16, NextFinalPos)) {
3493 ReadGVBOccupancy(Buffer, NumGVBPairs, MainData->GetNumBasisFunctions(),
3494 Occupancy);
3495 }
3496 }
3497 bool test = false;
3498 if (MainData->InputOptions->Control->GetCIType() == 4) {
3499 //CIS output includes the EIGENVECTORS token
3500 //I think the regular EIGENVECTORS would be before the CIS line???
3501 wxFileOffset bp = Buffer->GetFilePos();
3502 test = Buffer->LocateKeyWord("EIGENVECTORS", 12, NextFinalPos);
3503 Buffer->BackupnLines(1);
3504 if (Buffer->LocateKeyWord("CIS EIGENVALUES", 14, 80+Buffer->GetFilePos())) {
3505 Buffer->SkipnLines(1);
3506 test = Buffer->LocateKeyWord("EIGENVECTORS", 12, NextFinalPos);
3507 if (!test) {
3508 Buffer->SetFilePos(bp);
3509 test = Buffer->LocateKeyWord("MOLECULAR ORBITALS", 18, NextFinalPos);
3510 Buffer->BackupnLines(1);
3511 if (Buffer->LocateKeyWord("# MOLECULAR ORBITALS =", 22)) {
3512 Buffer->SkipnLines(1);
3513 test = Buffer->LocateKeyWord("MOLECULAR ORBITALS", 18, NextFinalPos);
3514 if (!test) Buffer->SetFilePos(bp);
3515 }
3516 }
3517 }
3518 } else {
3519 test = Buffer->LocateKeyWord("EIGENVECTORS", 12, NextFinalPos);
3520 if (!test) {
3521 test = Buffer->LocateKeyWord("MOLECULAR ORBITALS", 18, NextFinalPos);
3522 //for a while GAMESS printed out MOLECULAR ORBITALS with the LZ analysis
3523 //so add a test to avoid that output
3524 if (test) {
3525 Buffer->BackupnLines(0);
3526 Buffer->GetLine(LineText);
3527 LinePos = FindKeyWord(LineText, "LZ VALUE ANALYSIS", 16);
3528 if (LinePos > -1) {
3529 Buffer->SkipnLines(2);
3530 test = Buffer->LocateKeyWord("MOLECULAR ORBITALS", 18, NextFinalPos);
3531 }
3532 }
3533 }
3534 }
3535 if (test) {
3536 //skip over the line to the start of the orbital blocks
3537 //There is always a blank line before the orbs, but there may a '---' divider line after the key line just found
3538 if ((NextFinalPos<0)||(NextFinalPos>Buffer->GetFilePos())) {
3539 Buffer->SetFilePos(Buffer->FindBlankLine());
3540 Buffer->SkipnLines(1);
3541 ProgressInd->ChangeText("Reading eigenvectors");
3542 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3543 {throw UserCancel();}
3544 OrbitalRec * OrbSet = lFrame->ParseGAMESSEigenVectors(Buffer, MainData->GetNumBasisFunctions(),
3545 MainData->GetNumBasisFunctions(), NumBetaUHFOrbs, NumOccAlpha, NumOccBeta,
3546 (TypeOfWavefunction)(MainData->InputOptions->Control->GetSCFType()), ProgressInd);
3547 if ((MainData->InputOptions->Control->GetSCFType() == GAMESS_GVB)&&(OrbSet!=NULL)) {
3548 //Add the Occupancy vector for GVB wavefunctions
3549 OrbSet->SetOccupancy(Occupancy, MainData->GetNumBasisFunctions());
3550 }
3551 } else Buffer->SetFilePos(SavedPos);
3552 }
3553 }
3554 // It doesn't appear that GVB orbitals are read in after the first set???
3555 // It appears that GAMESS only prints the GI orbitals on the first iteration
3556 if (MainData->InputOptions->Control->GetSCFType() == GAMESS_UHF) {
3557 if (Buffer->LocateKeyWord("UHF NATURAL ORBITALS AND OCCUPATION NUMBERS",
3558 43, NextFinalPos)) {
3559 lFrame->ParseUHFNOs(Buffer, MainData->GetNumBasisFunctions(), ProgressInd);
3560 }
3561 }
3562 // if (MainData->InputOptions->Control->GetSCFType() == GAMESS_TDDFT) {
3563 //I don't have the right control keywords yet. Possibilities are TDDFT=EXCITE in
3564 //$CONTRL or TDPRP=.t. in $TDDFT
3565 if (Buffer->LocateKeyWord("TDDFT NATURAL ORBITALS",
3566 23, NextFinalPos)) {
3567 lFrame->ParseTDDFTNOs(Buffer, MainData->GetNumBasisFunctions(), ProgressInd);
3568 }
3569 // }
3570 if (MainData->InputOptions->Control->GetMPLevel()) {
3571 if (Buffer->LocateKeyWord("MP2 NATURAL ORBITAL OCCUPATION NUMBERS",
3572 38, NextFinalPos) && ReadMP2Orbitals) {
3573 lFrame->ReadMP2Vectors(Buffer, DatBuffer, MainData->GetNumBasisFunctions(),
3574 ProgressInd, &ReadMP2Orbitals);
3575 }
3576 }
3577 if (MainData->InputOptions->Control->GetCIType()) { //Look for CI Natural orbitals
3578 //loop to add multiple CI NOs, one set for each eigenstate.
3579 //This would be the place to read in each eigenstate's energy
3580 while (Buffer->LocateKeyWord("NATURAL ORBITALS IN ATOMIC ORBITAL BASIS",
3581 40, NextFinalPos)) {
3582 lFrame->ParseGAMESSCIVectors(Buffer, MainData->GetNumBasisFunctions(), ProgressInd);
3583 }
3584 }
3585 }
3586 catch (std::bad_alloc) {
3587 MessageAlert("Insufficient memory to read in eigenvectors.");
3588 }
3589 catch (MemoryError) {
3590 MessageAlert("Insufficient memory to read in eigenvectors.");
3591 }
3592 catch (DataError) {
3593 MessageAlert("Error reading eigenvectors, orbitals skipped.");
3594 }
3595 }
3596 }
3597 }
3598 //Read in normal modes, if present
3599 MainData->cFrame->ParseNormalModes(Buffer, ProgressInd, Prefs);
3600
3601 //Look for localized orbitals which appear only at the end of a log file
3602 if (MainData->Basis) {
3603 try {
3604 enum {
3605 CASSCFDiabatic=0,
3606 FockLocalized,
3607 DensityMatrixLocalized,
3608 OrientedLocOrbs,
3609 NonorthogLocOrbs,
3610 PPASVDOrbs,
3611 LocalizedOrbitals,
3612 SVDExternalOrbs,
3613 SplitQALocOrbs,
3614 OrderedExternalLocOrbs
3615 };
3616 std::vector<std::pair <std::string, int> > LocOrbKeywords;
3617 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_MCSCF)
3618 LocOrbKeywords.push_back(make_pair (std::string("CAS-SCF DIABATIC MOLECULAR ORBITALS"), (int) CASSCFDiabatic));
3619 LocOrbKeywords.push_back(make_pair (std::string("FOCK OPERATOR FOR THE LOCALIZED ORBITALS"), (int) FockLocalized));
3620 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_MCSCF)
3621 LocOrbKeywords.push_back(make_pair (std::string("DENSITY MATRIX FOR THE LOCALIZED ORBITALS"), (int) DensityMatrixLocalized));
3622 LocOrbKeywords.push_back(make_pair (std::string("ORIENTED LOCALIZED ORBITALS"), (int) OrientedLocOrbs));
3623 LocOrbKeywords.push_back(make_pair (std::string("NONORTHOGONAL PPA SVD LOCALIZED ORBITALS"), (int) NonorthogLocOrbs));
3624 LocOrbKeywords.push_back(make_pair (std::string("PPA SVD LOCALIZED ORBITALS"), (int) PPASVDOrbs));
3625 // LocOrbKeywords.push_back(make_pair (std::string("SVD EXTERNAL LOCALIZED ORBITALS"), (int) SVDExternalOrbs));
3626 LocOrbKeywords.push_back(make_pair (std::string("SPLITQA LOCALIZED ORBITALS"), (int) SplitQALocOrbs));
3627 LocOrbKeywords.push_back(make_pair (std::string("ORDERED EXTERNAL LOCALIZED ORBITALS"), (int) OrderedExternalLocOrbs));
3628 //Order is important, look for this last since it is a subset of some of the others
3629 LocOrbKeywords.push_back(make_pair (std::string("LOCALIZED ORBITALS"), (int) LocalizedOrbitals));
3630
3631 while (! Buffer->Eof()) {
3632 int kw;
3633 if (-1 < (kw = Buffer->LocateKeyWord(LocOrbKeywords))) {
3634 wxFileOffset keywordPosition = Buffer->GetFilePos();
3635 OrbitalRec * OrbSet;
3636 switch (kw) {
3637 case CASSCFDiabatic:
3638 //MCSCF runs can potentially have diabatic orbitals at the end.
3639 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_MCSCF) {
3640 lFrame->ParseGAMESSMCSCFDiabaticVectors(Buffer, MainData->GetNumBasisFunctions(),
3641 OccupiedOrbCount, ProgressInd);
3642 }
3643 break;
3644 case FockLocalized:
3645 Buffer->SkipnLines(1);
3646 break;
3647 case OrientedLocOrbs:
3648 Buffer->SkipnLines(2);
3649 ProgressInd->ChangeText("Reading oriented localized orbitals");
3650 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3651 { throw UserCancel();}
3652 OrbSet = lFrame->ParseGAMESSLMOs(Buffer, MainData->GetNumBasisFunctions(), MainData->GetNumBasisFunctions(),
3653 NumBetaUHFOrbs, ProgressInd, true);
3654 if (OrbSet != NULL) {
3655 OrbSet->setOrbitalWavefunctionType((TypeOfWavefunction)MainData->InputOptions->Control->GetSCFType());
3656 if (MainData->InputOptions->Control->GetSCFType() != GAMESS_MCSCF) {
3657 OrbSet->SetOrbitalOccupancy(NumOccAlpha, NumOccBeta);
3658 }
3659 }
3660 break;
3661 case NonorthogLocOrbs:
3662 Buffer->SetFilePos(Buffer->FindBlankLine());
3663 Buffer->SkipnLines(1);
3664 ProgressInd->ChangeText("Reading Nonorthogonal PPA SVD localized orbitals");
3665 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3666 { throw UserCancel();}
3667 OrbSet = lFrame->ParseGAMESSLMOs(Buffer, MainData->GetNumBasisFunctions(), MainData->GetNumBasisFunctions(),
3668 NumBetaUHFOrbs, ProgressInd, true);
3669 OrbSet->setOrbitalType(NonOrthogonalSVDLocalizedOrbital);
3670 break;
3671 case PPASVDOrbs:
3672 Buffer->SetFilePos(Buffer->FindBlankLine());
3673 Buffer->SkipnLines(1);
3674 ProgressInd->ChangeText("Reading PPA SVD localized orbitals");
3675 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3676 { throw UserCancel();}
3677 OrbSet = lFrame->ParseGAMESSLMOs(Buffer, MainData->GetNumBasisFunctions(), MainData->GetNumBasisFunctions(),
3678 NumBetaUHFOrbs, ProgressInd, true);
3679 OrbSet->setOrbitalType(PPASVDLocalizedOrbital);
3680 break;
3681 case LocalizedOrbitals:
3682 Buffer->SkipnLines(2);
3683 ProgressInd->ChangeText("Reading localized orbitals");
3684 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3685 { throw UserCancel();}
3686 OrbSet = lFrame->ParseGAMESSLMOs(Buffer, MainData->GetNumBasisFunctions(), MainData->GetNumBasisFunctions(),
3687 NumBetaUHFOrbs, ProgressInd, false);
3688 if (OrbSet != NULL) {
3689 OrbSet->setOrbitalWavefunctionType((TypeOfWavefunction)MainData->InputOptions->Control->GetSCFType());
3690 if (MainData->InputOptions->Control->GetSCFType() != GAMESS_MCSCF) {
3691 OrbSet->SetOrbitalOccupancy(NumOccAlpha, NumOccBeta);
3692 }
3693 }
3694 break;
3695 case SVDExternalOrbs:
3696 Buffer->SetFilePos(Buffer->FindBlankLine());
3697 Buffer->SkipnLines(1);
3698 ProgressInd->ChangeText("Reading SVD External localized orbitals");
3699 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3700 { throw UserCancel();}
3701 OrbSet = lFrame->ParseGAMESSLMOs(Buffer, MainData->GetNumBasisFunctions(), MainData->GetNumBasisFunctions(),
3702 NumBetaUHFOrbs, ProgressInd, true);
3703 OrbSet->setOrbitalType(SVDExternalLocalizedOrbital);
3704 break;
3705 case SplitQALocOrbs:
3706 Buffer->SetFilePos(Buffer->FindBlankLine());
3707 Buffer->SkipnLines(1);
3708 ProgressInd->ChangeText("Reading SplitQA localized orbitals");
3709 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3710 { throw UserCancel();}
3711 OrbSet = lFrame->ParseGAMESSLMOs(Buffer, MainData->GetNumBasisFunctions(), MainData->GetNumBasisFunctions(),
3712 NumBetaUHFOrbs, ProgressInd, true);
3713 OrbSet->setOrbitalType(SplitQAExternalLocalizedOrbital);
3714 break;
3715 case OrderedExternalLocOrbs:
3716 Buffer->SetFilePos(Buffer->FindBlankLine());
3717 Buffer->SkipnLines(1);
3718 ProgressInd->ChangeText("Reading Ordered External localized orbitals");
3719 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3720 { throw UserCancel();}
3721 OrbSet = lFrame->ParseGAMESSLMOs(Buffer, MainData->GetNumBasisFunctions(), MainData->GetNumBasisFunctions(),
3722 NumBetaUHFOrbs, ProgressInd, true);
3723 OrbSet->setOrbitalType(OrderedExternalLocalizedOrbital);
3724 break;
3725 }
3726 //If still positioned at the keyword, must advance or there will be a loop.
3727 if (keywordPosition == Buffer->GetFilePos()) Buffer->SkipnLines(1);
3728 } else break;
3729 }
3730 //MCSCF runs can potentially have diabatic orbitals at the end.
3731 // if (MainData->InputOptions->Control->GetSCFType()==GAMESS_MCSCF) {
3732 // if (Buffer->LocateKeyWord("CAS-SCF DIABATIC MOLECULAR ORBITALS", 34)) {
3733 // lFrame->ParseGAMESSMCSCFDiabaticVectors(Buffer, MainData->GetNumBasisFunctions(),
3734 // OccupiedOrbCount, ProgressInd);
3735 // }
3736 // }
3737 //GAMESS now punchs out the Fock operator for ruedenburg type localization
3738 //which I need to skip if it is present
3739 // if (Buffer->LocateKeyWord("FOCK OPERATOR FOR THE LOCALIZED ORBITALS",40))
3740 // Buffer->SkipnLines(1);
3741 // if (MainData->InputOptions->Control->GetSCFType()==GAMESS_MCSCF) {
3742 //skip over the density matrix (present in Ruedenburg MCSCF runs)
3743 // if (Buffer->LocateKeyWord("DENSITY MATRIX FOR THE LOCALIZED ORBITALS",41))
3744 // Buffer->SkipnLines(1);
3745 // }
3746 // KeyWordFound = Buffer->LocateKeyWord("LOCALIZED ORBITALS",18);
3747 // if (KeyWordFound) {
3748 // Buffer->SkipnLines(2);
3749 // ProgressInd->ChangeText("Reading localized orbitals");
3750 // if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3751 // { throw UserCancel();}
3752 // OrbitalRec * OrbSet = lFrame->ParseGAMESSLMOs(Buffer, MainData->GetNumBasisFunctions(), MainData->GetNumBasisFunctions(),
3753 // NumBetaUHFOrbs, ProgressInd, false);
3754 // if (OrbSet != NULL) {
3755 // OrbSet->setOrbitalWavefunctionType((TypeOfWavefunction)MainData->InputOptions->Control->GetSCFType());
3756 // if (MainData->InputOptions->Control->GetSCFType() != GAMESS_MCSCF) {
3757 // OrbSet->SetOrbitalOccupancy(NumOccAlpha, NumOccBeta);
3758 // }
3759 // }
3760 // // There may also be oriented localized orbitals
3761 // KeyWordFound = Buffer->LocateKeyWord("ORIENTED LOCALIZED ORBITALS",27);
3762 // if (KeyWordFound) {
3763 // Buffer->SkipnLines(2);
3764 // ProgressInd->ChangeText("Reading oriented localized orbitals");
3765 // if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
3766 // { throw UserCancel();}
3767 // OrbSet = lFrame->ParseGAMESSLMOs(Buffer, MainData->GetNumBasisFunctions(), MainData->GetNumBasisFunctions(),
3768 // NumBetaUHFOrbs, ProgressInd, true);
3769 // if (OrbSet != NULL) {
3770 // OrbSet->setOrbitalWavefunctionType((TypeOfWavefunction)MainData->InputOptions->Control->GetSCFType());
3771 // if (MainData->InputOptions->Control->GetSCFType() != GAMESS_MCSCF) {
3772 // OrbSet->SetOrbitalOccupancy(NumOccAlpha, NumOccBeta);
3773 // }
3774 // }
3775 // }
3776 // }
3777 }
3778 catch (std::bad_alloc) {
3779 MessageAlert("Insufficient memory to read in the localized orbitals.");
3780 }
3781 catch (MemoryError) {
3782 MessageAlert("Insufficient memory to read in the localized orbitals.");
3783 }
3784 catch (DataError) {
3785 MessageAlert("Error reading localized orbitals, local orbs. skipped.");
3786 }
3787 }
3788 if (DatBuffer) DatBuffer->CloseFile();
3789 if (Occupancy) delete [] Occupancy;
3790 MainData->cFrame = MainData->Frames;
3791 MainData->CurrentFrame = 1;
3792 if (MainData->InputOptions->Control->GetMPLevel()==2) {
3793 EnergyOptions * lOpts = Prefs->GetEnergyOptions();
3794 lOpts->SetPlotMPEnergy(true);
3795 lOpts->SetPlotEnergy(false);
3796 }
3797 if ((MainData->InputOptions->Control->GetRunType()==4)||
3798 (MainData->InputOptions->Control->GetRunType()==6)) {
3799 MainData->SetCurrentFrame(MainData->GetNumFrames());
3800 }
3801 return 1;
3802 } /*OpenGAMESSlog*/
ReadGVBOccupancy(BufferFile * Buffer,long NumPairs,long MaxOrbs,float * Occupancy)3803 bool ReadGVBOccupancy(BufferFile * Buffer, long NumPairs, long MaxOrbs, float * Occupancy) {
3804 char Line[kMaxLineLength];
3805 long junk, Orb1, Orb2;
3806 float junkf, Occ1, Occ2;
3807 if ((NumPairs <= 0)||(!Occupancy)) return false; //no GVB pairs or no memory
3808 Buffer->SkipnLines(4);
3809 for (long i=0; i<NumPairs; ++i) {
3810 Buffer->GetLine(Line);
3811 sscanf(Line, "%ld %ld %ld %f %f %f %f", &junk, &Orb1, &Orb2, &junkf, &junkf,
3812 &Occ1, &Occ2);
3813 if ((Orb1<1)||(Orb1>MaxOrbs)||(Orb2<1)||(Orb2>MaxOrbs)) return false;//invalid orbital number
3814 Occupancy[Orb1 - 1] = Occ1;
3815 Occupancy[Orb2 - 1] = Occ2;
3816 }
3817 return true;
3818 }
3819 //routine to parse initial fragment coordinates which are in a real ugly
3820 //format with all of the multipole expantion points
ReadInitialFragmentCoords(BufferFile * Buffer)3821 long MoleculeData::ReadInitialFragmentCoords(BufferFile * Buffer) {
3822 long NumFragmentAtoms = 0, iatom, NumMultipoles=0, FragmentNumber=0;
3823 char Label[kMaxLineLength], Line[kMaxLineLength];
3824 Frame * lFrame = GetCurrentFramePtr();
3825 iatom = lFrame->GetNumAtoms();
3826
3827 //First read in the fragment names which are separate from the coordinates
3828 //I am not sure why I originally pulled it as "FOR", but GAMESS hasn't used it for some time.
3829 // "COORDINATES FOR FRAGMENT"
3830 while (Buffer->LocateKeyWord("COORDINATES OF FRAGMENT", 23, Buffer->GetFilePos()+200)) {
3831 if (Buffer->LocateKeyWord("NAMED", 5, Buffer->GetFilePos()+80)) {
3832 Buffer->GetLine(Line);
3833 sscanf(&(Line[5]), "%s", Label);
3834 FragmentNames.push_back(std::string(Label));
3835 } else Buffer->SkipnLines(1);
3836 }
3837 while (Buffer->LocateKeyWord("READING POTENTIAL PARAMETERS FOR FRAGMENT", 40, Buffer->GetFilePos()+200)) {
3838 Buffer->SkipnLines(1);
3839 }
3840
3841 if (Buffer->LocateKeyWord("TOTAL NUMBER OF MULTIPOLE POINTS", 32, Buffer->GetFilePos()+10000)) {
3842 Buffer->GetLine(Line);
3843 sscanf(&(Line[32]), " =%ld", &NumMultipoles);
3844 }
3845 //Mike finally fixed the spelling of coordinates
3846 if ((NumMultipoles>0) && (Buffer->LocateKeyWord("MULTIPOLE COORDINATES", 20, Buffer->GetFilePos()+10000) ||
3847 Buffer->LocateKeyWord("MULTIPOLE CORDINATES", 19, Buffer->GetFilePos()+10000))) {
3848 Buffer->SkipnLines(3);
3849 SetupFrameMemory(lFrame->NumAtoms + 10, 0);
3850 bool workingFragment=false;
3851 for (int i=0; i<NumMultipoles; ++i) {
3852 CPoint3D Pos;
3853 float eCharge, nCharge;
3854 Buffer->GetLine(Line);
3855 int iscan = sscanf(Line, "%s%f%f%f%f%f", Label, &Pos.x, &Pos.y, &Pos.z,
3856 &eCharge, &nCharge);
3857 if (iscan == 6) {
3858
3859 //The fragment output at the top of the log file is very bad for reading
3860 //and parsing. First we test on charge (some types have atom positions with
3861 //zero nuclear but positive electronic charge). Then strip off the 'Z' which
3862 //may or may not be present, then try to avoid non-atom positions which most of
3863 //the time have negative charge and often seem to start with 'B'.
3864 if (eCharge>0.5 || nCharge > 0.5) {
3865 long AtomType = -1;
3866 if (std::toupper(Label[0]) == 'B') {
3867 //a 'B' almost always not an atom
3868 if (workingFragment) workingFragment=false; //flag to indicate end of fragment
3869 if ((std::isalpha(Label[1]))) {
3870 if (eCharge<3.5 || nCharge < 3.5) continue;
3871 }
3872 }
3873 if ((Label[0] == 'Z') || (Label[0] == 'z')) { //z represents an atom pos
3874 Label[0] = Label[1];
3875 if (std::isalpha(Label[2])) {
3876 Label[1] = Label[2];
3877 Label[2] = 0;
3878 } else Label[1] = 0;
3879 }
3880 AtomType = SetAtomType((unsigned char *) &(Label[0]));
3881 if ((std::toupper(Label[0]) == 'A')&&(AtomType < 0)) {
3882 AtomType = nCharge;
3883 }
3884 if (lFrame->NumAtoms + 1 > lFrame->AtomAllocation)
3885 SetupFrameMemory(lFrame->NumAtoms + 10, 0);
3886 if (AtomType > 0) {
3887 if (!workingFragment) {
3888 ++FragmentNumber;
3889 workingFragment = true;
3890 }
3891 Pos.x *= kBohr2AngConversion;
3892 Pos.y *= kBohr2AngConversion;
3893 Pos.z *= kBohr2AngConversion;
3894 mpAtom * newAtom = lFrame->AddAtom(AtomType, Pos);
3895 if (newAtom) newAtom->SetFragmentNumber(FragmentNumber);
3896 MaxSize = MAX(MaxSize, fabs(Pos.x));
3897 MaxSize = MAX(MaxSize, fabs(Pos.y));
3898 MaxSize = MAX(MaxSize, fabs(Pos.z));
3899 ++NumFragmentAtoms;
3900 }
3901 } else workingFragment = false;
3902 }
3903 }
3904 }
3905 return NumFragmentAtoms;
3906 }
ReadFragmentCoordinates(BufferFile * Buffer,long NumFragmentAtoms)3907 void MoleculeData::ReadFragmentCoordinates(BufferFile * Buffer, long NumFragmentAtoms) {
3908 long iatom=0, FragmentNumber=0;
3909 CPoint3D Pos;
3910 char Label[kMaxLineLength], Line[kMaxLineLength];
3911 Frame * lFrame = GetCurrentFramePtr();
3912 Frame * startFrame = Frames;
3913 long referenceFragAtom=0;
3914
3915 while (iatom<NumFragmentAtoms) {
3916 Buffer->GetLine(Line);
3917 if (-1<LocateKeyWord(Line, "FRAGNAME=",9, strlen(Line))) {++FragmentNumber; continue;}
3918 int iscan = sscanf(Line, "%s%f%f%f", Label, &Pos.x, &Pos.y, &Pos.z);
3919 if (iscan == 4) {
3920 long AtomType = -1;
3921 if ((Label[0] == 'Z') || (Label[0] == 'z')) { //z represents an atom pos
3922 Label[0] = Label[1];
3923 if (std::isalpha(Label[2])) {
3924 Label[1] = Label[2];
3925 Label[2] = 0;
3926 } else Label[1] = 0;
3927 }
3928 AtomType = SetAtomType((unsigned char *) &(Label[0]));
3929 //In the late-2007 style we get only the useless label (starting with an 'A')
3930 //and the x, y, and z coords. So in order to determine the atomtype we have
3931 //to reference the initial frame.
3932 if ((std::toupper(Label[0]) == 'A')&&(AtomType < 0)) {
3933 while ((referenceFragAtom < startFrame->GetNumAtoms())&&
3934 !startFrame->Atoms[referenceFragAtom].IsEffectiveFragment())
3935 ++referenceFragAtom;
3936 if (referenceFragAtom < startFrame->GetNumAtoms()) {
3937 AtomType = startFrame->Atoms[referenceFragAtom].Type;
3938 ++referenceFragAtom;
3939 }
3940 }
3941 if (AtomType > 0) {
3942 mpAtom * newAtom = lFrame->AddAtom(AtomType, Pos);
3943 if (newAtom) newAtom->SetFragmentNumber(FragmentNumber);
3944 MaxSize = MAX(MaxSize, fabs(Pos.x));
3945 MaxSize = MAX(MaxSize, fabs(Pos.y));
3946 MaxSize = MAX(MaxSize, fabs(Pos.z));
3947 ++iatom;
3948 }
3949 }
3950 }
3951 }
ReadBasisOptions(BufferFile * Buffer)3952 void MoleculeData::ReadBasisOptions(BufferFile * Buffer) {
3953 char LineText[kMaxLineLength], token[kMaxLineLength];
3954 long LinePos, test;
3955 if (Buffer->LocateKeyWord("GBASIS", 6)) {
3956 Buffer->GetLine(LineText);
3957 LinePos = FindKeyWord(LineText, "GBASIS", 6) + 7;
3958 sscanf(&(LineText[LinePos]),"%s", token);
3959 InputOptions->Basis->SetBasis(token);
3960
3961 LinePos = FindKeyWord(LineText, "IGAUSS", 6);
3962 if (LinePos > -1) {
3963 sscanf(&(LineText[LinePos+7]),"%ld", &test);
3964 InputOptions->Basis->SetNumGauss(test);
3965 }
3966
3967 LinePos = FindKeyWord(LineText, "POLAR", 5);
3968 if (LinePos > -1) {
3969 sscanf(&(LineText[LinePos+6]),"%s", token);
3970 InputOptions->Basis->SetPolar(&(LineText[LinePos+6]));
3971 }
3972
3973 Buffer->GetLine(LineText);
3974 LinePos = FindKeyWord(LineText, "NDFUNC", 6);
3975 if (LinePos > -1) {
3976 sscanf(&(LineText[LinePos+7]),"%ld", &test);
3977 InputOptions->Basis->SetNumDFuncs(test);
3978 }
3979
3980 LinePos = FindKeyWord(LineText, "DIFFSP", 6);
3981 if (LinePos > -1) {
3982 sscanf(&(LineText[LinePos+7]),"%1s", token);
3983 InputOptions->Basis->SetDiffuseSP(token[0] == 'T');
3984 }
3985
3986 Buffer->GetLine(LineText);
3987 LinePos = FindKeyWord(LineText, "NPFUNC", 6);
3988 if (LinePos > -1) {
3989 sscanf(&(LineText[LinePos+7]),"%ld", &test);
3990 InputOptions->Basis->SetNumPFuncs(test);
3991 }
3992
3993 LinePos = FindKeyWord(LineText, "DIFFS", 5);
3994 if (LinePos > -1) {
3995 sscanf(&(LineText[LinePos+6]),"%1s", token);
3996 InputOptions->Basis->SetDiffuseS(token[0] == 'T');
3997 }
3998 }
3999 }
ReadControlOptions(BufferFile * Buffer)4000 void MoleculeData::ReadControlOptions(BufferFile * Buffer) {
4001 long test;
4002 char LineText[kMaxLineLength], token[kMaxLineLength];
4003 wxFileOffset StartPos = Buffer->GetFilePos()+5; //All keywords should be between these positions
4004 wxFileOffset EndPos = Buffer->FindBlankLine();
4005 if (!Buffer->LocateKeyWord("SCFTYP", 6, EndPos)) throw DataError();
4006 Buffer->GetLine(LineText);
4007 sscanf(&(LineText[7]), "%s", token);
4008 test = InputOptions->Control->SetSCFType(token);
4009 // a -1 return means the SCFTyp was invalid, we'll continue, but there may be problems
4010 Buffer->SetFilePos(StartPos);
4011
4012 if (Buffer->LocateKeyWord("RUNTYP", 6, EndPos)) {
4013 Buffer->GetLine(LineText);
4014 sscanf(&(LineText[7]), "%s", token);
4015 InputOptions->Control->SetRunType(token);
4016 Buffer->SetFilePos(StartPos);
4017 }
4018
4019 if (Buffer->LocateKeyWord("EXETYP", 6, EndPos)) {
4020 Buffer->GetLine(LineText);
4021 sscanf(&(LineText[7]), "%s", token);
4022 InputOptions->Control->SetExeType(token);
4023 Buffer->SetFilePos(StartPos);
4024 }
4025
4026 if (Buffer->LocateKeyWord("MPLEVL", 6, EndPos)) {
4027 Buffer->GetLine(LineText);
4028 sscanf(&(LineText[7]),"%ld", &test);
4029 InputOptions->Control->SetMPLevel(test);
4030 Buffer->SetFilePos(StartPos);
4031 }
4032
4033 if (Buffer->LocateKeyWord("CITYP", 5, EndPos)) {
4034 Buffer->GetLine(LineText);
4035 sscanf(&(LineText[7]),"%s", token);
4036 InputOptions->Control->SetCIType(token);
4037 Buffer->SetFilePos(StartPos);
4038 }
4039
4040 if (Buffer->LocateKeyWord("CCTYP", 5, EndPos)) {
4041 Buffer->GetLine(LineText);
4042 sscanf(&(LineText[7]),"%s", token);
4043 InputOptions->Control->SetCCType(token);
4044 Buffer->SetFilePos(StartPos);
4045 }
4046
4047 if (Buffer->LocateKeyWord("LOCAL", 5, EndPos)) {
4048 Buffer->GetLine(LineText);
4049 sscanf(&(LineText[7]), "%s", token);
4050 InputOptions->Control->SetLocal(token);
4051 Buffer->SetFilePos(StartPos);
4052 }
4053
4054 if (Buffer->LocateKeyWord("MULT", 4, EndPos)) {
4055 Buffer->GetLine(LineText);
4056 sscanf(&(LineText[7]),"%ld", &test);
4057 InputOptions->Control->SetMultiplicity(test);
4058 Buffer->SetFilePos(StartPos);
4059 }
4060
4061 if (Buffer->LocateKeyWord("ICHARG", 6, EndPos)) {
4062 Buffer->GetLine(LineText);
4063 sscanf(&(LineText[7]),"%ld", &test);
4064 InputOptions->Control->SetCharge(test);
4065 Buffer->SetFilePos(StartPos);
4066 }
4067
4068 if (Buffer->LocateKeyWord("MAXIT", 5, EndPos)) {
4069 Buffer->GetLine(LineText);
4070 sscanf(&(LineText[7]),"%ld", &test);
4071 InputOptions->Control->SetMaxIt(test);
4072 Buffer->SetFilePos(StartPos);
4073 }
4074
4075 bool foo = Buffer->LocateKeyWord("ECP", 3, EndPos);
4076 if (!foo) foo = Buffer->LocateKeyWord("PP ", 4, EndPos);
4077 if (foo) {
4078 Buffer->GetLine(LineText);
4079 sscanf(&(LineText[7]),"%s", token);
4080 InputOptions->Basis->SetECPPotential(token);
4081 Buffer->SetFilePos(StartPos);
4082 }
4083
4084 if (Buffer->LocateKeyWord("ISPHER", 6, EndPos)) {
4085 Buffer->GetLine(LineText);
4086 sscanf(&(LineText[7]),"%ld", &test);
4087 if (test == 1) InputOptions->Control->UseSphericalHarmonics(true);
4088 Buffer->SetFilePos(StartPos);
4089 }
4090 if (Buffer->LocateKeyWord("NOSYM", 5, EndPos)) {
4091 Buffer->GetLine(LineText);
4092 sscanf(&(LineText[7]),"%ld", &test);
4093 InputOptions->Data->SetUseSym((test==0));
4094 Buffer->SetFilePos(StartPos);
4095 }
4096
4097 if (Buffer->LocateKeyWord("NORMF", 5, EndPos)) {
4098 Buffer->GetLine(LineText);
4099 sscanf(&(LineText[7]),"%ld", &test);
4100 InputOptions->Control->SetNormF((test!=0));
4101 Buffer->SetFilePos(StartPos);
4102 }
4103
4104 if (Buffer->LocateKeyWord("NORMP", 5, EndPos)) {
4105 Buffer->GetLine(LineText);
4106 sscanf(&(LineText[7]),"%ld", &test);
4107 InputOptions->Control->SetNormP((test!=0));
4108 Buffer->SetFilePos(StartPos);
4109 }
4110 }
ReadSystemOptions(BufferFile * Buffer)4111 void SystemGroup::ReadSystemOptions(BufferFile * Buffer) {
4112 char LineText[kMaxLineLength], token[kMaxLineLength];
4113 wxFileOffset StartPos = Buffer->GetFilePos(); //All keywords should be between these positions
4114 wxFileOffset EndPos = Buffer->FindBlankLine();
4115
4116 if (Buffer->LocateKeyWord("MEMORY=", 7, EndPos)) {
4117 Buffer->GetLine(LineText);
4118 double temp=0.0;
4119 sscanf(&(LineText[7]), "%lf", &temp);
4120 SetMemory(temp);
4121 Buffer->SetFilePos(StartPos);
4122 }
4123 if (Buffer->LocateKeyWord("MEMDDI=", 7, EndPos)) {
4124 Buffer->GetLine(LineText);
4125 double temp=0.0;
4126 sscanf(&(LineText[7]), "%lf", &temp);
4127 SetMemDDI(temp);
4128 Buffer->SetFilePos(StartPos);
4129 }
4130 if (Buffer->LocateKeyWord("TIMLIM=", 7, EndPos)) {
4131 Buffer->GetLine(LineText);
4132 double temp=0.0;
4133 sscanf(&(LineText[7]), "%lf%s", &temp, token);
4134 if (FindKeyWord(token, "SECONDS", 7)>=0)
4135 temp /= 60.0; //For some odd reason TIMLIM is printed in seconds...
4136 SetTimeLimit((long) temp);
4137 Buffer->SetFilePos(StartPos);
4138 }
4139 if (Buffer->LocateKeyWord("PARALL=", 7, EndPos)) {
4140 Buffer->GetLine(LineText);
4141 sscanf(&(LineText[7]), "%s", token);
4142 if (token[0]=='F') SetParallel(false);
4143 else if (token[0]=='T') SetParallel(true);
4144 Buffer->SetFilePos(StartPos);
4145 }
4146 if (Buffer->LocateKeyWord("BALTYP=", 7, EndPos)) {
4147 Buffer->GetLine(LineText);
4148 sscanf(&(LineText[7]), "%s", token);
4149 if (FindKeyWord(token, "LOOP", 4)>=0)
4150 SetBalanceType(true);
4151 Buffer->SetFilePos(StartPos);
4152 }
4153 if (Buffer->LocateKeyWord("COREFL=", 7, EndPos)) {
4154 Buffer->GetLine(LineText);
4155 sscanf(&(LineText[7]), "%s", token);
4156 if (token[0]=='F') SetCoreFlag(false);
4157 else if (token[0]=='T') SetCoreFlag(true);
4158 Buffer->SetFilePos(StartPos);
4159 }
4160 if (Buffer->LocateKeyWord("KDIAG=", 6, EndPos)) {
4161 Buffer->GetLine(LineText);
4162 int temp;
4163 sscanf(&(LineText[6]), "%d", &temp);
4164 SetDiag(temp);
4165 }
4166 }
OpenGAMESSTRJ(BufferFile * Buffer,bool Append,long flip,float offset)4167 long MolDisplayWin::OpenGAMESSTRJ(BufferFile * Buffer, bool Append, long flip, float offset)
4168 {
4169 TypeOfRun runType=InvalidRunType;
4170 char LineText[kMaxLineLength+1];
4171 bool FirstFrame = true;
4172 long IRCnSkip = Prefs->GetDRCSkip();
4173 long nSkip = 0;
4174
4175 ProgressInd->ChangeText("Reading GAMESS trajectory file...");
4176 Frame * lFrame = MainData->cFrame;
4177
4178 long NumAIAtoms=0, NumFragments=0, NumMDAtoms=0;
4179 //Determine the specific run type
4180 //the 1024 is arbitrary, but if it's not found in the first 1024 bytes it probably isn't there
4181 if (Buffer->LocateKeyWord("===== IRC DATA PACKET", 21, 1024)) {
4182 runType = IRCRun;
4183 } else if (Buffer->LocateKeyWord("===== DRC DATA PACKET", 21, 1024)) {
4184 runType = DRCRun;
4185 } else if (Buffer->LocateKeyWord("===== MD DATA PACKET", 20, 1024)) {
4186 runType = MolDynamics;
4187 } else if (Buffer->LocateKeyWord("ACCEPTED AT GLOBAL SEARCH POINT", 20, 1024)) {
4188 runType = GLOBOPRun;
4189 wxFileOffset start = Buffer->GetFilePos();
4190 wxFileOffset fragStart=0;
4191 if (Buffer->LocateKeyWord("COORDINATES OF FRAGMENT MULTIPOLE CENTERS", 40)) {
4192 fragStart = Buffer->GetFilePos();
4193 }
4194 wxFileOffset nextPoint = Buffer->GetFileLength();
4195 if (Buffer->LocateKeyWord("ACCEPTED AT GLOBAL SEARCH POINT", 20)) {
4196 nextPoint = Buffer->GetFilePos();
4197 }
4198 if (fragStart > 0) {
4199 Buffer->SetFilePos(fragStart);
4200 while (Buffer->LocateKeyWord("FRAGNAME", 8, nextPoint)) {
4201 NumFragments++;
4202 Buffer->SkipnLines(1);
4203 }
4204 } else fragStart = nextPoint;
4205 Buffer->SetFilePos(start);
4206 NumAIAtoms = Buffer->GetNumLines(fragStart - start) - 5;//subtract off the header lines
4207 }
4208 if (!Append) { //set the runtype
4209 if (!MainData->InputOptions) MainData->InputOptions = new InputData;
4210 if (runType) MainData->InputOptions->Control->SetRunType(runType);
4211 }
4212 Buffer->SetFilePos(0);
4213 std::vector<std::pair <std::string, int> > keywords;
4214 keywords.push_back(make_pair (std::string("DATA PACKET"), 1));
4215 keywords.push_back(make_pair (std::string("ACCEPTED AT GLOBAL SEARCH POINT"), 2));
4216
4217 std::vector<std::pair <std::string, int> > AIkeywords;
4218 AIkeywords.push_back(make_pair (std::string("----- QM PARTICLE COORDINATES"), 1));
4219 AIkeywords.push_back(make_pair (std::string("COORDINATES OF ALL ATOMS ARE"), 2));
4220
4221 std::vector<std::pair <std::string, int> > FragmentAtomsKeywords;
4222 FragmentAtomsKeywords.push_back(make_pair (std::string("----- EFP PARTICLE COORDINATES"), 1));
4223 FragmentAtomsKeywords.push_back(make_pair (std::string("COORDINATES OF FRAGMENT MULTIPOLE CENTERS"), 2));
4224
4225 //search for the beginning of the information packet
4226
4227 while (Buffer->LocateKeyWord(keywords) > -1) {
4228 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
4229 { throw UserCancel();}
4230 //if this is an irc we could pull the point out of the header line
4231 if (runType == IRCRun) {
4232 Buffer->GetLine(LineText);
4233 long point=0;
4234 long pos = FindKeyWord(LineText, "FOR STEP", 8);
4235 if (pos >= 0) {
4236 sscanf(&(LineText[pos+8]), "%ld", &point);
4237 }
4238 lFrame->IRCPt = point * flip;
4239 } else
4240 Buffer->SkipnLines(1);
4241 //search for the end of the packet?
4242 //first line give atom counts, nat= 3 nfrg= 1 nqmmm= 0
4243 Buffer->GetLine(LineText);
4244 if (nSkip >= IRCnSkip) {
4245 nSkip = 0;
4246 float xvalue=0.0;
4247 double totE=0.0;
4248 if (runType == GLOBOPRun) {
4249 Buffer->BackupnLines(2); //Need the first line for GlobOp files
4250 Buffer->GetLine(LineText);
4251 ReadDoubleKeyword(LineText, "ENERGY", totE);
4252 int Pos = FindKeyWord(LineText, "POINT", 5);
4253 if (Pos >= 0) {
4254 sscanf(&(LineText[Pos+5]), "%f", &xvalue);
4255 }
4256 } else {
4257 if (!ReadLongKeyword(LineText, "NAT", &NumAIAtoms))
4258 wxLogMessage(_("Unable to locate NAT (ab initio atom count)."));
4259 if (!ReadLongKeyword(LineText, "NFRG", &NumFragments))
4260 wxLogMessage(_("Unable to locate NFRG (fragment count)."));
4261 if (!ReadLongKeyword(LineText, "NQMMM", &NumMDAtoms))
4262 wxLogMessage(_("Unable to locate NQMM (MM atom count)."));
4263
4264 //second line is the x-axis and total energy, either ttotal or stotal
4265 //STOTAL= 1.49848 sqrt(amu)*bohr tot. E= -91.6219797490 Hartree
4266 Buffer->GetLine(LineText);
4267 if (runType == IRCRun) {
4268 if (!ReadFloatKeyword(LineText, "STOTAL", &xvalue)) {
4269 wxLogMessage(_("Unable to locate STOTAL in IRC data packet. Unable to position this packet in the sequence."));
4270 }
4271 } else { //MD and DRC spell it TTOTAL
4272 if (!ReadFloatKeyword(LineText, "TTOTAL", &xvalue)) {
4273 wxLogMessage(_("Unable to locate TOTAL in trajectory data packet. Unable to position this packet in the sequence."));
4274 }
4275 }
4276 ReadDoubleKeyword(LineText, "TOT. E", totE);
4277 }
4278
4279 xvalue *= flip;
4280 xvalue += offset;
4281 Frame * lFrame = NULL;
4282 if (!Append && FirstFrame) {
4283 lFrame = MainData->Frames;
4284 lFrame->time = xvalue;
4285 FirstFrame = false;
4286 } else
4287 lFrame = MainData->LocateNewFrame(xvalue);
4288 if (lFrame) {
4289 lFrame->Energy = totE;
4290 // DRCs have an extra line with the kinetic and potential energies
4291 //POT. E= -9.1287351998 kin. E= .0016326701 Hartree
4292 if (runType == DRCRun) {
4293 //DRCs conserve energy so Tot E == Pot. E + kinetic E.
4294 //Thus only need to store two of them.
4295 Buffer->GetLine(LineText);
4296 double kinE;
4297 if (ReadDoubleKeyword(LineText, "KIN. E", kinE))
4298 lFrame->SetEnergy(kinE, KineticEnergy);
4299 } else if (runType == MolDynamics) {
4300 // MD runs have two extra lines for energies
4301 //POT. E= -47726.960743 kcal/mol
4302 //kin. E= 7.015829 trans KE= 5.422237 rot KE= 1.593592 kcal/mol
4303 //Todo: For MD runs energy is not necessarily conserved so all energies could be stored
4304 //Don't have the infrastructure for that at the moment.
4305 Buffer->GetLine(LineText);
4306 Buffer->GetLine(LineText);
4307 double kinE;
4308 if (ReadDoubleKeyword(LineText, "KIN. E", kinE))
4309 lFrame->SetEnergy(kinE, KineticEnergy);
4310 else
4311 wxLogMessage(_("Unable to parse the kinetic energy while reading a molecular dynamics trajectory file. The file format may not be correct."));
4312 }
4313
4314 //setup the frame for the antipated atom count
4315 if (!MainData->SetupFrameMemory(NumAIAtoms+NumFragments+NumMDAtoms, 0)) throw MemoryError();
4316
4317 if (NumAIAtoms > 0) {
4318 switch (Buffer->LocateKeyWord(AIkeywords)) {
4319 case 1:
4320 Buffer->SkipnLines(1);
4321 ParseGLogLine(Buffer, lFrame, NumAIAtoms, 10, &(MainData->MaxSize));
4322 break;
4323 case 2:
4324 Buffer->SkipnLines(3); //just skip the header lines
4325 ParseGLogLine(Buffer, lFrame, NumAIAtoms, 10, &(MainData->MaxSize));
4326 break;
4327 default:
4328 wxLogMessage(_("Expected ab initio atoms, but unable to locate header."));
4329 }
4330 }
4331 int fragkey;
4332 if ((NumFragments > 0)&&(fragkey = Buffer->LocateKeyWord(FragmentAtomsKeywords))) {
4333 if (fragkey == 1)
4334 Buffer->SkipnLines(1);
4335 else if (fragkey == 2)
4336 Buffer->SkipnLines(3);
4337 if (fragkey > 0) {
4338 mpAtom *atm;
4339 CPoint3D dst_locs[3];
4340 CPoint3D pos;
4341 int fstart;
4342 int match[3] = {0, 0, 0};
4343 CPoint3D src_locs[3];
4344 std::string labels[3];
4345 long fragNum, fragmentsfound=0;
4346 int i;
4347 CPoint3D new_pos;
4348 CPoint3D rot_pos;
4349 CPoint3D curr_pos;
4350 CPoint3D orig;
4351 Matrix4D vec2vec;
4352 CPoint3D src_vec;
4353 CPoint3D dst_vec;
4354 CPoint3D dst_vec2;
4355 CPoint3D dst_norm;
4356 CPoint3D mid_norm;
4357 CPoint3D mid_vec1, mid_vec2;
4358 float dot;
4359 char token[kMaxLineLength+1];
4360
4361 Buffer->GetLine(LineText);
4362 while (ReadStringKeyword(LineText, "FRAGNAME", token)) {
4363 if (!strcasecmp(token, "H2ORHF") || !strcasecmp(token, "H2ODFT")) { //builtin EFP1 style is limited to H2O with known labels
4364 MainData->FragmentNames.push_back(std::string(token));
4365 long fragNum = MainData->FragmentNames.size();
4366 CPoint3D pos;
4367 int AtomType;
4368 for (int i=0; i<3; ++i) {
4369 AtomType = -1;
4370 Buffer->GetLine(LineText);
4371 //lines have format "label x, y, z"
4372 sscanf(LineText, "%s %f %f %f", token, &pos.x, &pos.y, &pos.z);
4373 int c = 0;
4374 if ((token[0] == 'Z')||(token[0] == 'z')) c = 1;
4375 if (!strcasecmp(&(token[c]), "O1")) AtomType = 8;
4376 else if (!strcasecmp(&(token[c]), "H2")||!strcasecmp(&(token[c]), "H3")) AtomType = 1;
4377 if (AtomType > 0) {
4378 mpAtom * atm = lFrame->AddAtom(AtomType, pos);
4379 atm->SetFragmentNumber(fragNum);
4380 }
4381 }
4382 }
4383
4384 // Custom fragment type.
4385 else {
4386
4387 // Read the three atoms that setup the fragment. These
4388 // should be in angstroms.
4389 MainData->FragmentNames.push_back(std::string(token));
4390 fragNum = MainData->FragmentNames.size();
4391 char label[kMaxLineLength];
4392 for (i = 0; i < 3; ++i) {
4393 Buffer->GetLine(LineText);
4394 sscanf(LineText, "%s %f %f %f", label,
4395 &(dst_locs[i].x), &(dst_locs[i].y),
4396 &(dst_locs[i].z));
4397 labels[i] = label;
4398 /* std::cout << "Line: " << Line << std::endl; */
4399 /* atm = lFrame->AddAtom(1, dst_locs[i]); */
4400 /* atm->SetFragmentNumber(fragNum); */
4401 }
4402
4403 //The fragment definition must be either already in the local list or in
4404 //the builder library. FindFragmentDef will find it either way.
4405 std::map<std::string, EFrag>::const_iterator frag;
4406 frag = FindFragmentDef(token);
4407 if (frag == MainData->efrags.end()) {
4408 wxString msg;
4409 msg.Printf(_("Unable to locate correct EFP2 fragment definition group named %s"), token);
4410 wxLogMessage(msg);
4411 throw DataError();
4412 }
4413
4414 fstart = lFrame->NumAtoms;
4415 const std::vector<EFragAtom>& labeled_atoms = frag->second.GetAtoms();
4416 std::vector<EFragAtom>::const_iterator efrag_atom;
4417
4418 for (efrag_atom = labeled_atoms.begin();
4419 efrag_atom != labeled_atoms.end();
4420 ++efrag_atom) {
4421
4422 if (efrag_atom->GetLabel().compare(labels[0]) == 0) {
4423 match[0] = lFrame->NumAtoms;
4424 src_locs[0] = efrag_atom->GetCoords();
4425 } else if (efrag_atom->GetLabel().compare(labels[1]) == 0) {
4426 match[1] = lFrame->NumAtoms;
4427 src_locs[1] = efrag_atom->GetCoords();
4428 } else if (efrag_atom->GetLabel().compare(labels[2]) == 0) {
4429 match[2] = lFrame->NumAtoms;
4430 src_locs[2] = efrag_atom->GetCoords();
4431 }
4432
4433 atm = lFrame->AddAtom(efrag_atom->GetAtomicNumber(),
4434 efrag_atom->GetCoords());
4435 atm->SetFragmentNumber(fragNum);
4436 }
4437
4438 // We first find a rotation that one will align a vector
4439 // in the fragment template to the corresponding vector in
4440 // the destination space.
4441 dst_vec = dst_locs[1] - dst_locs[0];
4442 Normalize3D(&dst_vec);
4443
4444 src_vec = src_locs[1] - src_locs[0];
4445 Normalize3D(&src_vec);
4446
4447 SetRotationMatrix(vec2vec, &src_vec, &dst_vec);
4448
4449 // The common vector now serves as an axis of rotation. We
4450 // need to rotate the fragment template plane so that it
4451 // coincides with the destination plane. The angle of rotation
4452 // can be determined by the angle between the two planes'
4453 // normals.
4454 lFrame->GetAtomPosition(match[0], orig);
4455 Rotate3DOffset(vec2vec, src_locs[1] - orig, &mid_vec1);
4456 Rotate3DOffset(vec2vec, src_locs[2] - orig, &mid_vec2);
4457 UnitCrossProduct3D(&mid_vec1, &mid_vec2, &mid_norm);
4458
4459 dst_vec2 = dst_locs[2] - dst_locs[0];
4460 UnitCrossProduct3D(&dst_vec, &dst_vec2, &dst_norm);
4461
4462 Matrix4D tri2tri;
4463 dot = DotProduct3D(&mid_norm, &dst_norm);
4464
4465 // Technically, the axis of rotation (the aligned vector)
4466 // might be facing a different direction than we think it
4467 // is. To be consistent, we instead use the axis that is
4468 // normal to both planes' normals. It points in the same
4469 // or opposite direction as dst_vec.
4470 CPoint3D axis;
4471 UnitCrossProduct3D(&mid_norm, &dst_norm, &axis);
4472 RotateAroundAxis(tri2tri, axis, acos(dot) * 180.0f / kPi);
4473
4474 // We concatenate the two rotation matrices.
4475 Matrix4D transform;
4476 MultiplyMatrix(vec2vec, tri2tri, transform);
4477
4478 // Okay, for each atom we added for this fragment instance,
4479 // we move all fragment atoms into destination space. We
4480 // translate to make the base fragment atom the origin and
4481 // then rotate to align the fragment with the destination
4482 // plane, and then translate by the base destination atom.
4483 for (long i = fstart; i < lFrame->NumAtoms; ++i) {
4484 lFrame->GetAtomPosition(i, curr_pos);
4485 new_pos = curr_pos - orig;
4486 Rotate3DOffset(transform, new_pos, &rot_pos);
4487 new_pos = rot_pos + dst_locs[0];
4488 lFrame->SetAtomPosition(i, new_pos);
4489 }
4490 }
4491 fragmentsfound++;
4492 if (fragmentsfound < NumFragments) {
4493 //gamess prints out all the coordinates, but we only read the first three
4494 //need to skip the rest to the start of the next fragment
4495 if (Buffer->LocateKeyWord("FRAGNAME", 8))
4496 Buffer->GetLine(LineText);
4497 }
4498 }
4499 }
4500
4501 }
4502 if ((NumMDAtoms > 0)&&Buffer->LocateKeyWord("----- MM PARTICLE COORDINATES", 29)) {
4503 Buffer->SkipnLines(1);
4504 }
4505
4506 if (Prefs->GetAutoBond())
4507 lFrame->SetBonds(Prefs, false, ProgressInd);
4508 }
4509 } else
4510 ++ nSkip;
4511 }
4512 return 1;
4513 }
OpenGAMESSIRC(BufferFile * Buffer,bool Append,long flip,float offset)4514 long MolDisplayWin::OpenGAMESSIRC(BufferFile * Buffer, bool Append, long flip, float offset)
4515 { long LinePos, NumAtoms, point;
4516 float Xpos;
4517 bool KeyWordFound;
4518 char LineText[kMaxLineLength+1];
4519
4520 ProgressInd->ChangeText("Reading GAMESS IRC file...");
4521 Frame * lFrame = MainData->cFrame;
4522 long IRCnSkip = Prefs->GetDRCSkip();
4523 long nSkip = 0;
4524
4525 if (!Append) {
4526 if (!Buffer->LocateKeyWord("IRC INFORMATION PACKET", 22)) return 0;
4527 if (!Buffer->LocateKeyWord("POINT=", 6)) return 0;
4528 Buffer->GetLine(LineText);
4529 LinePos = 6;
4530 sscanf(&(LineText[LinePos]), "%ld", &point);
4531 lFrame->IRCPt = (long) (flip*point + offset);
4532 LinePos = FindKeyWord(LineText, "STOTAL=", 7) + 7;
4533 sscanf(&(LineText[LinePos]), "%f", &(lFrame->time));
4534 lFrame->time *= flip;
4535 lFrame->time += offset;
4536 LinePos = FindKeyWord(LineText, "E=", 2) + 2;
4537 sscanf(&(LineText[LinePos]), "%lf", &(lFrame->Energy));
4538 Buffer->SkipnLines(1); //skip "Coordinates (bohr)... label line
4539
4540 wxFileOffset start = Buffer->GetFilePos();
4541 if (!Buffer->LocateKeyWord("MASS-WEIGHTED GRADIENT", 22)) throw DataError();
4542 wxFileOffset endpos = Buffer->GetFilePos();
4543 Buffer->SetFilePos(start);
4544 NumAtoms = Buffer->GetNumLines(endpos-start);
4545
4546 if (!MainData->SetupFrameMemory(NumAtoms, 0)) throw MemoryError();
4547
4548 ParseGLogLine(Buffer, lFrame, NumAtoms, 0, &(MainData->MaxSize));
4549
4550 if (Prefs->GetAutoBond())
4551 lFrame->SetBonds(Prefs, false, ProgressInd);
4552 }
4553 NumAtoms = lFrame->NumAtoms;
4554 KeyWordFound = Buffer->LocateKeyWord("POINT=", 6);
4555 while (KeyWordFound) {
4556 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
4557 { throw UserCancel();}
4558 Buffer->GetLine(LineText);
4559 if (nSkip >= IRCnSkip) {
4560 nSkip = 0;
4561 LinePos = 6;
4562 sscanf(&(LineText[LinePos]), "%ld", &point);
4563 point *= flip;
4564 LinePos = FindKeyWord(LineText, "STOTAL=", 7) + 7;
4565 sscanf(&(LineText[LinePos]), "%f", &Xpos);
4566 Xpos *= flip;
4567 Xpos += offset;
4568 lFrame = MainData->LocateNewFrame(Xpos);
4569
4570 if (lFrame) {
4571 lFrame->IRCPt = point;
4572 LinePos = FindKeyWord(LineText, "E=", 2) + 2;
4573 sscanf(&(LineText[LinePos]), "%lf", &(lFrame->Energy));
4574 Buffer->SkipnLines(1); //skip "Coordinates (bohr)... label line
4575
4576 sprintf(LineText, "Reading in IRC point %ld", point);
4577 ProgressInd->ChangeText(LineText);
4578
4579 if (!MainData->SetupFrameMemory(NumAtoms, 0)) throw MemoryError();
4580
4581 if (ParseGLogLine(Buffer, lFrame, NumAtoms, 0, &(MainData->MaxSize)) <= 0) break;
4582
4583 if (Prefs->GetAutoBond())
4584 lFrame->SetBonds(Prefs, false, ProgressInd);
4585 }
4586 } else
4587 ++nSkip;
4588 KeyWordFound = Buffer->LocateKeyWord("POINT=", 6);
4589 }
4590 MainData->cFrame = MainData->Frames;
4591 MainData->CurrentFrame = 1;
4592 return 1;
4593 } /*OpenGAMESSIRC*/
OpenGAMESSIRCLog(BufferFile * Buffer,long flip,float offset,long NumOccAlpha,long NumOccBeta,long NumFragmentAtoms)4594 long MolDisplayWin::OpenGAMESSIRCLog(BufferFile * Buffer, long flip, float offset,
4595 long NumOccAlpha, long NumOccBeta, long NumFragmentAtoms) {
4596 long point, LinePos, NumBetaUHFOrbs=0;
4597 char LineText[kMaxLineLength+1];
4598 float Xpos;
4599 bool LINEAR=false;
4600
4601 ProgressInd->ChangeText("Reading GAMESS IRC log file...");
4602 Frame * lFrame = MainData->cFrame;
4603 long IRCnSkip = Prefs->GetDRCSkip();
4604 long nSkip = 0;
4605
4606 long NumAtoms = lFrame->NumAtoms;
4607 long NumExpectedAtoms = NumAtoms;
4608 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_UHF) NumBetaUHFOrbs = NumOccBeta; //Only seperate Beta spin orbs for UHF wavefunctions
4609 char NextPointKeyword[30];
4610 strcpy(NextPointKeyword, "* NEXT POINT ON IRC FOUND *");
4611 bool KeyWordFound = Buffer->LocateKeyWord(NextPointKeyword, 27);
4612 if (!KeyWordFound) { //search for the alternative keyword needed for pace=linear IRC's
4613 strcpy(NextPointKeyword, "ON THE REACTION PATH");
4614 KeyWordFound = Buffer->LocateKeyWord(NextPointKeyword, 20);
4615 if (KeyWordFound) LINEAR=true;
4616 }
4617 while (KeyWordFound) {
4618 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
4619 { throw UserCancel();}
4620 if (LINEAR) Buffer->BackupnLines(1);
4621 Buffer->SkipnLines(1);
4622 if (Buffer->LocateKeyWord("POINT", 5)) {
4623 Buffer->GetLine(LineText);
4624 LinePos = 6;
4625 int result = sscanf(&(LineText[LinePos]), "%ld", &point);
4626 if (result != 1) break;
4627 } else break;
4628 if (Buffer->LocateKeyWord("STOTAL", 6)) {
4629 Buffer->GetLine(LineText);
4630 LinePos = 8;
4631 int result = sscanf(&(LineText[LinePos]), "%f", &Xpos);
4632 if (result != 1) break;
4633 } else break;
4634 lFrame = NULL;
4635 if (nSkip >= IRCnSkip) {
4636 nSkip = 0;
4637 point *= flip;
4638 Xpos *= flip;
4639 Xpos += offset;
4640 lFrame = MainData->LocateNewFrame(Xpos);
4641 if (lFrame) {
4642 sprintf(LineText, "Reading in IRC point %ld", point);
4643 ProgressInd->ChangeText(LineText);
4644
4645 lFrame->IRCPt = point;
4646 if (Buffer->LocateKeyWord("ENERGY =", 19)) {
4647 Buffer->GetLine(LineText);
4648 LinePos = 20;
4649 sscanf(&(LineText[LinePos]), "%lf", &(lFrame->Energy));
4650 }
4651
4652 if (!Buffer->LocateKeyWord("COORDINATES OF ALL ATOMS", 24)) break;
4653 Buffer->SkipnLines(3);
4654
4655 MainData->SetupFrameMemory(NumAtoms, 0);
4656
4657 ParseGLogLine(Buffer, lFrame, NumAtoms, 10, &(MainData->MaxSize));
4658
4659 if ((NumFragmentAtoms <= 0)&&(NumExpectedAtoms > MainData->cFrame->NumAtoms))
4660 NumFragmentAtoms = NumExpectedAtoms - MainData->cFrame->NumAtoms;
4661 if (NumFragmentAtoms > 0) {
4662 Buffer->BackupnLines(2);
4663 if (Buffer->LocateKeyWord("COORDINATES OF FRAGMENT MULTIPOLE CENTERS", 41)) {
4664 Buffer->SkipnLines(3);
4665 MainData->ReadFragmentCoordinates(Buffer, NumFragmentAtoms);
4666 }
4667 }
4668 if (Prefs->GetAutoBond())
4669 lFrame->SetBonds(Prefs, false, ProgressInd);
4670 }
4671 } else
4672 ++ nSkip;
4673 wxFileOffset SavedPos = Buffer->GetFilePos();
4674 KeyWordFound = Buffer->LocateKeyWord(NextPointKeyword, 20);
4675 wxFileOffset NextPointPos = -1;
4676 if (KeyWordFound) NextPointPos = Buffer->GetFilePos();
4677 if (lFrame) {
4678 //Attempt to read in orbitals for this geometry
4679 if (MainData->Basis) {
4680 Buffer->SetFilePos(SavedPos);
4681 try {
4682 bool test = Buffer->LocateKeyWord("CONVERGED ORBITALS AT IRC POINT", 31, NextPointPos);
4683 if (test) {
4684 //skip over the line to the start of the orbital blocks
4685 //There is always a blank line before the orbs, but there may a '---' divider line after the key line just found
4686 if ((NextPointPos<0)||(NextPointPos>Buffer->GetFilePos())) {
4687 Buffer->SetFilePos(Buffer->FindBlankLine());
4688 Buffer->SkipnLines(1);
4689 ProgressInd->ChangeText("Reading eigenvectors");
4690 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
4691 { throw UserCancel();}
4692 lFrame->ParseGAMESSEigenVectors(Buffer, MainData->GetNumBasisFunctions(),
4693 MainData->GetNumBasisFunctions(), NumBetaUHFOrbs, NumOccAlpha, NumOccBeta,
4694 (TypeOfWavefunction)(MainData->InputOptions->Control->GetSCFType()), ProgressInd);
4695 // if (MainData->InputOptions->Control->GetSCFType()==MCSCF)
4696 // lFrame->ExchangeEigenVectors();
4697 } else Buffer->SetFilePos(SavedPos);
4698 }
4699 // if (lFrame->Orbs) {
4700 // lFrame->Orbs->NumOccupiedAlphaOrbs = NumOccAlpha;
4701 // lFrame->Orbs->NumOccupiedBetaOrbs = NumOccBeta;
4702 // if (lFrame->Orbs->EigenVectors)
4703 // lFrame->Orbs->EigenVectors->OrbType = MainData->InputOptions->Control->GetSCFType();
4704 // }
4705 }
4706 catch (std::bad_alloc) {
4707 // if (lFrame->Orbs) delete lFrame->Orbs;
4708 // lFrame->Orbs = NULL;
4709 MessageAlert("Insufficient memory to read in eigenvectors.");
4710 }
4711 catch (MemoryError) {
4712 // if (lFrame->Orbs) delete lFrame->Orbs;
4713 // lFrame->Orbs = NULL;
4714 MessageAlert("Insufficient memory to read in eigenvectors.");
4715 }
4716 catch (DataError) {
4717 MessageAlert("Error reading eigenvectors, orbitals skipped.");
4718 // if (lFrame->Orbs) delete lFrame->Orbs;
4719 // lFrame->Orbs = NULL;
4720 }
4721 }
4722 if (NextPointPos >= 0)
4723 Buffer->SetFilePos(NextPointPos);
4724 }
4725 }
4726 MainData->cFrame = MainData->Frames;
4727 MainData->CurrentFrame = 1;
4728 return 1;
4729 } /*OpenGAMESSIRCLog*/
OpenGAMESSDRC(BufferFile * Buffer,bool LogFile,bool Append,long flip,float offset)4730 long MolDisplayWin::OpenGAMESSDRC(BufferFile * Buffer, bool LogFile, bool Append,
4731 long flip, float offset) {
4732
4733 bool QPpresent, KeyWordFound, newQPformat=false;
4734 long NumAtoms, Elength, nskip=0, LinePos, EStartPos;
4735 char Etext[40], LineText[kMaxLineLength+1];
4736 float tempfloat;
4737 double PE, KE;
4738
4739 ProgressInd->ChangeText("Reading GAMESS DRC file...");
4740 Frame * lFrame = MainData->cFrame;
4741 if (!Append) {
4742 }
4743 wxFileOffset FilePos = Buffer->GetFilePos();
4744 QPpresent = Buffer->LocateKeyWord("Q P", 12);
4745 if (!QPpresent) newQPformat = Buffer->LocateKeyWord("Q P", 16);
4746 Buffer->SetFilePos(FilePos);
4747 //test for Q P since there are two possible formats (Q P... include some mode information)
4748 if (QPpresent) {
4749 strncpy(Etext, "ENERGY ENERGY ENERGY", 34);
4750 Elength = 34;
4751 EStartPos = 41;
4752 } else if (newQPformat) { //After Sep62001R5 the header changed a bit
4753 strncpy(Etext, "E ENERGY ENERGY", 31);
4754 Elength = 31;
4755 EStartPos = 41;
4756 QPpresent = true;
4757 } else {
4758 strncpy(Etext, "ENERGY ENERGY ENERGY", 36);
4759 Elength = 36;
4760 EStartPos = 12;
4761 }
4762 KeyWordFound = Buffer->LocateKeyWord(Etext, Elength);
4763 if (!KeyWordFound) return 0;
4764 if (!Append) {
4765 Buffer->SkipnLines(1);
4766 Buffer->GetLine(LineText);
4767 sscanf(LineText, "%f", &(lFrame->time));
4768 lFrame->time *= flip;
4769 lFrame->time += offset;
4770 LinePos = EStartPos;
4771 sscanf(&(LineText[LinePos]), "%lf %lf %lf", &KE, &PE,
4772 &(lFrame->Energy));//Don't worry about the PE since E-KE=PE
4773 lFrame->SetEnergy(KE, KineticEnergy);
4774
4775 if (!Buffer->LocateKeyWord("VELOCITY", 8)) return 0;
4776 Buffer->SkipnLines(1);
4777 if (LogFile)
4778 Buffer->SkipnLines(1);
4779 FilePos = Buffer->GetFilePos();
4780 Buffer->LocateKeyWord("--------", 8);
4781 wxFileOffset endPos = Buffer->GetFilePos();
4782 Buffer->SetFilePos(FilePos);
4783 NumAtoms = Buffer->GetNumLines(endPos-FilePos)-1;
4784 if (NumAtoms <= 0) throw DataError();
4785
4786 if (!MainData->SetupFrameMemory(NumAtoms, 0)) throw MemoryError();
4787
4788 ParseGLogLine(Buffer, lFrame, NumAtoms, 2, &(MainData->MaxSize));
4789
4790 if (Prefs->GetAutoBond())
4791 lFrame->SetBonds(Prefs, false, ProgressInd);
4792
4793 KeyWordFound = Buffer->LocateKeyWord(Etext, Elength);
4794 }
4795
4796 NumAtoms = lFrame->NumAtoms;
4797 long DRCnSkip = Prefs->GetDRCSkip();
4798 while (KeyWordFound) {
4799 Buffer->SkipnLines(1);
4800 if (nskip >= DRCnSkip) {
4801 nskip = 0;
4802 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
4803 { throw UserCancel();}
4804 Buffer->GetLine(LineText);
4805 sscanf(LineText, "%f", &tempfloat);
4806 tempfloat *= flip;
4807 tempfloat += offset;
4808 lFrame = MainData->LocateNewFrame(tempfloat);
4809 if (lFrame == NULL) {
4810 KeyWordFound = Buffer->LocateKeyWord(Etext, Elength);
4811 continue;
4812 }
4813 LinePos = EStartPos;
4814 sscanf(&(LineText[LinePos]), "%lf %lf %lf", &KE, &PE,
4815 &(lFrame->Energy));//Don't worry about the PE since E-KE=PE
4816 lFrame->SetEnergy(KE, KineticEnergy);
4817
4818 sprintf(LineText, "Reading DRC time = %f", tempfloat);
4819 ProgressInd->ChangeText(LineText);
4820
4821 if (!MainData->SetupFrameMemory(NumAtoms, 0)) throw MemoryError();
4822
4823 if (!Buffer->LocateKeyWord("VELOCITY", 8)) break;;
4824 Buffer->SkipnLines(1);
4825 if (LogFile)
4826 Buffer->SkipnLines(1);
4827 if (ParseGLogLine(Buffer, lFrame, NumAtoms, 2, &(MainData->MaxSize)) < 0) break;
4828
4829 if (Prefs->GetAutoBond())
4830 lFrame->SetBonds(Prefs, false, ProgressInd);
4831 } else
4832 ++nskip;
4833 KeyWordFound = Buffer->LocateKeyWord(Etext, Elength);
4834 }
4835
4836 lFrame = MainData->Frames;
4837 for (long iframe=0; iframe<MainData->NumFrames; ++iframe) {
4838 lFrame->IRCPt = iframe + 1;
4839 lFrame = lFrame->NextFrame;
4840 }
4841 MainData->cFrame = MainData->Frames;
4842 MainData->CurrentFrame = 1;
4843 return 1;
4844 } /*OpenGAMESSDRC*/
4845
OpenGAMESSGlobOpLog(BufferFile * Buffer,long NumOccAlpha,long NumOccBeta,long NumFragmentAtoms)4846 long MolDisplayWin::OpenGAMESSGlobOpLog(BufferFile * Buffer,
4847 long NumOccAlpha, long NumOccBeta, long NumFragmentAtoms) {
4848 long NumBetaUHFOrbs=0;
4849 char LineText[kMaxLineLength+1];
4850
4851 ProgressInd->ChangeText("Reading GAMESS GlobOp log file...");
4852 Frame * lFrame = MainData->cFrame;
4853
4854 long NumAtoms = lFrame->NumAtoms;
4855 long NumExpectedAtoms = NumAtoms;
4856 MainData->SetCurrentFrame(MainData->GetNumFrames());
4857 //Setup a new frame for the initial geometry.
4858 lFrame = MainData->AddFrame(NumExpectedAtoms, lFrame->GetNumBonds());
4859 lFrame->IRCPt = MainData->GetCurrentFrame();
4860 lFrame->time = MainData->GetCurrentFrame();
4861 if (MainData->InputOptions->Control->GetSCFType()==GAMESS_UHF) NumBetaUHFOrbs = NumOccBeta; //Only seperate Beta spin orbs for UHF wavefunctions
4862
4863 // There appear to be two type of files, MCMIN=T|F. If true each accepted geometry is optimized
4864 // and the code should only grab the optimized coordinates and energies. If false then there is just
4865 // a single set of coordinates and energy.
4866 // If true look for "EQUILIBRIUM GEOMETRY LOCATED", grab the following coordinates and optionally, orbitals.
4867 // Both types end with an energy "ENERGY ACCEPTED AT POINT", probably best to use it.
4868 // It appears the globop frame is bracketed by "GEOMETRY NUMBER" and "ENERGY ACCEPTED", though not all
4869 // geometries are accepted.
4870
4871 // Old GlobOp files lack the keywords, but current ones do have them under the heading of
4872 // ---- MONTE CARLO/SIMULATED ANNEALING OPTIONS -----
4873
4874 enum GlobOpTags {
4875 GeomStart=0,
4876 NonOptGeometry,
4877 GeomEnd,
4878 GeomEnd2,
4879 OptGeometry,
4880 Orbitals,
4881 FailedOpt
4882 };
4883
4884 std::vector<std::pair <std::string, int> > keywords;
4885 keywords.push_back(make_pair (std::string("GEOMETRY NUMBER"), (int) GeomStart));//old style
4886 keywords.push_back(make_pair (std::string("EVALUATE ENERGY AT NEW TRANSLATIONAL GEOMETRY"), (int) GeomStart));//new style
4887 keywords.push_back(make_pair (std::string("BEGINNING GEOMETRY SEARCH POINT NSERCH="), (int) NonOptGeometry));//new style
4888 keywords.push_back(make_pair (std::string("NUCLEAR COORDINATES FOR GLOBAL OPTIMIZATION POINT"), (int) NonOptGeometry));
4889 keywords.push_back(make_pair (std::string("ENERGY ACCEPTED AT POINT"), (int) GeomEnd));
4890 keywords.push_back(make_pair (std::string("ENERGY ACCEPTED AT GLOBAL SEARCH POINT"), (int) GeomEnd2));
4891 keywords.push_back(make_pair(std::string("EQUILIBRIUM GEOMETRY LOCATED"), (int) OptGeometry));
4892 keywords.push_back(make_pair(std::string("MOLECULAR ORBITALS"), (int) Orbitals));
4893 keywords.push_back(make_pair(std::string("FAILURE TO LOCATE STATIONARY POINT"), (int) FailedOpt));
4894
4895 // In the old style there was a clear beginning and end of a search. In the new style it's a bit murkier.
4896 // The new style doesn't announce the end of an optimization until you are past the coordinates.
4897
4898 int state = 1, kw;
4899 while (! Buffer->Eof()) {
4900 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
4901 { throw UserCancel();}
4902 if (-1 < (kw = Buffer->LocateKeyWord(keywords))) {
4903 switch (kw) {
4904 case GeomStart: //start of a search point
4905 if (state == 0) {
4906 state = 1;
4907 } else {//found another start before finding the end of the previous geometry
4908 //The most likely reason is that the previous geometry was not accepted.
4909 //I could search for the rejection text, but this should do the trick.
4910 MainData->DeleteFrame();
4911 lFrame = MainData->GetCurrentFramePtr();
4912 }
4913 lFrame = MainData->AddFrame(NumExpectedAtoms, lFrame->GetNumBonds());
4914 lFrame->IRCPt = MainData->GetCurrentFrame();
4915 lFrame->time = MainData->GetCurrentFrame();
4916 Buffer->SkipnLines(1);
4917 break;
4918 case NonOptGeometry: // set of coordinates, MCMIN=false, these coords seem to be in an odd format
4919 if (state == 1) {
4920 if (lFrame->NumAtoms > 0) {
4921 MainData->DeleteFrame();
4922 lFrame = MainData->GetCurrentFramePtr();
4923 lFrame = MainData->AddFrame(NumExpectedAtoms, lFrame->GetNumBonds());
4924 lFrame->IRCPt = MainData->GetCurrentFrame();
4925 lFrame->time = MainData->GetCurrentFrame();
4926 }
4927 Buffer->SkipnLines(1);
4928
4929 //The output is in the form of index_# atomic name x y z
4930 if ((NumAtoms-NumFragmentAtoms)>0) {
4931 bool done=false;
4932 int nextExpected=1;
4933 while (!done) {
4934 if (Buffer->GetLine(LineText) < 1) break;
4935 int index;
4936 CPoint3D position;
4937 unsigned char Label[kMaxLineLength];
4938 int items = sscanf(LineText, "%d %s %f%f%f", &index, Label, &(position.x),
4939 &(position.y), &(position.z));
4940 if (items == 5) {
4941 if (index != nextExpected) {
4942 wxLogMessage(_("Error parsing coordinates, attempting to continue."));
4943 break;
4944 } else {
4945 int atomtype = SetAtomType(Label);
4946 if (atomtype > 0) {
4947 lFrame->AddAtom(atomtype, position);
4948 } else {
4949 wxLogMessage(_("Error parsing coordinates, attempting to continue."));
4950 break;
4951 }
4952 }
4953
4954 } else {
4955 Buffer->BackupnLines(1); //reset position and end
4956 break;
4957 }
4958 nextExpected ++;
4959 }
4960 }
4961
4962 if ((NumFragmentAtoms <= 0)&&(NumExpectedAtoms > MainData->cFrame->NumAtoms))
4963 NumFragmentAtoms = NumExpectedAtoms - MainData->cFrame->NumAtoms;
4964 if (NumFragmentAtoms > 0) {
4965 Buffer->BackupnLines(2);
4966 if (Buffer->LocateKeyWord("COORDINATES OF FRAGMENT MULTIPOLE CENTERS", 41)) {
4967 Buffer->SkipnLines(3);
4968 MainData->ReadFragmentCoordinates(Buffer, NumFragmentAtoms);
4969 }
4970 }
4971 if (Prefs->GetAutoBond())
4972 lFrame->SetBonds(Prefs, false, ProgressInd);
4973 } else {
4974 wxLogMessage(_("Unexpected set of coordinates! Skipping and attempting to continue"));
4975 Buffer->SkipnLines(1);
4976 }
4977 break;
4978 case GeomEnd: // End of the search, read the energy and store the frame.
4979 case GeomEnd2:
4980 if (state == 0) { // Found an end without a matching begining, skip
4981 wxLogMessage(_("Unexpected end of search point! Skipping and attempting to continue"));
4982 Buffer->SkipnLines(1);
4983 } else {
4984 Buffer->GetLine(LineText);
4985 int geom;
4986 int tokenLen = 25;
4987 if (kw == GeomEnd2) tokenLen = 38;
4988 int result = sscanf(&(LineText[tokenLen]), "%d IS %lf", &geom, &(lFrame->Energy));
4989 if (result != 2)
4990 wxLogMessage(_("Error parsing final energy for a geometry. Attempting to continue."));
4991 sprintf(LineText, "Completed parsing geometry %d", geom);
4992 ProgressInd->ChangeText(LineText);
4993 state = 0;
4994 }
4995 break;
4996 case OptGeometry: // Final optimized coordinates, parse and overwrite previous set
4997 if (state == 1) {
4998 if (!Buffer->LocateKeyWord("COORDINATES OF ALL ATOMS", 24)) break;
4999 Buffer->SkipnLines(3);
5000
5001 ParseGLogLine(Buffer, lFrame, NumAtoms, 10, &(MainData->MaxSize));
5002
5003 if ((NumFragmentAtoms <= 0)&&(NumExpectedAtoms > MainData->cFrame->NumAtoms))
5004 NumFragmentAtoms = NumExpectedAtoms - MainData->cFrame->NumAtoms;
5005 if (NumFragmentAtoms > 0) {
5006 Buffer->BackupnLines(2);
5007 if (Buffer->LocateKeyWord("COORDINATES OF FRAGMENT MULTIPOLE CENTERS", 41)) {
5008 Buffer->SkipnLines(3);
5009 MainData->ReadFragmentCoordinates(Buffer, NumFragmentAtoms);
5010 }
5011 }
5012 if (Prefs->GetAutoBond())
5013 lFrame->SetBonds(Prefs, false, ProgressInd);
5014 } else Buffer->SkipnLines(1);
5015 break;
5016 case Orbitals: // Set of Orbitals
5017 //Attempt to read in orbitals for this geometry
5018 if (state == 1) {
5019 if (MainData->Basis) {
5020 try {
5021 //skip over the line to the start of the orbital blocks
5022 //There is always a blank line before the orbs, but there may a '---' divider line after the key line just found
5023 Buffer->SetFilePos(Buffer->FindBlankLine());
5024 Buffer->SkipnLines(1);
5025 ProgressInd->ChangeText("Reading eigenvectors");
5026 if (!ProgressInd->UpdateProgress(Buffer->PercentRead()))
5027 { throw UserCancel();}
5028 lFrame->ParseGAMESSEigenVectors(Buffer, MainData->GetNumBasisFunctions(),
5029 MainData->GetNumBasisFunctions(), NumBetaUHFOrbs, NumOccAlpha, NumOccBeta,
5030 (TypeOfWavefunction)(MainData->InputOptions->Control->GetSCFType()), ProgressInd);
5031 }
5032 catch (std::bad_alloc) {
5033 MessageAlert("Insufficient memory to read in eigenvectors.");
5034 }
5035 catch (MemoryError) {
5036 MessageAlert("Insufficient memory to read in eigenvectors.");
5037 }
5038 catch (DataError) {
5039 MessageAlert("Error reading eigenvectors, orbitals skipped.");
5040 }
5041 }
5042 } else Buffer->SkipnLines(1);
5043 break;
5044 case FailedOpt: //optimization failed.
5045 if (state == 1) {
5046 sprintf(LineText, "Geometry optimization incomplete for frame %ld", MainData->GetNumFrames()-1);
5047 MessageAlert(LineText);
5048
5049 if (Buffer->LocateKeyWord("COORDINATES OF ALL ATOMS ARE (ANGS)", 35)) {
5050 Buffer->SkipnLines(3);
5051 ParseGLogLine(Buffer, lFrame, NumAtoms, 10, &(MainData->MaxSize));
5052
5053 if ((NumFragmentAtoms <= 0)&&(NumExpectedAtoms > MainData->cFrame->NumAtoms))
5054 NumFragmentAtoms = NumExpectedAtoms - MainData->cFrame->NumAtoms;
5055 if (NumFragmentAtoms > 0) {
5056 Buffer->BackupnLines(2);
5057 if (Buffer->LocateKeyWord("COORDINATES OF FRAGMENT MULTIPOLE CENTERS", 41)) {
5058 Buffer->SkipnLines(3);
5059 MainData->ReadFragmentCoordinates(Buffer, NumFragmentAtoms);
5060 }
5061 }
5062 if (Prefs->GetAutoBond())
5063 lFrame->SetBonds(Prefs, false, ProgressInd);
5064 }
5065 } else Buffer->SkipnLines(1);
5066 break;
5067 }
5068 } else break;
5069 }
5070 if (state == 1) MainData->DeleteFrame(); //started a frame without finding the end.
5071 MainData->SetCurrentFrame(1);
5072 MainData->DeleteFrame(); //Delete the initial frame that has only starting geometry
5073 return 1;
5074 } /*OpenGAMESSGlobOpLog*/
5075
5076 /**
5077 Output the coordinates in gamess input format ($DATA and $EFRAG group).
5078 If AllFrames then a series of $DATA groups will be output for the user to divide as needed.
5079 @param Buffer A buffer to write the text to.
5080 @param AllFrames Should the data for all frames be included or just the current frame?
5081 */
ExportGAMESS(BufferFile * Buffer,bool AllFrames)5082 void MolDisplayWin::ExportGAMESS(BufferFile * Buffer, bool AllFrames) {
5083 //Utilize the data group class to do all the real work
5084 InputData * lInputOptions = MainData->GetInputData();
5085 long basisTest = 1;
5086 if (lInputOptions->Basis) {
5087 if (lInputOptions->Basis->GetBasis() != 0) basisTest = 0;
5088 }
5089 if (!AllFrames) {
5090 lInputOptions->Data->WriteToFile(Buffer, MainData, Prefs, basisTest);
5091 } else {
5092 long savedFrame = MainData->GetCurrentFrame();
5093 MainData->CurrentFrame = 1;
5094 MainData->cFrame = MainData->Frames;
5095 for (int iframe=0; iframe<MainData->GetNumFrames(); ++iframe) {
5096 char text[kMaxLineLength];
5097 sprintf(text, "! Frame # %d", iframe+1);
5098 Buffer->WriteLine(text, true);
5099
5100 MainData->SetCurrentFrame(iframe);
5101
5102 lInputOptions->Data->WriteToFile(Buffer, MainData, Prefs, basisTest);
5103 }
5104
5105 MainData->SetCurrentFrame(savedFrame);
5106
5107 if ((lInputOptions->Data->GetCoordType() == ZMTCoordType)||
5108 (lInputOptions->Data->GetCoordType() == ZMTMPCCoordType)) {
5109 //If we are using internals update their values after restoring the frame
5110 Internals * IntCoords = MainData->GetInternalCoordinates();
5111 MOPacInternals * mInts = NULL;
5112 if (IntCoords)
5113 mInts = IntCoords->GetMOPacStyle();
5114 if (mInts) {
5115 mInts->CartesiansToInternals(MainData);
5116 }
5117 }
5118 }
5119 }
WriteTabbedEnergies(BufferFile * Buffer,bool AllFrames)5120 void MolDisplayWin::WriteTabbedEnergies(BufferFile * Buffer, bool AllFrames) {
5121 char text[kMaxLineLength];
5122 long a1, a2, a3;
5123
5124 EnergyOptions * lEOpts = Prefs->GetEnergyOptions();
5125 GraphOptions * lPOpts = Prefs->GetGraphOptions();
5126 bool PlotTE = lEOpts->PlotEnergy();
5127 bool PlotMPE = lEOpts->PlotMPEnergy();
5128 bool PlotKE = lEOpts->PlotKEnergy();
5129 bool PlotPE = lEOpts->PlotPEnergy();
5130
5131 Buffer->PutText("X Pos");
5132 if (PlotTE) Buffer->PutText("\tEnergy");
5133 if (PlotMPE) Buffer->PutText("\tMP2 Energy");
5134 if (PlotKE) Buffer->PutText("\tKinetic Energy");
5135 if (PlotPE) Buffer->PutText("\tPotential Energy");
5136 if (lPOpts->PlotRMSGradient()) Buffer->PutText("\tRMS Gradient");
5137 if (lPOpts->PlotMaxGradient()) Buffer->PutText("\tMax Gradient");
5138 if (lPOpts->PlotBondLength()) {
5139 a1 = lPOpts->Get1stAtom();
5140 a2 = lPOpts->Get2ndAtom();
5141 sprintf(text, "\tBond %ld-%ld", a1+1, a2+1);
5142 Buffer->PutText(text);
5143 }
5144 if (lPOpts->PlotBondAngle()) {
5145 a1 = lPOpts->Get1stAtom();
5146 a2 = lPOpts->Get2ndAtom();
5147 a3 = lPOpts->Get3rdAtom();
5148 sprintf(text, "\tAngle %ld-%ld-%ld", a1+1, a2+1, a3+1);
5149 Buffer->PutText(text);
5150 }
5151 Buffer->WriteLine("", true);
5152
5153 Frame * lFrame = MainData->Frames;
5154 float UnitFactor = 1.0f;
5155 if (lEOpts->GetDisplayUnits() == kKCalPerMole) UnitFactor = kHartreeTokCalPMol;
5156 long NumFrames = MainData->NumFrames;
5157 if (!AllFrames) {
5158 lFrame = MainData->cFrame;
5159 NumFrames = 1;
5160 }
5161 for (long i=0; i<NumFrames; ++i) {
5162 sprintf(text, "%f", lFrame->time);
5163 Buffer->PutText(text);
5164 if (PlotTE) {
5165 sprintf(text, "\t%f", (lFrame->Energy-lEOpts->GetY1Zero())*UnitFactor);
5166 Buffer->PutText(text);
5167 }
5168 if (PlotMPE) {
5169 sprintf(text, "\t%f", (lFrame->GetMP2Energy()-lEOpts->GetY1Zero())*UnitFactor);
5170 Buffer->PutText(text);
5171 }
5172 if (PlotKE) {
5173 sprintf(text, "\t%f", (lFrame->GetKineticEnergy()-lEOpts->GetY2Zero())*UnitFactor);
5174 Buffer->PutText(text);
5175 }
5176 if (PlotPE) {
5177 sprintf(text, "\t%f", (lFrame->Energy - lFrame->GetKineticEnergy() - lEOpts->GetY1Zero())*UnitFactor);
5178 Buffer->PutText(text);
5179 }
5180 if (lPOpts->PlotRMSGradient()) {
5181 sprintf(text, "\t%f", (lFrame->GetRMSGradient() - lEOpts->GetY2Zero()));
5182 Buffer->PutText(text);
5183 }
5184 if (lPOpts->PlotMaxGradient()) {
5185 sprintf(text, "\t%f", (lFrame->GetMaxGradient() - lEOpts->GetY2Zero()));
5186 Buffer->PutText(text);
5187 }
5188 if (lPOpts->PlotBondLength()) {
5189 float bLength;
5190 if (lFrame->GetBondLength(a1, a2, &bLength)) {
5191 sprintf(text, "\t%f", (bLength - lEOpts->GetY2Zero()));
5192 Buffer->PutText(text);
5193 } Buffer->PutText("\t");
5194 }
5195 if (lPOpts->PlotBondAngle()) {
5196 float bAngle;
5197 if (lFrame->GetBondAngle(a1, a2, a3, &bAngle)) {
5198 sprintf(text, "\t%f", (bAngle - lEOpts->GetY2Zero()));
5199 Buffer->PutText(text);
5200 } Buffer->PutText("\t");
5201 }
5202 Buffer->WriteLine("", true);
5203
5204 lFrame = lFrame->NextFrame;
5205 if (!lFrame) break;
5206 }
5207 }
WriteFrequencies(BufferFile * Buffer)5208 void MolDisplayWin::WriteFrequencies(BufferFile * Buffer) {
5209 char text[kMaxLineLength];
5210 Frame * lFrame;
5211 lFrame = MainData->cFrame;
5212
5213 if (!lFrame->Vibs) return;
5214
5215 bool haveInten = (lFrame->Vibs->Intensities.size() > 0);
5216 bool haveRaman = (lFrame->Vibs->RamanIntensity.size() > 0);
5217
5218 Buffer->PutText("Frequency\tIntensity");
5219 if (haveRaman) Buffer->PutText("\tRaman Intensity");
5220 Buffer->WriteLine("", true);
5221 for (long i=0; i<lFrame->Vibs->GetNumModes(); ++i) {
5222 sprintf(text, "%s", lFrame->Vibs->Frequencies[i].c_str());
5223 Buffer->PutText(text);
5224 if (haveInten) {
5225 sprintf(text, "\t%f", lFrame->Vibs->GetIntensity(i));
5226 Buffer->PutText(text);
5227 }
5228 if (haveRaman) {
5229 sprintf(text, "\t%f", lFrame->Vibs->GetRamanIntensity(i));
5230 Buffer->PutText(text);
5231 }
5232 Buffer->WriteLine("", true);
5233 }
5234 }
WriteXYZFile(BufferFile * Buffer,bool AllFrames,bool AllModes,bool AnimateMode)5235 void MolDisplayWin::WriteXYZFile(BufferFile * Buffer, bool AllFrames, bool AllModes,
5236 bool AnimateMode) {
5237 char text[kMaxLineLength];
5238
5239 Frame * lFrame;
5240 lFrame = MainData->Frames;
5241 long NumFrames = MainData->NumFrames;
5242 if (!AllFrames) {
5243 lFrame = MainData->cFrame;
5244 NumFrames = 1;
5245 }
5246
5247 if (AnimateMode) { //One geometry with all normal modes
5248 if (!lFrame->Vibs) return;
5249 mpAtom * lAtoms = lFrame->Atoms;
5250 long i, iatm;
5251 long cmode = (lFrame->NumAtoms)*(lFrame->Vibs->CurrentMode);
5252 CPoint3D * ModeOffset = new CPoint3D[lFrame->NumAtoms];
5253 CPoint3D * tempAtoms = new CPoint3D[lFrame->NumAtoms];
5254 if (!ModeOffset || !tempAtoms) return;
5255 float VectorScale = Prefs->GetVectorScale();
5256 float offsetFactor = 1.0/40.0;
5257 for (iatm=0; iatm<(lFrame->NumAtoms); ++iatm) {
5258 tempAtoms[iatm] = lAtoms[iatm].Position;
5259 ModeOffset[iatm] = lFrame->Vibs->NormMode[iatm+cmode];
5260 ModeOffset[iatm] *= VectorScale;
5261 }
5262 for (i=0; i<20; ++i) {
5263 if ((i==5)||(i==15)) {
5264 offsetFactor *= -1.0f;
5265 }
5266 for (iatm=0; iatm<(lFrame->NumAtoms); ++iatm) {
5267 tempAtoms[iatm].x += offsetFactor*(ModeOffset[iatm].x);
5268 tempAtoms[iatm].y += offsetFactor*(ModeOffset[iatm].y);
5269 tempAtoms[iatm].z += offsetFactor*(ModeOffset[iatm].z);
5270 } //Now punch out the XYZ frame
5271 sprintf(text, "%ld", lFrame->NumAtoms);
5272 Buffer->WriteLine(text, true);
5273 sprintf(text, "Frequency %s Frame %ld",
5274 lFrame->Vibs->Frequencies[lFrame->Vibs->CurrentMode].c_str(), i+1);
5275 Buffer->WriteLine(text, true);
5276 for (long j=0; j<lFrame->NumAtoms; ++j) {
5277 Str255 Label;
5278 Prefs->GetAtomLabel(lAtoms[j].Type-1, Label);
5279 Label[Label[0]+1]=0;
5280 sprintf(text, "%s %.4f %.4f %.4f", &(Label[1]), tempAtoms[j].x,
5281 tempAtoms[j].y, tempAtoms[j].z);
5282 Buffer->PutText(text);
5283 CPoint3D * lMode = &(lFrame->Vibs->NormMode[(j + cmode)]);
5284 sprintf(text," %.4f %.4f %.4f", lMode->x, lMode->y, lMode->z);
5285 Buffer->WriteLine(text, true);
5286 }
5287 }
5288 delete [] tempAtoms;
5289 delete [] ModeOffset;
5290 } else if (AllModes) {
5291 if (!lFrame->Vibs) return;
5292 mpAtom * lAtoms = lFrame->Atoms;
5293 for (long i=0; i<lFrame->Vibs->GetNumModes(); ++i) {
5294 sprintf(text, "%ld", lFrame->NumAtoms);
5295 Buffer->WriteLine(text, true);
5296 sprintf(text, "Frequency %s",
5297 lFrame->Vibs->Frequencies[i].c_str());
5298 Buffer->WriteLine(text, true);
5299 for (long j=0; j<lFrame->NumAtoms; ++j) {
5300 Str255 Label;
5301 Prefs->GetAtomLabel(lAtoms[j].Type-1, Label);
5302 Label[Label[0]+1]=0;
5303 sprintf(text, "%s %.4f %.4f %.4f", &(Label[1]), lAtoms[j].Position.x,
5304 lAtoms[j].Position.y, lAtoms[j].Position.z);
5305 Buffer->PutText(text);
5306 long cmode = (lFrame->NumAtoms)*i;
5307 CPoint3D * lMode = &(lFrame->Vibs->NormMode[(j + cmode)]);
5308 sprintf(text," %.4f %.4f %.4f", lMode->x, lMode->y, lMode->z);
5309 Buffer->WriteLine(text, true);
5310 }
5311 }
5312 } else {
5313 for (long i=0; i<NumFrames; ++i) {
5314 mpAtom * lAtoms = lFrame->Atoms;
5315 sprintf(text, "%ld", lFrame->NumAtoms);
5316 Buffer->WriteLine(text, true);
5317 sprintf(text, "Frame %ld", i+1);
5318 Buffer->WriteLine(text, true);
5319 for (long j=0; j<lFrame->NumAtoms; ++j) {
5320 Str255 Label;
5321 Prefs->GetAtomLabel(lAtoms[j].GetType()-1, Label);
5322 Label[Label[0]+1]=0;
5323 sprintf(text, "%s %.4f %.4f %.4f", &(Label[1]), lAtoms[j].Position.x,
5324 lAtoms[j].Position.y, lAtoms[j].Position.z);
5325 Buffer->PutText(text);
5326 if (lFrame->Vibs) { //There are normal modes with this frame so setup drawing parameters
5327 if (MainData->GetDrawMode()) { //Are we supposed to show the normal mode?
5328 long cmode = (lFrame->NumAtoms)*(lFrame->Vibs->CurrentMode);
5329 CPoint3D * lMode = &(lFrame->Vibs->NormMode[(j + cmode)]);
5330 sprintf(text," %.4f %.4f %.4f", lMode->x, lMode->y, lMode->z);
5331 Buffer->PutText(text);
5332 }
5333 }
5334 Buffer->WriteLine("", true);
5335 }
5336 lFrame = lFrame->NextFrame;
5337 if (!lFrame) break;
5338 }
5339 }
5340 }
WriteMDLMolFile(BufferFile * Buffer)5341 void MolDisplayWin::WriteMDLMolFile(BufferFile * Buffer) {
5342 char Line[kMaxLineLength];
5343 Frame * lFrame = MainData->GetCurrentFramePtr();
5344 //The first line is the molecule name so copy out the current description
5345 if (MainData->Description)
5346 Buffer->PutText(MainData->Description);
5347 else if (MainData->InputOptions) {
5348 const char * temp = MainData->InputOptions->Data->GetTitle();
5349 if (temp) {
5350 Buffer->PutText(temp);
5351 }
5352 }
5353 Buffer->WriteLine("", true);
5354 //2nd line may contain various program data
5355 Buffer->PutText(" MacMolPlt ");
5356 if (lFrame->Energy != 0.0) {
5357 sprintf(Line, "%12.5f", lFrame->Energy);
5358 Buffer->PutText(Line);
5359 }
5360 Buffer->WriteLine("", true); //finish off 2nd line and leave 3rd line blank
5361 Buffer->WriteLine("", true);
5362 sprintf(Line, "%3ld%3ld 0 0 0 0 0 0 0 0 0 v2000",
5363 lFrame->GetNumAtoms(), lFrame->GetNumBonds());
5364 Buffer->WriteLine(Line, true);
5365 mpAtom * lAtoms = lFrame->Atoms;
5366 long i;
5367 for (i=0; i<lFrame->GetNumAtoms(); ++i) {
5368 Str255 Label;
5369 Prefs->GetAtomLabel(lAtoms[i].GetType()-1, Label);
5370 Label[Label[0]+1]=0;
5371 sprintf(Line, "%10.4f%10.4f%10.4f %-3s 0 0 0 0 0 0 0 0 0 0 0 0",
5372 lAtoms[i].Position.x, lAtoms[i].Position.y,
5373 lAtoms[i].Position.z, &(Label[1]));
5374 Buffer->WriteLine(Line, true);
5375 }
5376 if (lFrame->GetNumBonds() > 0) {
5377 Bond * lBonds = lFrame->Bonds;
5378 for (i=0; i<lFrame->GetNumBonds(); ++i) {
5379 int type = lBonds[i].Order;
5380 if (type>3 || type<=0) type = 1;
5381 sprintf(Line, "%3ld%3ld%3d 0 0 0 0", lBonds[i].Atom1+1,
5382 lBonds[i].Atom2+1, type);
5383 Buffer->WriteLine(Line, true);
5384 }
5385 }
5386 //Final line needs to be end line to terminate properties block
5387 Buffer->WriteLine("M END", true);
5388 }
5389
WriteVRMLFile(BufferFile * Buffer)5390 void MolDisplayWin::WriteVRMLFile(BufferFile * Buffer) {
5391 Buffer->PutText("#VRML V2.0 utf8\n"); //VRML header
5392 Buffer->PutText("\n");
5393
5394 Frame * lFrame = MainData->GetCurrentFramePtr();
5395 mpAtom * lAtoms = lFrame->Atoms;
5396
5397 //drawing atoms
5398
5399 long NumAtoms = lFrame->NumAtoms;
5400 float AtomScale = Prefs->GetAtomScale();
5401 long curAtomType;
5402 RGBColor * AtomColor;
5403 wxString tmpStr;
5404 float red, green, blue;
5405
5406 for (long iatom=0; iatom<NumAtoms; ++iatom) {
5407 if (lAtoms[iatom].GetInvisibility()) continue;
5408
5409 curAtomType = lAtoms[iatom].GetType() - 1;
5410 AtomColor = Prefs->GetAtomColorLoc(curAtomType);
5411 red = AtomColor->red/65536.0;
5412 green = AtomColor->green/65536.0;
5413 blue = AtomColor->blue/65536.0;
5414
5415 float radius = AtomScale*Prefs->GetAtomSize(curAtomType);
5416 Buffer->PutText("Transform {\n");
5417 tmpStr.Printf(wxT("\ttranslation %f %f %f\n"), lAtoms[iatom].Position.x,
5418 lAtoms[iatom].Position.y, lAtoms[iatom].Position.z);
5419 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5420 Buffer->PutText("\tchildren [\n");
5421 Buffer->PutText("\t\tShape {\n");
5422 tmpStr.Printf(wxT("\t\t\tgeometry Sphere { radius %f }\n"), radius);
5423 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5424 Buffer->PutText("\t\t\tappearance Appearance {\n");
5425 tmpStr.Printf(wxT("\t\t\t\tmaterial Material { diffuseColor %f %f %f }\n"),
5426 red, green, blue);
5427 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5428 Buffer->PutText("\t\t\t}\n");
5429 Buffer->PutText("\t\t}\n");
5430 Buffer->PutText("\t]\n");
5431 Buffer->PutText("}\n");
5432 }
5433
5434 //drawing bonds
5435 Bond * lBonds = lFrame->Bonds;
5436 long NumBonds = lFrame->NumBonds;
5437 double BondSize = Prefs->GetQD3DBondWidth();
5438 //float dotProd;
5439 Matrix4D rotMat;
5440 CPoint3D NormalOffset, NormStart = CPoint3D(0.0f, 1.0f, 0.0f);
5441 double theta;
5442 double axisX, axisY, axisZ;
5443
5444 for (long ibond=0; ibond<NumBonds; ++ibond) {
5445 CPoint3D v1, v2, offset;
5446 long atom1 = lBonds[ibond].Atom1;
5447 long atom2 = lBonds[ibond].Atom2;
5448 //BondOrder tmpOrder = lBonds[ibond].Order;
5449
5450 //for (int ipipe = 0; ipipe < MAX(tmpOrder,1); ++ipipe) {
5451
5452 v1.x = lAtoms[atom1].Position.x; // + offset_vec.x * baseBondOffset +
5453 //3.5 * tmpBondSize * offset_vec.x * ipipe;
5454 v1.y = lAtoms[atom1].Position.y; //+ offset_vec.y * baseBondOffset +
5455 //3.5 * tmpBondSize * offset_vec.y * ipipe;
5456 v1.z = lAtoms[atom1].Position.z; //+ offset_vec.z * baseBondOffset +
5457 //3.5 * tmpBondSize * offset_vec.z * ipipe;
5458 v2.x = lAtoms[atom2].Position.x; //+ offset_vec.x * baseBondOffset +
5459 //3.5 * tmpBondSize * offset_vec.x * ipipe;
5460 v2.y = lAtoms[atom2].Position.y; //+ offset_vec.y * baseBondOffset +
5461 //3.5 * tmpBondSize * offset_vec.y * ipipe;
5462 v2.z = lAtoms[atom2].Position.z; //+ offset_vec.z * baseBondOffset +
5463 //3.5 * tmpBondSize * offset_vec.z * ipipe;
5464
5465 offset.x = v2.x - v1.x;
5466 offset.y = v2.y - v1.y;
5467 offset.z = v2.z - v1.z;
5468
5469 double length = offset.Magnitude();
5470 double radius1 = AtomScale*Prefs->GetAtomSize(lAtoms[atom1].GetType() - 1);
5471 double radius2 = AtomScale*Prefs->GetAtomSize(lAtoms[atom2].GetType() - 1);
5472 double percent1 = radius1/length;
5473 double percent2 = radius2/length;
5474 double centerPercent = 0.5 + 0.5*(percent1-percent2);
5475
5476 if (length>0.00001) {
5477 NormalOffset.x = offset.x/length;
5478 NormalOffset.y = offset.y/length;
5479 NormalOffset.z = offset.z/length;
5480 } else {
5481 NormalOffset.x=NormalOffset.y=NormalOffset.z=0.0f;
5482 }
5483
5484 SetRotationMatrix(rotMat, &NormStart, &NormalOffset);
5485
5486 double tmp1 = rotMat[2][1]-rotMat[1][2];
5487 double tmp2 = rotMat[0][2]-rotMat[2][0];
5488 double tmp3 = rotMat[1][0]-rotMat[0][1];
5489 double dev = sqrt(tmp1*tmp1+tmp2*tmp2+tmp3*tmp3);
5490 theta = -1 * acos((rotMat[0][0] + rotMat[1][1] + rotMat[2][2] - 1)/2);
5491
5492 if (fabs(dev) > 0.0000001 ) {
5493 axisX = (rotMat[2][1] - rotMat[1][2]) / dev;
5494 axisY = (rotMat[0][2] - rotMat[2][0]) / dev;
5495 axisZ = (rotMat[1][0] - rotMat[0][1]) / dev;
5496 }
5497
5498 CPoint3D v3; //first half bond from atom 1
5499 v3.x = centerPercent*(v2.x - v1.x)+v1.x;
5500 v3.y = centerPercent*(v2.y - v1.y)+v1.y;
5501 v3.z = centerPercent*(v2.z - v1.z)+v1.z;
5502
5503 curAtomType = lAtoms[atom1].GetType() - 1;
5504 AtomColor = Prefs->GetAtomColorLoc(curAtomType);
5505 red = AtomColor->red/65536.0;
5506 green = AtomColor->green/65536.0;
5507 blue = AtomColor->blue/65536.0;
5508
5509 Buffer->PutText("Transform {\n");
5510
5511 if (fabs(dev) > 0.000001) {
5512 tmpStr.Printf(wxT("\trotation %lf %lf %lf %lf\n"), axisX, axisY, axisZ, theta);
5513 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5514 }
5515 tmpStr.Printf(wxT("\ttranslation %lf %lf %lf\n"), (v1.x+v3.x)/2, (v1.y+v3.y)/2, (v1.z+v3.z)/2);
5516 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5517 Buffer->PutText("\tchildren [\n");
5518 Buffer->PutText("\t\tShape {\n");
5519 tmpStr.Printf(wxT("\t\t\tgeometry Cylinder { radius %lf height %lf}\n"), BondSize, (centerPercent)*length);
5520 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5521 Buffer->PutText("\t\t\tappearance Appearance {\n");
5522 tmpStr.Printf(wxT("\t\t\t\tmaterial Material { diffuseColor %f %f %f }\n"),
5523 red, green, blue);
5524 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5525 Buffer->PutText("\t\t\t}\n");
5526 Buffer->PutText("\t\t}\n");
5527 Buffer->PutText("\t]\n");
5528 Buffer->PutText("}\n");
5529
5530 curAtomType = lAtoms[atom2].GetType() - 1;
5531 AtomColor = Prefs->GetAtomColorLoc(curAtomType);
5532 red = AtomColor->red/65536.0;
5533 green = AtomColor->green/65536.0;
5534 blue = AtomColor->blue/65536.0;
5535
5536 Buffer->PutText("Transform {\n");
5537
5538 if (fabs(dev) > 0.000001) {
5539 tmpStr.Printf(wxT("\trotation %lf %lf %lf %lf\n"), axisX, axisY, axisZ, theta);
5540 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5541 }
5542 tmpStr.Printf(wxT("\ttranslation %lf %lf %lf\n"), (v2.x+v3.x)/2, (v2.y+v3.y)/2, (v2.z+v3.z)/2);
5543 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5544 Buffer->PutText("\tchildren [\n");
5545 Buffer->PutText("\t\tShape {\n");
5546 tmpStr.Printf(wxT("\t\t\tgeometry Cylinder { radius %lf height %lf}\n"), BondSize, (1-centerPercent)*length);
5547 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5548 Buffer->PutText("\t\t\tappearance Appearance {\n");
5549 tmpStr.Printf(wxT("\t\t\t\tmaterial Material { diffuseColor %f %f %f }\n"),
5550 red, green, blue);
5551 Buffer->PutText(tmpStr.mb_str(wxConvUTF8));
5552 Buffer->PutText("\t\t\t}\n");
5553 Buffer->PutText("\t\t}\n");
5554 Buffer->PutText("\t]\n");
5555 Buffer->PutText("}\n");
5556 }
5557 }
5558
WritePOVFile(BufferFile * Buffer)5559 void MolDisplayWin::WritePOVFile(BufferFile *Buffer) {
5560
5561 MainData->ExportPOV(Buffer, Prefs);
5562
5563 }
5564
ReadGrid(const bool Square,const bool UseMult,const double & MultValue)5565 void General2DSurface::ReadGrid(const bool Square, const bool UseMult, const double & MultValue) {
5566 wxString filename = wxFileSelector(wxT("Choose a file containing the surface data."));
5567 //We are looking for $ VEC groups. Scan to see how many are there. If more than 1 the user will
5568 //have to choose.
5569 FILE * myfile = NULL;
5570 if (!filename.empty()) {
5571 myfile = fopen(filename.mb_str(wxConvUTF8), "rb");
5572 if (myfile == NULL) {
5573 MessageAlert("Unable to open the selected file!");
5574 return;
5575 }
5576 } else
5577 return;
5578 bool FirstFile = (Grid == NULL);
5579
5580 //Ok got a file, create a buffer for it and then attempt to read it in
5581 if (FirstFile) {
5582 if (Label) {delete [] Label; Label = NULL;}
5583 FreeGrid();
5584 }
5585
5586 BufferFile * Buffer = NULL;
5587
5588 bool success = false;
5589 long LineLength, LinePos;
5590 short scanerr;
5591 CPoint3D tempPt;
5592 try {
5593 char Line[kMaxLineLength];
5594 Buffer = new BufferFile(myfile, false);
5595 Buffer->GetLine(Line);
5596 if (FirstFile) SetLabel(Line);
5597 Buffer->GetLine(Line);
5598 scanerr = sscanf(Line, "%ld", &LinePos);
5599 if ((scanerr != 1)||(LinePos<=0)) {
5600 wxLogMessage(_("The second line must contain the # of grid points."));
5601 throw DataError();
5602 }
5603 if (FirstFile) NumGridPoints = LinePos;
5604 else if (LinePos != NumGridPoints) {
5605 wxLogMessage(_("The number of grid points does not match the existing grid!"));
5606 throw DataError();
5607 }
5608 Buffer->GetLine(Line);
5609 scanerr = sscanf(Line, "%f%f%f", &(tempPt.x), &(tempPt.y), &(tempPt.z));
5610 if (scanerr != 3) {
5611 wxLogMessage(_("Could not parse the x, y, and z values for the origin of the 3D grid."));
5612 throw DataError();
5613 }
5614 if (FirstFile) Origin = tempPt;
5615 else if ((fabs(tempPt.x) < fabs(100*(tempPt.x-Origin.x)))||
5616 (fabs(tempPt.y) < fabs(100*(tempPt.y-Origin.y)))||
5617 (fabs(tempPt.z) < fabs(100*(tempPt.z-Origin.z)))) {
5618 wxLogMessage(_("The origin of the file grid does not match the current origin!"));
5619 throw DataError();
5620 }
5621 Buffer->GetLine(Line);
5622 scanerr = sscanf(Line, "%f%f%f", &(tempPt.x), &(tempPt.y), &(tempPt.z));
5623 if (scanerr != 3) {
5624 wxLogMessage(_("The fourth line must contain a 3D vector indicating the increment along the first side of the grid."));
5625 throw DataError();
5626 }
5627 if (FirstFile) XInc = tempPt;
5628 else if ((fabs(tempPt.x) < fabs(100*(tempPt.x-XInc.x)))||
5629 (fabs(tempPt.y) < fabs(100*(tempPt.y-XInc.y)))||
5630 (fabs(tempPt.z) < fabs(100*(tempPt.z-XInc.z)))) {
5631 wxLogMessage(_("The first increment vector does not match the current grid!"));
5632 throw DataError();
5633 }
5634 Buffer->GetLine(Line);
5635 scanerr = sscanf(Line, "%f%f%f", &(tempPt.x), &(tempPt.y), &(tempPt.z));
5636 if (scanerr != 3) {
5637 wxLogMessage(_("The fifth line must contain a 3D vector indicating the increment along the second grid direction."));
5638 throw DataError();
5639 }
5640 if (FirstFile) YInc = tempPt;
5641 else if ((fabs(tempPt.x) < fabs(100*(tempPt.x-YInc.x)))||
5642 (fabs(tempPt.y) < fabs(100*(tempPt.y-YInc.y)))||
5643 (fabs(tempPt.z) < fabs(100*(tempPt.z-YInc.z)))) {
5644 wxLogMessage(_("The second increment vector does not match the current grid!"));
5645 throw DataError();
5646 }
5647 //allocate memory for the grid
5648 long TotalPoints = NumGridPoints*NumGridPoints;
5649 if (FirstFile) {
5650 AllocateGrid(TotalPoints);
5651 }
5652 if (!Grid) throw MemoryError();
5653 float * lGrid;
5654 lGrid = Grid;
5655 if (FirstFile) for (LinePos=0; LinePos<TotalPoints; ++LinePos)
5656 lGrid[LinePos] = 0.0;
5657 Buffer->GetLine(Line);
5658 LinePos = 0;
5659 LineLength = strlen(Line);
5660 long n=0;
5661 float tempF;
5662 GridMax = -1.0e20; //init the Grid max to a value sure to be changed later
5663 GridMin = 1.0e20;
5664 while (n<TotalPoints) {
5665 if (LinePos>=LineLength) {
5666 Buffer->GetLine(Line);
5667 LinePos = 0;
5668 LineLength = strlen(Line);
5669 }
5670 int nchar;
5671 scanerr = sscanf(&(Line[LinePos]), "%f%n", &tempF, &nchar);
5672 if (scanerr != 1) {
5673 Buffer->GetLine(Line);
5674 LinePos = 0;
5675 LineLength = strlen(Line);
5676 scanerr = sscanf(&(Line[LinePos]), "%f%n", &tempF, &nchar);
5677 }
5678 if (Square) tempF *= tempF;
5679 if (UseMult) tempF *= MultValue;
5680 lGrid[n] += tempF;
5681 GridMax = MAX(GridMax, lGrid[n]);
5682 GridMin = MIN(GridMin, lGrid[n]);
5683 LinePos += nchar;
5684 ++n;
5685 }
5686
5687 success = true;
5688 }
5689 catch (DataError /*Error*/) {}
5690 catch (FileError Error) { Error.WriteError();}
5691 catch (...) {
5692 success = false;
5693 }
5694 if (!success && FirstFile) { //invalid data or out of memory, etc
5695 if (Label) {delete [] Label; Label = NULL;}
5696 FreeGrid();
5697 }
5698 if (Buffer) delete Buffer;
5699 fclose(myfile);
5700 }
ReadGrid(const bool Square,const bool UseValue,const double & MultValue)5701 void General3DSurface::ReadGrid(const bool Square, const bool UseValue, const double & MultValue) {
5702 //First prompt the user for the file
5703 wxString filename = wxFileSelector(wxT("Choose a file containing the surface data."));
5704 FILE * myfile = NULL;
5705 if (!filename.empty()) {
5706 myfile = fopen(filename.mb_str(wxConvUTF8), "rb");
5707 if (myfile == NULL) {
5708 MessageAlert("Unable to open the selected file!");
5709 return;
5710 }
5711 } else
5712 return;
5713
5714 bool FirstFile = (Grid == NULL);
5715
5716 //Ok got a file, create a buffer for it and then attempt to read it in
5717 if (FirstFile) { //shouldn't have old data if the first file...
5718 if (Label) {delete [] Label; Label = NULL;}
5719 if (Grid) FreeGrid();
5720 if (ContourHndl) FreeContour();
5721 }
5722
5723 BufferFile * Buffer = NULL;
5724
5725 bool success = false;
5726 long LineLength, LinePos, tempL;
5727 CPoint3D tempPt;
5728 short scanerr;
5729 try {
5730 char Line[kMaxLineLength];
5731 Buffer = new BufferFile(myfile, false);
5732 Buffer->GetLine(Line);
5733 if (FirstFile) SetLabel(Line); //grab the label only if this is the first data file
5734
5735 Buffer->GetLine(Line);
5736 scanerr = sscanf(Line, "%ld%ld%ld", &LineLength, &LinePos, &tempL);
5737 if ((scanerr != 3)||(LineLength<=0)||(LinePos<=0)||(tempL<=0)) {
5738 wxLogMessage(_("The second line must contain the # of x, y, and z grid points."));
5739 throw DataError();
5740 }
5741 if (FirstFile) {
5742 NumXGridPoints = LineLength;
5743 NumYGridPoints = LinePos;
5744 NumZGridPoints = tempL;
5745 } else if ((NumXGridPoints!=LineLength)||(NumYGridPoints!=LinePos)||
5746 (NumZGridPoints!=tempL)) {
5747 wxLogMessage(_("The number of grid points does not match the existing grid!"));
5748 throw DataError();
5749 }
5750
5751 Buffer->GetLine(Line);
5752 scanerr = sscanf(Line, "%f%f%f", &(tempPt.x), &(tempPt.y), &(tempPt.z));
5753 if (scanerr != 3) {
5754 wxLogMessage(_("Could not parse the x, y, and z values for the origin of the 3D grid."));
5755 throw DataError();
5756 }
5757 if (FirstFile) Origin = tempPt;
5758 else if ((fabs(tempPt.x) < fabs(100*(tempPt.x-Origin.x)))||
5759 (fabs(tempPt.y) < fabs(100*(tempPt.y-Origin.y)))||
5760 (fabs(tempPt.z) < fabs(100*(tempPt.z-Origin.z)))) {
5761 wxLogMessage(_("The origin of the file grid does not match the current origin!"));
5762 throw DataError();
5763 }
5764
5765 Buffer->GetLine(Line);
5766 scanerr = sscanf(Line, "%f%f%f", &(tempPt.x), &(tempPt.y), &(tempPt.z));
5767 if (scanerr != 3) {
5768 wxLogMessage(_("Could not parse the x, y, and z increment values from the fourth line."));
5769 throw DataError();
5770 }
5771 if (FirstFile) {
5772 XGridInc = tempPt.x;
5773 YGridInc = tempPt.y;
5774 ZGridInc = tempPt.z;
5775 } else if ((fabs(tempPt.x) < fabs(100*(tempPt.x-XGridInc)))||
5776 (fabs(tempPt.y) < fabs(100*(tempPt.y-YGridInc)))||
5777 (fabs(tempPt.z) < fabs(100*(tempPt.z-ZGridInc)))) {
5778 wxLogMessage(_("The x, y, and z grid increments must match those of the existing grid."));
5779 throw DataError();
5780 }
5781 //allocate memory for the grid (if needed)
5782 long TotalPoints = NumXGridPoints*NumYGridPoints*NumZGridPoints;
5783 if (FirstFile) AllocateGrid(TotalPoints);
5784 if (!Grid) throw MemoryError();
5785 float * lGrid;
5786 lGrid = Grid;
5787 if (FirstFile) for (LinePos=0; LinePos<TotalPoints; ++LinePos)
5788 lGrid[LinePos] = 0.0;
5789 Buffer->GetLine(Line);
5790 LinePos = 0;
5791 LineLength = strlen(Line);
5792 long n=0;
5793 float tempF;
5794 GridMax = -1.0e20; //init the Grid max to a value sure to be changed later
5795 GridMin = 1.0e20;
5796 while (n<TotalPoints) {
5797 if (LinePos>=LineLength) {
5798 Buffer->GetLine(Line);
5799 LinePos = 0;
5800 LineLength = strlen(Line);
5801 }
5802 int nchar;
5803 scanerr = sscanf(&(Line[LinePos]), "%f%n", &tempF, &nchar);
5804 if (scanerr != 1) {
5805 Buffer->GetLine(Line);
5806 LinePos = 0;
5807 LineLength = strlen(Line);
5808 scanerr = sscanf(&(Line[LinePos]), "%f%n", &tempF, &nchar);
5809 }
5810 if (Square) tempF *= tempF;
5811 if (UseValue) tempF *= MultValue;
5812 lGrid[n] += tempF;
5813 GridMax = MAX(GridMax, lGrid[n]);
5814 GridMin = MIN(GridMin, lGrid[n]);
5815 LinePos += nchar;
5816 ++n;
5817 }
5818
5819 success = true;
5820 }
5821 catch (DataError /*Error*/) {}
5822 catch (FileError Error) { Error.WriteError();}
5823 catch (...) {
5824 success = false;
5825 }
5826 if (!success && FirstFile) { //invalid data or out of memory, etc
5827 if (Label) {delete [] Label; Label = NULL;}
5828 if (Grid) FreeGrid();
5829 }
5830 if (Buffer) delete Buffer;
5831 fclose(myfile);
5832 }
LocateKeyWord(const char * Buffer,const char * KeyWord,long length,long bytecount)5833 long LocateKeyWord(const char *Buffer, const char * KeyWord, long length, long bytecount)
5834 { long test=0, pos=-1;
5835
5836 while (!test) {
5837 for (pos++; ((toupper(Buffer[pos]) != toupper(KeyWord[0]))||
5838 (toupper(Buffer[pos+1]) != toupper(KeyWord[1])))&&(pos<bytecount)&&
5839 (Buffer[pos]!='\0'); pos++) ;
5840 if (pos>=bytecount) return -1;
5841 if (Buffer[pos]=='\0') return -1;
5842 test = 2;
5843 while ((toupper(Buffer[pos+test]) == toupper(KeyWord[test]))&&(test<length)&&
5844 ((pos+test)<bytecount)) test++;
5845 test = (long) test==length;
5846 }
5847 return pos;
5848 } /*LocateKeyWord*/
5849 /* ParseGLogLine converts the various cartesian coordinate formats in
5850 GAMESS output files to my internal binary coordinate array. Type's
5851 less than ten mean coordinates are in Bohr and thus need conversion,
5852 greater than ten means they are already in Angstroms. */
ParseGLogLine(BufferFile * Buffer,Frame * lFrame,long numExpected,long Type,float * maxsize)5853 long ParseGLogLine(BufferFile * Buffer, Frame * lFrame, long numExpected, long Type, float *maxsize)
5854 { long LinePos=0, iscanerr=0, iatm;
5855 float temp;
5856 char LineText[kMaxLineLength+1];
5857 CPoint3D Position;
5858
5859 for (iatm=0; iatm<numExpected; ++iatm) {
5860 Buffer->GetLine(LineText);
5861 switch (Type) {
5862 case 0: //Standard Coordinates at the top of the log file
5863 case 10: // IRC Log file format (same as above but in angstroms)
5864 //1/1998 changed standard log format to 10
5865 LinePos = 11; //Skip the name and space before the nuclear charge
5866 break;
5867 case 1: //format used during geometry optimizations
5868 LinePos = 15; //skip # and name before the nuclear charge
5869 break;
5870 case 2: //DRC irc and log file format, atom labels are missing
5871 LinePos = 1;
5872 break;
5873 default:
5874 LinePos = 0;
5875 }
5876 iscanerr = sscanf(&(LineText[LinePos]), "%f%f%f%f", &temp, &Position.x,
5877 &Position.y, &Position.z);
5878 if (iscanerr == 4) { /*Convert the coordinates to Angstroms*/
5879 if (Type < 10) {
5880 Position.x *= kBohr2AngConversion;
5881 Position.y *= kBohr2AngConversion;
5882 Position.z *= kBohr2AngConversion;
5883 }
5884 *maxsize = MAX(*maxsize, Position.x);
5885 *maxsize = MAX(*maxsize, Position.y);
5886 *maxsize = MAX(*maxsize, Position.z);
5887 if (temp == 0) temp = 115;
5888 lFrame->AddAtom((long) temp, Position);
5889 } else break;
5890 }
5891 return iatm;
5892 } /*ParseGLogLine*/
ParseCartLine(char * Line,long * atomtype,CPoint3D * coord,CPoint3D * offset,long Mode)5893 long ParseCartLine(char *Line, long *atomtype, CPoint3D *coord, CPoint3D *offset, long Mode)
5894 { long iscanerr=0, junk;
5895 unsigned char Label[kMaxLineLength]="\0";
5896
5897 if (!sscanf(Line, "%s", Label)) return -1;
5898 if ((Label[0] > 47)&&(Label[0] < 58)) { /*A number? must be Gaussian style (bleah)*/
5899 float arg6;
5900 iscanerr = sscanf(Line, "%ld%ld%f%f%f%f",&junk, atomtype, &(coord->x),
5901 &(coord->y), &(coord->z), &arg6);
5902 //G98 adds an integer column for the 'atomic type' which is normally 0???
5903 if (iscanerr == 6) {
5904 coord->x = coord->y;
5905 coord->y = coord->z;
5906 coord->z = arg6;
5907 }
5908 if ((*atomtype>130)||(*atomtype<1)) //bad atom type: assume whole line is garbage
5909 return -1;
5910 if ((iscanerr != 5)&&(iscanerr != 6)) return -iscanerr;
5911 } else {
5912 float tempx, tempy, tempz;
5913
5914 iscanerr = sscanf(Line, "%s%f%f%f%f%f%f", Label, &(coord->x),
5915 &(coord->y), &(coord->z), &tempx, &tempy, &tempz);
5916
5917 if (iscanerr == 7) {
5918 *atomtype = SetAtomType(Label);
5919 if (*atomtype == 116) {
5920 offset->x = tempx*kDebyeToAU; /*convert the units from Debye to AU for better viewing*/
5921 offset->y = tempy*kDebyeToAU;
5922 offset->z = tempz*kDebyeToAU;
5923 } else if (*atomtype == 117) {
5924 coord->x *= kBohr2AngConversion;
5925 coord->y *= kBohr2AngConversion;
5926 coord->z *= kBohr2AngConversion;
5927 offset->x = tempx*kDebyeToAU; /*convert the units from Debye to AU for better viewing*/
5928 offset->y = tempy*kDebyeToAU;
5929 offset->z = tempz*kDebyeToAU;
5930 *atomtype = 116;
5931 } else if (Mode==-1) { // Normal mode is not mass-weighted here!
5932 offset->x = tempx;
5933 offset->y = tempy;
5934 offset->z = tempz;
5935 }
5936 } else {
5937 if (iscanerr == 5) { /*looks like GAMESS unit=bohr format -- label Atomic_num x, y, z*/
5938 *atomtype = (long) coord->x;
5939 coord->x = coord->y;
5940 coord->y = coord->z;
5941 coord->z = tempx;
5942 } else if (iscanerr == 4) {
5943 //Check for Fragment coords - I "think" a fragment is ZLabel#
5944 if (Label[0] == 'Z' || Label[0] == 'z') {
5945 if ((Label[2]!=0)||((Label[1]!='R')&&(Label[1]!='r')&&
5946 (Label[1]!='N')&&(Label[1]!='n'))) {
5947 Label[0] = Label[1];
5948 Label[1] = 0;
5949 }
5950 }
5951 *atomtype = SetAtomType(Label);
5952 } else return iscanerr; //return the error code
5953 }
5954 }
5955 return iscanerr;
5956 } /*ParseCartLine*/
SetAtomType(const unsigned char * TestLabel)5957 long SetAtomType(const unsigned char *TestLabel) {
5958 char label[2];
5959 long result = -1;
5960
5961 label[0] = TestLabel[0]; label[1]=TestLabel[1];
5962 if ((label[0]>96)&&(label[0]<123)) label[0] = label[0] - 32; /* Make the first character upper case */
5963 if ((label[1]>64)&&(label[1]<91)) label[1] = label[1] + 32; /* and the second character lower case */
5964 if ((label[1]<'a')||(label[1]>'z')) label[1] = ' '; //Not a letter!
5965 switch (label[0]) {
5966 case 'H':
5967 switch (label[1]) {
5968 case 'e': /* Helium */
5969 result = 2;
5970 break;
5971 case 'o': /* Holmium */
5972 result = 67;
5973 break;
5974 case 'f': /* Hafnium */
5975 result = 72;
5976 break;
5977 case 'g': /* Mercury */
5978 result = 80;
5979 break;
5980 case 's':
5981 result = 108;
5982 break;
5983 default: /* Hydrogen */
5984 result = 1;
5985 break;
5986 }
5987 break;
5988 case 'L':
5989 switch (label[1]) {
5990 case 'i': /* Lithium */
5991 result = 3;
5992 break;
5993 case 'a': /* Lathanum */
5994 result = 57;
5995 break;
5996 case 'u': /* Lutetium */
5997 result = 71;
5998 break;
5999 case 'r': /* Lawrencium */
6000 result = 103;
6001 break;
6002 case 'v': /* Livermorium */
6003 result = 116;
6004 break;
6005 }
6006 break;
6007 case 'B':
6008 switch (label[1]) {
6009 case 'e': /* Beryllium */
6010 result = 4;
6011 break;
6012 case 'r': /* Bromine */
6013 result = 35;
6014 break;
6015 case 'a': /* Barium */
6016 result = 56;
6017 break;
6018 case 'i': /* Bismuth */
6019 result = 83;
6020 break;
6021 case 'k': /* Berkelium */
6022 result = 97;
6023 break;
6024 case 'h': //Bh
6025 result = 107;
6026 break;
6027 default: /* Boron */
6028 result = 5;
6029 break;
6030 }
6031 break;
6032 case 'C':
6033 switch (label[1]) {
6034 case 'l': /* Chlorine */
6035 result = 17;
6036 break;
6037 case 'a': /* Calcium */
6038 result = 20;
6039 break;
6040 case 'r': /* Chromium */
6041 result = 24;
6042 break;
6043 case 'o': /* Cobalt */
6044 result = 27;
6045 break;
6046 case 'u': /* Copper */
6047 result = 29;
6048 break;
6049 case 'd': /* Cadmium */
6050 result = 48;
6051 break;
6052 case 's': /* Cesium */
6053 result = 55;
6054 break;
6055 case 'e': /* Cerium */
6056 result = 58;
6057 break;
6058 case 'm': /* Curium */
6059 result = 96;
6060 break;
6061 case 'f': /* Californium */
6062 result = 98;
6063 break;
6064 case 'n': /* Copernicium */
6065 result = 112;
6066 break;
6067 default: /* Carbon */
6068 result = 6;
6069 break;
6070 }
6071 break;
6072 case 'N':
6073 switch (label[1]) {
6074 case 'e': /* Neon */
6075 result = 10;
6076 break;
6077 case 'a': /* Sodium */
6078 result = 11;
6079 break;
6080 case 'i': /* Nickel */
6081 result = 28;
6082 break;
6083 case 'b': /* Niobium */
6084 result = 41;
6085 break;
6086 case 'd': /* Neodymium */
6087 result = 60;
6088 break;
6089 case 'p': /* Neptunium */
6090 result = 93;
6091 break;
6092 case 'o': /* Nobelium */
6093 result = 102;
6094 break;
6095 default: /* Nitrogen */
6096 result = 7;
6097 break;
6098 }
6099 break;
6100 case 'O':
6101 switch (label[1]) {
6102 case 's': /* Osmium */
6103 result = 76;
6104 break;
6105 default: /* Oxygen */
6106 result = 8;
6107 break;
6108 }
6109 break;
6110 case 'F':
6111 switch (label[1]) {
6112 case 'e': /* Iron */
6113 result = 26;
6114 break;
6115 case 'r': /* Francium */
6116 result = 87;
6117 break;
6118 case 'm': /* Fermium */
6119 result = 100;
6120 break;
6121 case 'l': /* Flerovium */
6122 result = 114;
6123 break;
6124 default: /* Fluorine */
6125 result = 9;
6126 break;
6127 }
6128 break;
6129 case 'M':
6130 switch (label[1]) {
6131 case 'g': /* Magnesium */
6132 result = 12;
6133 break;
6134 case 'n': /* Manganese */
6135 result = 25;
6136 break;
6137 case 'o': /* Molybdenum */
6138 result = 42;
6139 break;
6140 case 'd': /* Mendelevium */
6141 result = 101;
6142 break;
6143 case 't':
6144 result = 109;
6145 break;
6146 }
6147 break;
6148 case 'A':
6149 switch (label[1]) {
6150 case 'l': /* Aluminum */
6151 result = 13;
6152 break;
6153 case 'r': /* Argon */
6154 result = 18;
6155 break;
6156 case 's': /* Arsenic */
6157 result = 33;
6158 break;
6159 case 'g': /* Silver */
6160 result = 47;
6161 break;
6162 case 'u': /* Gold */
6163 result = 79;
6164 break;
6165 case 't': /* Astatine */
6166 result = 85;
6167 break;
6168 case 'c': /* Actinium */
6169 result = 89;
6170 break;
6171 case 'm': /* Americium */
6172 result = 95;
6173 break;
6174 }
6175 break;
6176 case 'S':
6177 switch (label[1]) {
6178 case 'i': /* Silicon */
6179 result = 14;
6180 break;
6181 case 'c': /* Scandium */
6182 result = 21;
6183 break;
6184 case 'e': /* Selenium */
6185 result = 34;
6186 break;
6187 case 'r': /* Strontium */
6188 result = 38;
6189 break;
6190 case 'n': /* Tin */
6191 result = 50;
6192 break;
6193 case 'b': /* Antimony */
6194 result = 51;
6195 break;
6196 case 'm': /* Samarium */
6197 result = 62;
6198 break;
6199 case 'g': /* Seaborgium */
6200 result = 106;
6201 break;
6202 default: /* Sulfur */
6203 result = 16;
6204 break;
6205 }
6206 break;
6207 case 'P':
6208 switch (label[1]) {
6209 case 'd': /* Palladium */
6210 result = 46;
6211 break;
6212 case 'r': /* Praseodymium */
6213 result = 59;
6214 break;
6215 case 'm': /* Promethium */
6216 result = 61;
6217 break;
6218 case 't': /* Platinum */
6219 result = 78;
6220 break;
6221 case 'b': /* Lead */
6222 result = 82;
6223 break;
6224 case 'o': /* Polonium */
6225 result = 84;
6226 break;
6227 case 'a': /* Protoactinium */
6228 result = 91;
6229 break;
6230 case 'u': /* Plutonium */
6231 result = 94;
6232 break;
6233 default: /* Phosphorus */
6234 result = 15;
6235 break;
6236 }
6237 break;
6238 case 'K':
6239 switch (label[1]) {
6240 case 'r': /* Krypton */
6241 result = 36;
6242 break;
6243 default: /* Potassium */
6244 result = 19;
6245 break;
6246 }
6247 break;
6248 case 'T':
6249 switch (label[1]) {
6250 case 'i': /* Titanium */
6251 result = 22;
6252 break;
6253 case 'c': /* Technetium */
6254 result = 43;
6255 break;
6256 case 'e': /* Tellurium */
6257 result = 52;
6258 break;
6259 case 'b': /* Terbium */
6260 result = 65;
6261 break;
6262 case 'm': /* Thullium */
6263 result = 69;
6264 break;
6265 case 'a': /* Tantalum */
6266 result = 73;
6267 break;
6268 case 'l': /* Thallium */
6269 result = 81;
6270 break;
6271 case 'h': /* Thorium */
6272 result = 90;
6273 break;
6274 }
6275 break;
6276 case 'V': /* Vanadium */
6277 result = 23;
6278 break;
6279 case 'Z':
6280 switch (label[1]) {
6281 case 'n': /* Zinc */
6282 result = 30;
6283 break;
6284 case 'r': /* Zirconium */
6285 result = 40;
6286 break;
6287 }
6288 break;
6289 case 'G':
6290 switch (label[1]) {
6291 case 'a': /* Gallium */
6292 result = 31;
6293 break;
6294 case 'e': /* Germanium */
6295 result = 32;
6296 break;
6297 case 'd': /* Gadolinium */
6298 result = 64;
6299 break;
6300 }
6301 break;
6302 case 'R':
6303 switch (label[1]) {
6304 case 'b': /* Rubidium */
6305 result = 37;
6306 break;
6307 case 'u': /* Ruthenium */
6308 result = 44;
6309 break;
6310 case 'g':
6311 result = 111; //Roentgenium
6312 break;
6313 case 'h': /* Rhodium */
6314 result = 45;
6315 break;
6316 case 'e': /* Rhenium */
6317 result = 75;
6318 break;
6319 case 'n': /* Radon */
6320 result = 86;
6321 break;
6322 case 'a': /* Radium */
6323 result = 88;
6324 break;
6325 case 'f': /* Rutherfordium */
6326 result = 104;
6327 break;
6328 }
6329 break;
6330 case 'Y':
6331 switch (label[1]) {
6332 case 'b': /* Ytterbium */
6333 result = 70;
6334 break;
6335 default: /* Yttrium */
6336 result = 39;
6337 break;
6338 }
6339 break;
6340 case 'I':
6341 switch (label[1]) {
6342 case 'n': /* Indium */
6343 result = 49;
6344 break;
6345 case 'r': /* Iridium */
6346 result = 77;
6347 break;
6348 default: /* Iodine */
6349 result = 53;
6350 break;
6351 }
6352 break;
6353 case 'X': /* Xenon */
6354 result = 54;
6355 break;
6356 case 'E':
6357 switch (label[1]) {
6358 case 'u': /* Europium */
6359 result = 63;
6360 break;
6361 case 'r': /* Erbium */
6362 result = 68;
6363 break;
6364 case 's': /* Einsteinium */
6365 result = 99;
6366 break;
6367 }
6368 break;
6369 case 'D':
6370 switch (label[1]) {
6371 case 'y':/* Dysprosium */
6372 result = 66;
6373 break;
6374 case 'b': /* Dubnium */
6375 result = 105;
6376 break;
6377 case 's': //Darmstadtium
6378 result = 110;
6379 break;
6380 default: //Deuterium
6381 result = 1;
6382 break;
6383 }
6384 break;
6385 case 'W': /* Tungsten */
6386 result = 74;
6387 break;
6388 case 'U': /* Uranium */
6389 result = 92;
6390 break;
6391 case '*': /*special atom types for special vectors*/
6392 switch (label[1]) {
6393 case 'c': /*Charge centroids with dipole vectors*/
6394 if (TestLabel[2]=='B' || TestLabel[2]=='b')
6395 result = 117;
6396 else
6397 result = 116;
6398 break;
6399 /* case 'd': The next two are not yet implemented
6400 result = 117;
6401 break;
6402 case 'p':
6403 result = 118;
6404 break; */
6405 case 'v': /*arbitrary vectors*/
6406 result = 119;
6407 break;
6408 default: /*This should only be used for *# cases*/
6409 sscanf((char *)&(label[1]), "%ld", &result);
6410 }
6411 break;
6412 }
6413 return result;
6414 } /* SetAtomType */
6415
6416 /**
6417 * This function opens the file specified by file_name and copies the contents
6418 * to a string.
6419 * @param file_name Name of file to read
6420 * @param contents String to write contents to
6421 * @\return True
6422 */
FileToString(const std::string & file_name,std::string & contents)6423 bool FileToString(const std::string& file_name,
6424 std::string& contents) {
6425
6426 std::ifstream f(file_name.c_str(), std::ios::in | std::ios::ate);
6427 if (!f.is_open()) {
6428 return false;
6429 }
6430
6431 int size;
6432
6433 // Get file size.
6434 size = (int) f.tellg();
6435 f.seekg(0, std::ios::beg);
6436
6437 // Allocate buffer, read contents in.
6438 char *cstr = new char[size];
6439 f.read(cstr, size);
6440 f.close();
6441 contents = std::string(cstr, size);
6442 delete[] cstr;
6443
6444 return true;
6445
6446 }
6447