1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2006-09-12 00:46:22 -0500 (Tue, 12 Sep 2006) $ 4 * $Revision: 5501 $ 5 * 6 * Copyright (C) 2004-2005 The Jmol Development Team 7 * 8 * Contact: jmol-developers@lists.sf.net 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 */ 24 25 package org.jmol.adapter.readers.quantum; 26 27 import java.io.BufferedReader; 28 import java.util.Hashtable; 29 import java.util.Map; 30 31 import javajs.util.AU; 32 import javajs.util.Lst; 33 import javajs.util.P3; 34 import javajs.util.PT; 35 import javajs.util.Rdr; 36 import javajs.util.SB; 37 38 import org.jmol.adapter.smarter.Atom; 39 import org.jmol.quantum.QS; 40 import org.jmol.util.Logger; 41 import org.jmol.viewer.FileManager; 42 import org.jmol.viewer.JC; 43 import org.jmol.viewer.Viewer; 44 45 46 /** 47 * NBO file nn reader will pull in other files as necessary 48 * 49 * acknowledgments: Grange Hermitage, Frank Weinhold 50 * 51 * 52 * upgrade to NBO 6 allows reading of resonance structures, including base structure 53 * 54 * 55 * @author hansonr 56 **/ 57 58 59 public class GenNBOReader extends MOReader { 60 61 62 // 63 // *********************************** NBO 6.0 *********************************** 64 // N A T U R A L A T O M I C O R B I T A L A N D 65 // N A T U R A L B O N D O R B I T A L A N A L Y S I S 66 // **************************** Robert Hanson (100634) *************************** 67 // (c) Copyright 1996-2014 Board of Regents of the University of Wisconsin System 68 // on behalf of the Theoretical Chemistry Institute. All rights reserved. 69 // 70 // Cite this program as: 71 // 72 // NBO 6.0. E. D. Glendening, J. K. Badenhoop, A. E. Reed, 73 // J. E. Carpenter, J. A. Bohmann, C. M. Morales, C. R. Landis, 74 // and F. Weinhold (Theoretical Chemistry Institute, University 75 // of Wisconsin, Madison, WI, 2013); http://nbo6.chem.wisc.edu/ 76 // 77 // /NLMO / : Form natural localized molecular orbitals 78 // /NRT / : Natural Resonance Theory Analysis 79 // /AOPNAO / : Print the AO to PNAO transformation 80 // /SAO / : Print the AO overlap matrix 81 // /STERIC / : Print NBO/NLMO steric analysis 82 // /CMO / : Print analysis of canonical MOs 83 // /PLOT / : Write information for the orbital plotter 84 // /FILE / : Set to co2_p 85 // 86 // Filename set to co2_p 87 88 private boolean isOutputFile; 89 private String nboType = ""; 90 private int nOrbitals0; 91 private boolean is47File; 92 private boolean isOpenShell; 93 private boolean alphaOnly, betaOnly; 94 95 private int nAOs, nNOs; 96 97 @Override initializeReader()98 protected void initializeReader() throws Exception { 99 /* 100 * molname.31 AO 101 * molname.32 PNAO 102 * molname.33 NAO 103 * molname.34 PNHO 104 * molname.35 NHO 105 * molname.36 PNBO 106 * molname.37 NBO 107 * molname.38 PNLMO 108 * molname.39 NLMO 109 * molname.40 MO 110 * molname.41 AO density matrix 111 * molname.44 RNBO 112 * molname.45 PRNBO 113 * molname.46 Basis label file 114 * molname.47 archive file 115 * molname.nbo output file 116 * 117 */ 118 String line1 = rd().trim().toUpperCase(); 119 is47File = (line1.indexOf("$GENNBO") >= 0 || line1.indexOf("$NBO") >= 0); // GENNBO 6 120 if (is47File) { 121 if (line1.indexOf("BOHR") >= 0) { 122 fileOffset = new P3(); 123 fileScaling = P3.new3(ANGSTROMS_PER_BOHR,ANGSTROMS_PER_BOHR,ANGSTROMS_PER_BOHR); 124 } 125 readData47(); 126 return; 127 } 128 alphaOnly = checkFilterKey("ALPHA"); 129 betaOnly = checkFilterKey("BETA"); 130 boolean isOK; 131 String line2 = rd(); 132 line = line1 + line2; 133 isOutputFile = (line2.indexOf("****") >= 0); 134 if (isOutputFile) { 135 // this may or may not work. 136 isOK = getFile31(); 137 super.initializeReader(); 138 // keep going -- we need to read the file using MOReader 139 //moData.put("isNormalized", Boolean.TRUE); 140 } else if (line2.indexOf("s in the AO basis:") >= 0) { 141 nboType = line2.substring(1, line2.indexOf("s")); 142 asc.setCollectionName(line1 + ": " + nboType + "s"); 143 isOK = getFile31(); 144 } else {//if (line.indexOf("Basis set information") >= 0) { 145 nboType = "AO"; 146 asc.setCollectionName(line1 + ": " + nboType + "s"); 147 isOK = readData31(line1); 148 } 149 if (!isOK) 150 Logger.error("Unimplemented shell type -- no orbitals available: " + line); 151 if (isOutputFile) 152 return; 153 if (isOK) 154 readMOs(); 155 continuing = false; 156 } 157 158 @Override finalizeSubclassReader()159 protected void finalizeSubclassReader() throws Exception { 160 appendLoadNote("NBO type " + nboType); 161 if (isOpenShell) 162 asc.setCurrentModelInfo("isOpenShell", Boolean.TRUE); 163 finalizeReaderASCR(); 164 } 165 166 private String topoType = "A"; 167 168 //$GENNBO NATOMS=7 NBAS=28 UPPER BODM FORMAT $END 169 //$NBO $END 170 //$COORD 171 //Methylamine...RHF/3-21G//Pople-Gordon geometry 172 // 6 6 0.745914 0.011106 0.000000 173 // 7 7 -0.721743 -0.071848 0.000000 174 // 1 1 1.042059 1.060105 0.000000 175 // 1 1 1.129298 -0.483355 0.892539 176 // 1 1 1.129298 -0.483355 -0.892539 177 // 1 1 -1.076988 0.386322 -0.827032 178 // 1 1 -1.076988 0.386322 0.827032 179 //$END 180 181 182 @Override checkLine()183 protected boolean checkLine() throws Exception { 184 // for .nbo only 185 if (line.indexOf("SECOND ORDER PERTURBATION THEORY ANALYSIS") >= 0 186 && !orbitalsRead) { 187 // Frank Weinhold suggests that NBO/.37 is not the best choice for a default. 188 // PNBOs (pre-NBOs) are not orthogonalized and so "look better." But we are already 189 // reading NBOs, and they are fine as well. I'd rather not change this 190 // default and risk changes in PNGJ files already saved. 191 nboType = "NBO"; 192 String data = getFileData(".37"); 193 if (data == null) 194 return true; 195 BufferedReader readerSave = reader; 196 reader = Rdr.getBR(data); 197 rd(); 198 rd(); 199 readMOs(); 200 reader = readerSave; 201 orbitalsRead = false; 202 return true; 203 } 204 if (line.indexOf("$NRTSTRA") >= 0) { 205 getStructures("NRTSTRA"); 206 return true; 207 } 208 if (line.indexOf("$NRTSTRB") >= 0) { 209 getStructures("NRTSTRB"); 210 return true; 211 } 212 if (line.indexOf("$NRTSTR") >= 0) { 213 getStructures("NRTSTR"); 214 return true; 215 } 216 if (line.indexOf(" TOPO ") >= 0) { 217 getStructures("TOPO" + topoType); 218 topoType = "B"; 219 return true; 220 } 221 if (line.indexOf("$CHOOSE") >= 0) { 222 getStructures("CHOOSE"); 223 return true; 224 } 225 return checkNboLine(); 226 } 227 228 private int nStructures = 0; 229 NBOParser nboParser; 230 private boolean addBetaSet; 231 getStructures(String type)232 private void getStructures(String type) throws Exception { 233 if (nboParser == null) 234 nboParser = new NBOParser(); 235 236 Lst<Object> structures = getStructureList(); 237 SB sb = new SB(); 238 while (!rd().trim().equals("$END")) 239 sb.append(line).append("\n"); 240 nStructures = nboParser.getStructures(sb.toString(), type, structures); 241 appendLoadNote(nStructures + " NBO " + type + " resonance structures"); 242 } 243 244 @SuppressWarnings("unchecked") getStructureList()245 private Lst<Object> getStructureList() { 246 Lst<Object> structures = (Lst<Object>) asc.getAtomSetAuxiliaryInfo(asc.iSet).get("nboStructures"); 247 if (structures == null) 248 asc.setCurrentModelInfo("nboStructures", structures = new Lst<Object>()); 249 return structures; 250 } 251 getFileData(String ext)252 private String getFileData(String ext) throws Exception { 253 String fileName = FileManager.stripTypePrefix((String) htParams.get("fullPathName")); 254 int pt = fileName.lastIndexOf("."); 255 if (pt < 0) 256 pt = fileName.length(); 257 fileName = fileName.substring(0, pt); 258 moData.put("nboRoot", fileName); 259 if (ext.startsWith(".")) { 260 fileName += ext; 261 } else { 262 pt = fileName.lastIndexOf("/"); 263 fileName = fileName.substring(0, pt + 1) + ext; 264 } 265 String data = vwr.getFileAsString3(fileName, false, null); 266 Logger.info(data.length() + " bytes read from " + fileName); 267 boolean isError = (data.indexOf("java.io.") >= 0); 268 if (data.length() == 0 || isError && nboType != "AO") 269 throw new Exception(" supplemental file " + fileName + " was not found"); 270 if (!isError) 271 addAuxFile(moData, fileName, htParams); 272 return (isError ? null : data); 273 } 274 275 // 14_a Basis set information needed for plotting orbitals 276 // --------------------------------------------------------------------------- 277 // 36 90 162 278 // --------------------------------------------------------------------------- 279 // 6 -2.992884000 -1.750577000 1.960024000 280 // 6 -2.378528000 -1.339374000 0.620578000 281 // 282 getFile31()283 private boolean getFile31() throws Exception { 284 try { 285 String data = getFileData(".31"); 286 if (data == null) 287 return false; 288 BufferedReader readerSave = reader; 289 reader = Rdr.getBR(data); 290 return (readData31(null) && (reader = readerSave) != null); 291 } catch (Exception e) { 292 return false; 293 } 294 } 295 296 /** 297 * read the labels from xxxx.46 298 * 299 * @throws Exception 300 */ getFile46()301 private void getFile46() { 302 nNOs = nAOs = nOrbitals; 303 String labelKey = getLabelKey(nboType); 304 Map<String, String[]> map = null; 305 BufferedReader readerSave = reader; 306 try { 307 reader = Rdr.getBR(getFileData(".46")); 308 map = readData46(labelKey); 309 } catch (Exception e) { 310 try { 311 map = readOutputProperties(getFileData("output.properties")); 312 } catch (Exception ee) { 313 map = new Hashtable<String, String[]>(); 314 setMap(map, "NHO", nNOs, false); 315 setMap(map, "NBO", nNOs, false); 316 setMap(map, "NAO", nNOs, false); 317 } 318 } 319 setMap(map, labelKey, nNOs, true); 320 reader = readerSave; 321 } 322 readOutputProperties(String data)323 private Map<String, String[]> readOutputProperties(String data) { 324 Map<String, String[]> map = new Hashtable<String, String[]>(); 325 String[] lines = data.split("\n"); 326 for (int i = lines.length; --i >= 0;) { 327 String line = lines[i]; 328 if (line.startsWith("Natural Atomic Orbitals=")) { 329 setLabels(map, "NAO", line); 330 } else if (line.startsWith("Natural Hybrid Orbitals=")) { 331 setLabels(map, "NHO", line); 332 } else if (line.startsWith("Natural Bond Orbitals=")) { 333 setLabels(map, "NBO", line); 334 } 335 } 336 return map; 337 } 338 setLabels(Map<String, String[]> map, String key, String line)339 private void setLabels(Map<String, String[]> map, String key, String line) { 340 String[] tokens = PT.split(line, ":"); 341 for (int i = tokens.length; --i >= 0;) { 342 String s = PT.split(tokens[i], ",")[1]; 343 tokens[i] = (s.indexOf("%") >= 0 ? s.substring(0, s.indexOf(" ")) 344 : PT.rep(s, " ","")); 345 } 346 map.put(key, tokens); 347 } 348 349 private static String P_LIST = "101 102 103"; 350 private static String PS_LIST = "151 152 153"; 351 // GenNBO may be 103 101 102 352 353 private static String SP_LIST = "1 101 102 103"; 354 private static String SPS_LIST = "51 151 152 153"; 355 356 private static String DS_LIST = "255 252 253 254 251"; 357 // GenNBO is 251 252 253 254 255 358 // for Dxy Dxz Dyz Dx2-y2 D2z2-x2-y2 359 // org.jmol.quantum.MOCalculation expects 360 // d2z^2-x2-y2, dxz, dyz, dx2-y2, dxy 361 362 private static String DC_LIST = "201 204 206 202 203 205"; 363 // GenNBO is 201 202 203 204 205 206 364 // for Dxx Dxy Dxz Dyy Dyz Dzz 365 // org.jmol.quantum.MOCalculation expects 366 // Dxx Dyy Dzz Dxy Dxz Dyz 367 368 private static String FS_LIST = "351 352 353 354 355 356 357"; 369 // GenNBO is 351 352 353 354 355 356 357 370 // f(0) 2z3-3x2z-3y2z 371 // f(c1) 4xz2-x3-xy2 372 // f(s1) 4yz2-x2y-y3 373 // f(c2) x2z-y2z 374 // f(s2) xyz 375 // f(c3) x3-3xy2 376 // f(s3) 3x2y-y3 377 // org.jmol.quantum.MOCalculation expects the same 378 private static String FC_LIST = "301 307 310 304 302 303 306 309 308 305"; 379 // GenNBO is 301 302 303 304 305 306 307 308 309 310 380 // for xxx xxy xxz xyy xyz xzz yyy yyz yzz zzz 381 // org.jmol.quantum.MOCalculation expects 382 // xxx yyy zzz xyy xxy xxz xzz yzz yyz xyz 383 // 301 307 310 304 302 303 306 309 308 305 384 385 private static String GS_LIST = "451 452 453 454 455 456 457 458 459"; 386 // GenNBO assumes same 387 // org.jmol.quantum.MOCalculation expects 388 // 9G: G 0, G+1, G-1, G+2, G-2, G+3, G-3, G+4, G-4 389 390 private static String GC_LIST = "415 414 413 412 411 410 409 408 407 406 405 404 403 402 401"; 391 // GenNBO 401 402 403 404 405 406 407 408 409 410 392 // for xxxx xxxy xxxz xxyy xxyz xxzz xyyy xyyz xyzz xzzz 393 // GenNBO 411 412 413 414 415 394 // yyyy yyyz yyzz yzzz zzzz 395 // 396 // Gaussian is exactly opposite this. 397 398 399 private static String HS_LIST = "551 552 553 554 555 556 557 558 559 560 561"; 400 401 private static String HC_LIST = 402 "521 520 519 518 517 516 515 514 513 512 " + 403 "511 510 509 508 507 506 505 504 503 502 501"; 404 // GenNBO is 501-521 405 // 501 502 503 504 505 506 507 508 509 510 406 // for xxxxx xxxxy xxxxz xxxyy xxxyz xxxzz xxyyy xxyyz xxyzz xxzzz 407 // 511 512 513 514 515 516 517 518 519 520 408 // xyyyy xyyyz xyyzz xyzzz xzzzz yyyyy yyyyz yyyzz yyzzz yzzzz 409 // 521 410 // zzzzz 411 // 412 // Gaussian is opposite 413 414 private static String IS_LIST = "651 652 653 654 655 656 657 658 659 660 661 662 663"; 415 416 private static String IC_LIST = 417 "628 627 626 625 624 623 622 621 620 " + 418 "619 618 617 616 615 614 613 612 611 610 " + 419 "609 608 607 606 605 604 603 602 601"; 420 // GenNBO is 601-628 421 // for xxxxxx xxxxxy xxxxxz xxxxyy xxxxyz xxxxzz xxxyyy xxxyyz xxxyzz xxxzzz 422 // xxyyyy xxyyyz xxyyzz xxyzzz xxzzzz xyyyyy xyyyyz xyyyzz xyyzzz xyzzzz 423 // xzzzzz yyyyyy yyyyyz yyyyzz yyyzzz yyzzzz yzzzzz zzzzzz 424 // 425 // Gaussian is opposite this 426 readData47()427 private void readData47() throws Exception { 428 allowNoOrbitals = true; 429 discardLinesUntilContains("$COORD"); 430 asc.newAtomSet(); 431 asc.setAtomSetName(rd().trim()); 432 while (rd().indexOf("$END") < 0) { 433 String[] tokens = getTokens(); 434 addAtomXYZSymName(tokens, 2, null, null).elementNumber = (short) parseIntStr(tokens[0]); 435 } 436 437 //Commented out by fzy 438 //This fixes the issue of NRT (SEARCH module) stuck in "getting list r" operation/ NBOServe dies for open shell molecules. 439 //This also fixes the issue of switching from RUN module(after inputting a .47 file) to MODEL module, which results in NBOServe throwing 440 //warning. The reason lies in Jmol sending CMD <empty string> to NBOServe. 441 // if (doReadMolecularOrbitals && !getFile31()) { 442 // alphaOnly = true; 443 // betaOnly = false; 444 445 discardLinesUntilContains("$BASIS"); 446 appendLoadNote("basis AOs are unnormalized"); 447 int[] centers = getIntData(); 448 int[] labels = getIntData(); 449 450 discardLinesUntilContains("NSHELL ="); 451 452 453 454 shellCount = parseIntAt(line, 10); 455 gaussianCount = parseIntAt(rd(), 10); 456 rd(); 457 int[] ncomp = getIntData(); 458 int[] nprim = getIntData(); 459 int[] nptr = getIntData(); 460 // read basis functions 461 shells = new Lst<int[]>(); 462 gaussians = AU.newFloat2(gaussianCount); 463 for (int i = 0; i < gaussianCount; i++) 464 gaussians[i] = new float[6]; 465 nOrbitals = 0; 466 int ptCenter = 0; 467 String l = line; 468 for (int i = 0; i < shellCount; i++) { 469 int[] slater = new int[4]; 470 int nc = ncomp[i]; 471 slater[0] = centers[ptCenter]; 472 line = ""; 473 for (int ii = 0; ii < nc; ii++) 474 line += labels[ptCenter++] + " "; 475 if (!fillSlater(slater, nc, nptr[i] - 1, nprim[i])) 476 return; 477 } 478 line = l; 479 getAlphasAndExponents(); 480 nboType = "AO"; 481 readMOs(); 482 // } 483 continuing = false; 484 } 485 getIntData()486 private int[] getIntData() throws Exception { 487 while (line.indexOf("=") < 0) 488 rd(); 489 String s = line.substring(line.indexOf("=") + 1); 490 line = ""; 491 while (rd().indexOf("=") < 0 && line.indexOf("$") < 0) 492 s += line; 493 String[] tokens = PT.getTokens(s); 494 int[] f = new int[tokens.length]; 495 for (int i = f.length; --i >= 0;) 496 f[i] = parseIntStr(tokens[i]); 497 return f; 498 } 499 fillSlater(int[] slater, int n, int pt, int ng)500 private boolean fillSlater(int[] slater, int n, int pt, int ng) { 501 nOrbitals += n; 502 switch (n) { 503 case 1: 504 slater[1] = QS.S; 505 break; 506 case 3: 507 if (!getDFMap("P", line, QS.P, P_LIST, 3) && resetDF() && !getDFMap("P", line, QS.P, PS_LIST, 3)) 508 return false; 509 slater[1] = QS.P; 510 break; 511 case 4: 512 if (!getDFMap("SP", line, QS.SP, SP_LIST, 1) && resetDF() && !getDFMap("SP", line, QS.SP, SPS_LIST, 2)) 513 return false; 514 slater[1] = QS.SP; 515 break; 516 517 case 5: 518 if (!getDFMap("DS", line, QS.DS, DS_LIST, 3)) 519 return false; 520 slater[1] = QS.DS; 521 break; 522 case 6: 523 if (!getDFMap("DC", line, QS.DC, DC_LIST, 3)) 524 return false; 525 slater[1] = QS.DC; 526 break; 527 528 case 7: 529 if (!getDFMap("FS", line, QS.FS, FS_LIST, 3)) 530 return false; 531 slater[1] = QS.FS; 532 break; 533 case 10: 534 if (!getDFMap("FC", line, QS.FC, FC_LIST, 3)) 535 return false; 536 slater[1] = QS.FC; 537 break; 538 539 case 9: 540 if (!getDFMap("GS", line, QS.GS, GS_LIST, 3)) 541 return false; 542 slater[1] = QS.GS; 543 break; 544 case 15: 545 if (!getDFMap("GC", line, QS.GC, GC_LIST, 3)) 546 return false; 547 slater[1] = QS.GC; 548 break; 549 550 case 11: 551 if (!getDFMap("HS", line, QS.HS, HS_LIST, 3)) 552 return false; 553 slater[1] = QS.HS; 554 break; 555 case 21: 556 if (!getDFMap("HC", line, QS.HC, HC_LIST, 3)) 557 return false; 558 slater[1] = QS.HC; 559 break; 560 561 case 13: 562 if (!getDFMap("IS", line, QS.IS, IS_LIST, 3)) 563 return false; 564 slater[1] = QS.IS; 565 break; 566 case 28: 567 if (!getDFMap("IC", line, QS.IC, IC_LIST, 3)) 568 return false; 569 slater[1] = QS.IC; 570 break; 571 default: 572 Logger.error("Unrecognized orbital slater count: " + n); 573 break; 574 } 575 slater[2] = pt + 1; // gaussian list pointer 576 slater[3] = ng; // number of gaussians 577 shells.addLast(slater); 578 return true; 579 } 580 resetDF()581 private boolean resetDF() { 582 dfCoefMaps[QS.P][0] = 0; 583 return true; 584 } 585 getAlphasAndExponents()586 private void getAlphasAndExponents() throws Exception { 587 // EXP CS CP CD ?? 588 for (int j = 0; j < 5; j++) { 589 if (line.indexOf("=") < 0) 590 rd(); 591 if (line.indexOf("$END") >= 0) 592 break; 593 line = line.substring(line.indexOf("=") + 1); 594 float[] temp = fillFloatArray(line, 0, new float[gaussianCount]); 595 for (int i = 0; i < gaussianCount; i++) { 596 gaussians[i][j] = temp[i]; 597 if (j > 1) 598 gaussians[i][5] += temp[i]; 599 } 600 } 601 // GenNBO lists S, P, D, F, G orbital coefficients separately 602 // we need all of them in [1] if [1] is zero (not S or SP) 603 for (int i = 0; i < gaussianCount; i++) { 604 if (gaussians[i][1] == 0) 605 gaussians[i][1] = gaussians[i][5]; 606 } 607 if (debugging) { 608 Logger.debug(shells.size() + " slater shells read"); 609 Logger.debug(gaussians.length + " gaussian primitives read"); 610 } 611 } 612 readData31(String line1)613 private boolean readData31(String line1) throws Exception { 614 615 // HCN(-), E(UB3LYP) = -93.4597027357 [nu: 804(2),2186,3329] Vibrational te 616 // Basis set information needed for plotting orbitals 617 // --------------------------------------------------------------------------- 618 // 3 74 111 619 // --------------------------------------------------------------------------- 620 // 1 0.000000 0.000000 -1.567118 621 // 6 0.000000 0.000000 -0.496424 622 // 7 0.000000 0.000000 0.649380 623 // --------------------------------------------------------------------------- 624 // 1 1 1 4 625 // 1 626 // 1 1 5 1 627 // 1 628 // 1 1 6 1 629 // 1 630 // 1 1 7 1 631 // 1 632 // 1 1 8 1 633 // 1 634 // 1 1 9 1 635 // 1 636 // 1 3 10 1 637 // 101 102 103 638 // ... 639 // 2 11 66 1 640 // 551 552 553 554 555 556 557 558 559 560 641 // 561 642 643 644 if (line1 == null) { 645 line1 = rd(); 646 rd(); 647 } 648 rd(); // ---------- 649 650 // read ac, shellCount, and gaussianCount 651 String[] tokens = PT.getTokens(rd()); 652 int ac = parseIntStr(tokens[0]); 653 shellCount = parseIntStr(tokens[1]); 654 gaussianCount = parseIntStr(tokens[2]); 655 if (tokens.length < 4) 656 Logger.error("NOTE! .31 file is old; d orbitals are not normalized"); 657 658 // read atom types and positions 659 rd(); // ---------- 660 asc.newAtomSet(); 661 asc.setAtomSetName(nboType + "s: " + line1.trim()); 662 asc.setCurrentModelInfo("nboType", nboType); 663 for (int i = 0; i < ac; i++) { 664 tokens = PT.getTokens(rd()); 665 int z = parseIntStr(tokens[0]); 666 if (z < 0) // dummy atom 667 continue; 668 Atom atom = asc.addNewAtom(); 669 atom.elementNumber = (short) z; 670 setAtomCoordTokens(atom, tokens, 1); 671 } 672 673 // read basis functions 674 shells = new Lst<int[]>(); 675 gaussians = AU.newFloat2(gaussianCount); 676 for (int i = 0; i < gaussianCount; i++) 677 gaussians[i] = new float[6]; 678 rd(); // ---------- 679 nOrbitals = 0; 680 for (int i = 0; i < shellCount; i++) { 681 tokens = PT.getTokens(rd()); 682 int[] slater = new int[4]; 683 slater[0] = parseIntStr(tokens[0]); // atom pointer; 1-based 684 int n = parseIntStr(tokens[1]); 685 int pt = parseIntStr(tokens[2]) - 1; // gaussian list pointer 686 int ng = parseIntStr(tokens[3]); // number of gaussians 687 line = rd(); 688 for (int j = (n - 1) / 10; --j >= 0;) 689 line += rd().substring(1); 690 line = line.trim(); 691 //System.out.println(line); 692 if (!fillSlater(slater, n, pt, ng)) 693 return false; 694 } 695 rd(); 696 getAlphasAndExponents(); 697 return true; 698 } 699 700 /** 701 * read labels and not proper number of NOs, nNOs, for this nboType 702 * @return 703 * 704 * @throws Exception 705 */ readData46(String labelKey)706 private Map<String, String[]> readData46(String labelKey) throws Exception { 707 Map<String, String[]> map = new Hashtable<String, String[]>(); 708 String[] tokens = new String[0]; 709 rd(); 710 int nNOs = this.nNOs; 711 while (line != null && line.length() > 0) { 712 tokens = PT.getTokens(line); 713 String type = tokens[0]; 714 isOpenShell = (tokens.length == 3); 715 String ab = (isOpenShell ? tokens[1] : ""); 716 String count = tokens[tokens.length - 1]; 717 String key = (ab.equals("BETA") ? "beta_" : "") + type; 718 if (parseIntStr(count) != nOrbitals) { 719 Logger.error("file 46 number of orbitals for " + line + " (" + count + ") does not match nOrbitals: " 720 + nOrbitals + "\n"); 721 nNOs = parseIntStr(count); 722 } 723 if (type.equals(labelKey)) 724 this.nNOs = nNOs; 725 SB sb = new SB(); 726 while (rd() != null && line.length() > 4 && " NA NB AO NH".indexOf(line.substring(1, 4)) < 0) 727 sb.append(line.substring(1)); 728 //System.out.println(sb.length()); 729 tokens = new String[sb.length() / 10]; 730 for (int i = 0, pt = 0; i < tokens.length; i++, pt += 10) 731 tokens[i] = PT.rep(sb.substring2(pt, pt + 10), " ",""); 732 map.put(key, tokens); 733 } 734 return map; 735 } 736 setMap(Map<String, String[]> map, String labelKey, int nNOs, boolean doAll)737 private void setMap(Map<String, String[]> map, String labelKey, int nNOs, boolean doAll) { 738 String[] tokens = map.get((betaOnly ? "beta_" : "") + labelKey); 739 moData.put("nboLabelMap", map); 740 if (tokens == null) { 741 tokens = new String[nNOs]; 742 for (int i = 0; i < nNOs; i++) 743 tokens[i] = nboType + (i + 1); 744 map.put(labelKey, tokens); 745 if (isOpenShell) 746 map.put("beta_" + labelKey, tokens); 747 } 748 if (!doAll) 749 return; 750 moData.put("nboLabels", tokens); 751 addBetaSet = (isOpenShell && !betaOnly && !is47File); 752 if (addBetaSet) 753 nOrbitals *= 2; 754 for (int i = 0; i < nOrbitals; i++) 755 setMO(new Hashtable<String, Object>()); 756 setNboLabels(tokens, nNOs, orbitals, nOrbitals0, nboType); 757 if (addBetaSet) { 758 moData.put("firstBeta", Integer.valueOf(nNOs)); 759 setNboLabels( map.get("beta_" + labelKey), nNOs, orbitals, nOrbitals0 + nNOs, nboType); 760 } 761 Lst<Object> structures = getStructureList(); 762 NBOParser.getStructures46(map.get("NBO"), "alpha", structures, asc.ac); 763 NBOParser.getStructures46(map.get("beta_NBO"), "beta", structures, asc.ac); 764 765 } 766 getLabelKey(String labelKey)767 private static String getLabelKey(String labelKey) { 768 if (labelKey.startsWith("P")) 769 labelKey = labelKey.substring(1); 770 if (labelKey.equals("NLMO")) 771 labelKey = "NBO"; 772 if (labelKey.equals("MO")) // no longer? 773 labelKey = "NO"; 774 return labelKey; 775 } 776 777 /** 778 * Called by setNBOType in IsoExt when use issues NBO TYPE xxx 779 * 780 * @param moData 781 * @param nboType 782 * @param vwr 783 * @return true if sucessful or false if required file is missing 784 */ 785 @SuppressWarnings("unchecked") readNBOCoefficients(Map<String, Object> moData, String nboType, Viewer vwr)786 public static boolean readNBOCoefficients(Map<String, Object> moData, String nboType, 787 Viewer vwr) { 788 int ext = JC.getNBOTypeFromName(nboType); 789 boolean isAO = nboType.equals("AO"); 790 boolean isNBO = nboType.equals("NBO"); 791 //boolean discardExtra = PT.isOneOf(nboType, ";NBO;NLMO;"); 792 boolean hasNoBeta = PT.isOneOf(nboType, ";AO;PNAO;NAO;"); 793 Map<String, String[]> map = (Map<String, String[]>) moData.get("nboLabelMap"); 794 int nAOs = map.get("AO").length; 795 String labelKey = getLabelKey(nboType); 796 String[] nboLabels = map.get(labelKey); 797 if (nboLabels == null) { 798 // MO and NO need simple MO1 MO2 .. labels 799 nboLabels = new String[nAOs]; 800 for (int i = 0; i < nAOs; i++) 801 nboLabels[i] = nboType + (i + 1); 802 labelKey = nboType; 803 map.put(labelKey, nboLabels); 804 if (!hasNoBeta) 805 map.put("beta_" + labelKey, nboLabels); 806 } 807 // It is possible for nAOs > nMOs. See, for example, 808 // http://nbo6.chem.wisc.edu/jmol_nborxiv/ketamine.47 809 int nMOs = nboLabels.length; 810 try { 811 Lst<Map<String, Object>> orbitals = (Lst<Map<String, Object>>) moData 812 .get(nboType + "_coefs"); 813 if (orbitals == null) { 814 String data = null; 815 if (!isAO) { 816 String fileName = moData.get("nboRoot") + "." + ext; 817 if ((data = vwr.getFileAsString3(fileName, true, null)) == null 818 || data.indexOf("Exception:") >= 0) 819 return false; 820 addAuxFile(moData, fileName, null); 821 data = data.substring(data.indexOf("--\n") + 3).toLowerCase(); 822 if (ext == 33) 823 data = data.substring(0, data.indexOf("--\n") + 3); 824 } 825 orbitals = (Lst<Map<String, Object>>) moData.get("mos"); 826 Object dfCoefMaps = orbitals.get(0).get("dfCoefMaps"); 827 orbitals = new Lst<Map<String, Object>>(); 828 int len = 0; 829 int[] next = null; 830 int nOrbitals = nMOs; 831 if (!isAO) { 832 if (data.indexOf("alpha") >= 0) { 833 nOrbitals *= 2; 834 data = data.substring(data.indexOf("alpha") + 10); // "alpha spin" 835 } 836 len = data.length(); 837 next = new int[1]; 838 } 839 for (int i = nOrbitals; --i >= 0;) { 840 Map<String, Object> mo = new Hashtable<String, Object>(); 841 orbitals.addLast(mo); 842 if (dfCoefMaps != null) 843 mo.put("dfCoefMaps", dfCoefMaps); 844 } 845 setNboLabels(nboLabels, nMOs, orbitals, 0, nboType); 846 for (int i = 0; i < nOrbitals; i++) { 847 if (!isAO && i == nMOs) { 848 if (isNBO) 849 getNBOOccupanciesStatic(orbitals, nMOs, 0, data, len, next); 850 nboLabels = map.get("beta_" + labelKey); 851 // always discarding extra here 852 853 next[0] = (hasNoBeta ? 0 : data.indexOf("beta spin") + 12); 854 // do skips, occupancy here 855 // must skip "beta spin" 856 } 857 Map<String, Object> mo = orbitals.get(i); 858 float[] coefs = new float[nAOs]; 859 if (isAO) { 860 coefs[i % nAOs] = 1; 861 } else if (i >= nAOs && hasNoBeta){ 862 coefs = (float[]) orbitals.get(i % nAOs).get("coefficients"); 863 } else { 864 for (int j = 0; j < nAOs; j++) { 865 coefs[j] = PT.parseFloatChecked(data, len, next, false); 866 if (Float.isNaN(coefs[j])) 867 System.out.println("oops = IsoExt "); 868 } 869 } 870 mo.put("coefficients", coefs); 871 } 872 if (isNBO) 873 getNBOOccupanciesStatic(orbitals, nMOs, nOrbitals - nMOs, data, len, next); 874 moData.put(nboType + "_coefs", orbitals); 875 } 876 moData.put("nboType", nboType); 877 moData.put("nboLabels", nboLabels); 878 moData.put("mos", orbitals); 879 } catch (Exception e) { 880 e.printStackTrace(); 881 return false; 882 } 883 return true; 884 } 885 addAuxFile(Map<String, Object> moData, String fileName, Map<String, Object> htParams)886 private static void addAuxFile(Map<String, Object> moData, String fileName, Map<String, Object> htParams) { 887 @SuppressWarnings("unchecked") 888 Lst<String> auxFiles = (Lst<String>) moData.get("auxFiles"); 889 if (auxFiles == null) 890 moData.put("auxFiles", auxFiles = new Lst<String>()); 891 auxFiles.addLast(fileName); 892 if (htParams != null) 893 htParams.put("auxFiles", auxFiles); 894 } 895 getNBOOccupanciesStatic(Lst<Map<String, Object>> orbitals, int nAOs, int pt, String data, int len, int[] next)896 private static void getNBOOccupanciesStatic(Lst<Map<String, Object>> orbitals, 897 int nAOs, int pt, String data, 898 int len, int[] next) { 899 float[] occupancies = new float[nAOs]; 900 for (int j = 0; j < nAOs; j++) 901 occupancies[j] = PT.parseFloatChecked(data, len, next, false); 902 for (int i = 0; i < nAOs; i++) { 903 Map<String, Object> mo = orbitals.get(pt + i); 904 mo.put("occupancy", Float.valueOf(occupancies[i])); 905 } 906 } 907 readMOs()908 private void readMOs() throws Exception { 909 910 // .31 AO basis 911 // .32 PNAO no beta coef 912 // .33 NAO no beta coef ; adds orbital types 913 // .34 PNHO alpha+beta 914 // .35 NHO alpha+beta 915 // .36 PNBO alpha+beta 916 // .37 NBO alpha+extra+beta+extra 917 // .38 PNLMO alpha+beta 918 // .39 NLMO alpha+extra+beta+extra 919 // .40 MO alpha+beta 920 // .41 NO alpha+beta 921 // .42 (density matrix) 922 // .44 RNBO alpha+beta 923 // .45 PRNBO alpha+beta 924 // .46 (labels) 925 // .47 (coords) 926 927 boolean isAO = nboType.equals("AO"); 928 boolean isNBO = nboType.equals("NBO"); 929 boolean discardExtra = PT.isOneOf(nboType, ";NBO;NLMO;"); 930 boolean hasNoBeta = PT.isOneOf(nboType, ";AO;PNAO;NAO;"); 931 nOrbitals0 = orbitals.size(); 932 // get the labels 933 getFile46(); 934 if (betaOnly) { 935 discardLinesUntilContains("BETA"); 936 filterMO(); 937 } 938 nOrbitals = orbitals.size(); 939 if (nOrbitals == 0) 940 return; 941 line = null; 942 int pt = 0; 943 for (int i = nOrbitals0, n = nOrbitals0 + nOrbitals; i < n; i++, pt++) { 944 if (pt == nNOs) { 945 if (isNBO) { 946 readNBO37Occupancies(pt); 947 } 948 if (discardExtra) 949 discardLinesUntilContains2("BETA", "beta"); 950 } 951 Map<String, Object> mo = orbitals.get(i); 952 float[] coefs = new float[nAOs]; 953 if (isAO) { 954 coefs[pt % nAOs] = 1; 955 } else if (pt >= nNOs && hasNoBeta){ 956 coefs = (float[]) orbitals.get(pt % nNOs).get("coefficients"); 957 } else { 958 if (line == null) { 959 while (rd() != null && Float.isNaN(parseFloatStr(line))) { 960 filterMO(); //switch a/b 961 } 962 } else { 963 line = null; 964 } 965 fillFloatArray(line, 0, coefs); 966 line = null; 967 } 968 mo.put("coefficients", coefs); 969 } 970 if (isNBO) 971 readNBO37Occupancies(pt); 972 moData.put(nboType + "_coefs", orbitals); 973 setMOData(false); 974 moData.put("nboType", nboType); 975 Logger.info((orbitals.size() - nOrbitals0) + " orbitals read"); 976 977 } 978 979 /** 980 * Read occupancies from .37 file. Called by readMOs. 981 * @param pt 982 * @throws Exception 983 */ readNBO37Occupancies(int pt)984 private void readNBO37Occupancies(int pt) throws Exception { 985 float[] occupancies = new float[nNOs]; 986 fillFloatArray(null, 0, occupancies); 987 for (int i = 0; i < nNOs; i++) { 988 Map<String, Object> mo = orbitals.get(nOrbitals0 + pt - nNOs + i); 989 mo.put("occupancy", Float.valueOf(occupancies[i])); 990 } 991 } 992 setNboLabels(String[] tokens, int nLabels, Lst<Map<String, Object>> orbitals, int nOrbitals0, String moType)993 public static void setNboLabels(String[] tokens, int nLabels, 994 Lst<Map<String, Object>> orbitals, int nOrbitals0, 995 String moType) { 996 boolean alphaBeta = (orbitals.size() == nLabels * 2); 997 boolean addOccupancy = !PT.isOneOf(moType, ";AO;NAO;PNAO;MO;NO;"); 998 String ab = (!alphaBeta ? "" : nOrbitals0 == 0 ? " alpha" : " beta"); 999 for (int j = 0; j < nLabels; j++) { 1000 Map<String, Object> mo = orbitals.get(j + nOrbitals0); 1001 String type = tokens[j]; 1002 mo.put("type", moType + " " + type + ab); 1003 if (addOccupancy) 1004 mo.put( 1005 "occupancy", 1006 Float.valueOf(alphaBeta ? 1 : type.indexOf("*") >= 0 1007 || type.indexOf("(ry)") >= 0 ? 0 : 2)); 1008 } 1009 } 1010 1011 }