Package org.jmol.adapter.readers.quantum

Source Code of org.jmol.adapter.readers.quantum.AdfReader$SymmetryData

/* $RCSfile: ADFReader.java,v $
* $Author: egonw $
* $Date: 2004/02/23 08:52:55 $
* $Revision: 1.3.2.4 $
*
* Copyright (C) 2002-2004  The Jmol Development Team
*
* Contact: jmol-developers@lists.sf.net
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License as published by the Free Software Foundation; either
*  version 2.1 of the License, or (at your option) any later version.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
*  02111-1307  USA.
*/
package org.jmol.adapter.readers.quantum;

import org.jmol.adapter.smarter.*;
import org.jmol.api.JmolAdapter;
import org.jmol.quantum.SlaterData;
import org.jmol.util.Logger;
//import org.jmol.util.Escape;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.ArrayList;

/**
*
* TODO: adf-2007.out causes failure reading basis functions
*
* A reader for ADF output.
* Amsterdam Density Functional (ADF) is a quantum chemistry program
* by Scientific Computing & Modelling NV (SCM)
* (http://www.scm.com/).
*
* <p> Molecular coordinates, energies, and normal coordinates of
* vibrations are read. Each set of coordinates is added to the
* ChemFile in the order they are found. Energies and vibrations
* are associated with the previously read set of coordinates.
*
* <p> This reader was developed from a small set of
* example output files, and therefore, is not guaranteed to
* properly read all ADF output. If you have problems,
* please contact the author of this code, not the developers
* of ADF.
*
*<p> Added note (Bob Hanson) -- 1/1/2010 --
*    Trying to implement reading of orbitals; ran into the problem
*    that the atomic Slater description uses Cartesian orbitals,
*    but the MO refers to spherical orbitals.
*
*
* @author Bradley A. Smith (yeldar@home.com)
* @version 1.0
*/
public class AdfReader extends SlaterReader {

 
  private Hashtable htSymmetries;
  private List vSymmetries;
  private String energy = null;
  private int nXX = 0;
  private String symLine;
 
  protected boolean checkLine() throws Exception {
   
    if (line.indexOf("Irreducible Representations, including subspecies") >= 0) {
      readSymmetries();
      return true;
    }
    if (line.indexOf("S F O s  ***  (Symmetrized Fragment Orbitals)  ***") >= 0) {
      readSlaterBasis(); // Cartesians
      return true;
    }
    if (line.indexOf(" Coordinates (Cartesian, in Input Orientation)") >= 0
        || line.indexOf("G E O M E T R Y  ***") >= 0) {
      if (!doGetModel(++modelNumber))
        return checkLastModel();
      readCoordinates();
      return true;
    }
    if (line.indexOf(" ======  Eigenvectors (rows) in BAS representation") >= 0) {
      if (readMolecularOrbitals)
        readMolecularOrbitals(getTokens(symLine)[1]);
      return true;
    }
    if (!doProcessLines)
      return true;
   
    if (line.indexOf("Energy:") >= 0) {
      String[] tokens = getTokens(line.substring(line.indexOf("Energy:")));
      energy = tokens[1];
      return true;
    }
    if (line.indexOf("Vibrations") >= 0) {
      readFrequencies();
      return true;
    }
    if (line.indexOf(" === ") >= 0) {
      symLine = line;
      return true;
    }
    if (line.indexOf(" ======  Eigenvectors (rows) in BAS representation") >= 0) {
      readMolecularOrbitals(getTokens(symLine)[1]);
      return true;
    }
    return true;
  }

  /**
   * Reads a set of coordinates
   *
   * @exception Exception  if an I/O error occurs
   */
  private void readCoordinates() throws Exception {

    /*
     *
Coordinates (Cartesian)
=======================

   Atom                      bohr                                 angstrom                 Geometric Variables
                   X           Y           Z              X           Y           Z       (0:frozen, *:LT par.)
--------------------------------------------------------------------------------------------------------------
   1 XX         .000000     .000000     .000000        .000000     .000000     .000000      0       0       0


OR


ATOMS
=====                            X Y Z                    CHARGE
                                (Angstrom)             Nucl     +Core       At.Mass
                       --------------------------    ----------------       -------
    1  Ni              0.0000    0.0000    0.0000     28.00     28.00       57.9353

     *
     */
    boolean isGeometry = (line.indexOf("G E O M E T R Y") >= 0);
    atomSetCollection.newAtomSet();
    atomSetCollection.setAtomSetName("" + energy); // start with an empty name
    discardLinesUntilContains("----");
    int pt0 = (isGeometry ? 2 : 5);
    nXX = 0;
    String[] tokens;
    while (readLine() != null && !line.startsWith(" -----")) {
      tokens = getTokens();
      if (tokens.length < 5)
        break;
      String symbol = tokens[1];
      if (JmolAdapter.getElementNumber(symbol) < 1) {
        nXX++;
        continue;
      }
      Atom atom = atomSetCollection.addNewAtom();
      atom.elementSymbol = symbol;
      atom.set(parseFloat(tokens[pt0]), parseFloat(tokens[pt0 + 1]),
          parseFloat(tokens[pt0 + 2]));
    }
  }

  /*
   Vibrations and Normal Modes  ***  (cartesian coordinates, NOT mass-weighted)  ***
   ===========================
  
   The headers on the normal mode eigenvectors below give the Frequency in cm-1
   (a negative value means an imaginary frequency, no output for (almost-)zero frequencies)


   940.906                      1571.351                      1571.351
   ------------------------      ------------------------      ------------------------
   1.XX          .000    .000    .000          .000    .000    .000          .000    .000    .000
   2.N           .000    .000    .115          .008    .067    .000         -.067    .008    .000
   3.H           .104    .180   -.534          .323   -.037   -.231          .580   -.398    .098
   4.H          -.208    .000   -.534          .017   -.757    .030         -.140   -.092   -.249
   5.H           .104   -.180   -.534         -.453   -.131    .201          .485    .378    .151


   ====================================
   */
  /**
   * Reads a set of vibrations.
   *
   * @exception Exception  if an I/O error occurs
   */
  private void readFrequencies() throws Exception {
    readLine();
    while (readLine() != null) {
      while (readLine() != null && line.indexOf(".") < 0
          && line.indexOf("====") < 0) {
      }
      if (line == null || line.indexOf(".") < 0)
        return;
      String[] frequencies = getTokens();
      readLine(); // -------- -------- --------
      int iAtom0 = atomSetCollection.getAtomCount();
      int atomCount = atomSetCollection.getLastAtomSetAtomCount();
      int frequencyCount = frequencies.length;
      boolean[] ignore = new boolean[frequencyCount];
      for (int i = 0; i < frequencyCount; ++i) {
        ignore[i] = !doGetVibration(++vibrationNumber);
        if (ignore[i])
          continue;
        atomSetCollection.cloneLastAtomSet();
        atomSetCollection.setAtomSetFrequency(null, null, frequencies[i], null);
      }
      discardLines(nXX);
      fillFrequencyData(iAtom0, atomCount, atomCount, ignore, true, 0, 0, null);
    }
  }
 
  private void readSymmetries() throws Exception {
    /*
Irreducible Representations, including subspecies
-------------------------------------------------
A1
A2
B1
B2
     */
    vSymmetries = new ArrayList();
    htSymmetries = new Hashtable();
    readLine();
    int index = 0;
    String syms = "";
    while (readLine() != null && line.length() > 1)
      syms += line;
    String[] tokens = getTokens(syms);
    for (int i = 0; i < tokens.length; i++) {
      SymmetryData sd = new SymmetryData(index++, tokens[i]);
      htSymmetries.put(tokens[i], sd);
      vSymmetries.add(sd);
    }
  }

  class SymmetryData {
    int index;
    String sym;
    int nSFO;
    int nBF;
    float[][] coefs;
    Hashtable[] mos;
    int[] basisFunctions;
    public SymmetryData(int index, String sym) {
      Logger.info("ADF reader creating SymmetryData " + sym + " " + index);
      this.index = index;
      this.sym = sym;
    }
   
  }
 
  private void readSlaterBasis() throws Exception {
    if (vSymmetries == null)
      return;
    int nBF = 0;
    for (int i = 0; i < vSymmetries.size(); i++) {
      SymmetryData sd = (SymmetryData) vSymmetries.get(i);
      Logger.info(sd.sym);
      discardLinesUntilContains("=== " + sd.sym + " ===");
      if (line == null) {
        Logger.error("Symmetry slater basis section not found: " + sd.sym);
        return;
      }
    /*
                                      === A1 ===
Nr. of SFOs :   20
Cartesian basis functions that participate in this irrep (total number =    32) :
      1     2     3     4     5     8    11    14    20    15
     18    30    23    28    31    43    32    44    33    45
     36    48    34    46    42    54    39    51    37    40
     49    52
     */
      sd.nSFO = parseInt(readLine().substring(15));
      sd.nBF = parseInt(readLine().substring(75));
      String funcList = "";
      while (readLine() != null && line.length() > 1)
        funcList += line;
      String[] tokens = getTokens(funcList);
      if (tokens.length != sd.nBF)
        return;
      sd.basisFunctions = new int[tokens.length];
      for (int j = tokens.length; --j >= 0; ) {
        int n = parseInt(tokens[j]);
        if (n > nBF)
          nBF = n;
        sd.basisFunctions[j] = n - 1;
      }
    }
    slaterArray = new SlaterData[nBF];
        /*
     (power of) X  Y  Z  R     Alpha  on Atom
                ==========     =====     ==========

N                                    1
                                  ---------------------------------------------------------------------------
    Core    0  0  0  0     6.380      1
            0  0  0  1     1.500      2
            0  0  0  1     2.500      3
            0  0  0  1     5.150      4
            1  0  0  0     1.000      5

H                                    2    3
                                  ---------------------------------------------------------------------------
            0  0  0  0     0.690     31   43
            0  0  0  0     0.920     32   44
            0  0  0  0     1.580     33   45
            1  0  0  0     1.250     34   46

       */
   
    // note, however, that these may continue to the next line as in example adf-2007.out
   
    discardLinesUntilContains("(power of)");
    discardLines(2);
    while (readLine() != null && line.length() > 2 && line.charAt(2) == ' ') {
      String data = line;
      while (readLine().indexOf("---") < 0)
        data += line;
      String[] tokens = getTokens(data);
      int nAtoms = tokens.length - 1;
      int[] atomList = new int[nAtoms];
      for (int i = 1; i <= nAtoms; i++)
        atomList[i - 1] = parseInt(tokens[i]) - 1;
      readLine();
      while (line.length() >= 10) {
        data = line;
        while (readLine().length() > 35 && line.substring(0, 35).trim().length() == 0)
          data += line;
        tokens = getTokens(data);
        boolean isCore = tokens[0].equals("Core");
        int pt = (isCore ? 1 : 0);
        int x = parseInt(tokens[pt++]);
        int y = parseInt(tokens[pt++]);
        int z = parseInt(tokens[pt++]);
        int r = parseInt(tokens[pt++]);
        float zeta = parseFloat(tokens[pt++]);
        for (int i = 0; i < nAtoms; i++) {
          int ptBF = parseInt(tokens[pt++]) - 1;
          slaterArray[ptBF] = new SlaterData(atomList[i], x, y, z, r, zeta, 1);
          slaterArray[ptBF].index = ptBF;
        }
      }
    }
  }

  private void readMolecularOrbitals(String sym) throws Exception {
    /*
======  Eigenvectors (rows) in BAS representation

  column           1                   2                   3                   4
  row  
    1    2.97448635016195E-01  7.07156589388012E-01  6.86546190383583E-03 -1.61065890134540E-03
    2   -1.38294969376236E-01 -1.62913073678337E-02 -1.31464541737858E-01  5.35848303329039E-01
    3    3.86427624200707E-02  2.84046375688973E-02  3.66872765902448E-02 -2.21326610798233E-01
     */
    SymmetryData sd = (SymmetryData) htSymmetries.get(sym);
    if (sd == null)
      return;
    int ptSym = sd.index;
    boolean isLast = (ptSym == vSymmetries.size() - 1);
    int n = 0;
    int nBF = slaterArray.length;
    sd.coefs = new float[sd.nSFO][nBF];
    while (n < sd.nBF) {
      readLine();
      int nLine = getTokens(readLine()).length;
      readLine();
      sd.mos = new Hashtable[sd.nSFO];
      String[][] data = new String[sd.nSFO][];
      fillDataBlock(data);
      for (int j = 1; j < nLine; j++) {
        int pt = sd.basisFunctions[n++];
        for (int i = 0; i < sd.nSFO; i++)
          sd.coefs[i][pt] = parseFloat(data[i][j]);
      }
    }
    for (int i = 0; i < sd.nSFO; i++) {
      Hashtable mo = new Hashtable();
      mo.put("coefficients", sd.coefs[i]);
      //System.out.println(i + " " + Escape.escapeArray(sd.coefs[i]));
      mo.put("id", sym + " " + (i + 1));
      sd.mos[i] = mo;
    }
    if (!isLast)
      return;
   /*
Orbital Energies, all Irreps
========================================

Irrep        no.  (spin)   Occup              E (au)                E (eV)
---------------------------------------------------------------------------
A1            1             2.00       -0.18782651837132E+02      -511.1020
A1            2             2.00       -0.93500325051330E+00       -25.4427
    */
    discardLinesUntilContains("Orbital Energies, all Irreps");
    discardLines(4);
    while (readLine() != null && line.length() > 10) {
      String[] tokens = getTokens();
      int len = tokens.length;
      sym = tokens[0];
      int moPt = parseInt(tokens[1]);
      // could be spin here?
      float occ = parseFloat(tokens[len - 3]);
      float energy = parseFloat(tokens[len - 1]); // eV
      sd = (SymmetryData) htSymmetries.get(sym);
      if (sd == null) {
        Enumeration e = htSymmetries.keys();
        while (e.hasMoreElements()) {
          String symfull = (String) e.nextElement();
          if (symfull.startsWith(sym + ":"))
            addMo((SymmetryData) htSymmetries.get(symfull), moPt, (occ > 2 ? 2 : occ), energy);           
        }
      } else {
        addMo(sd, moPt, occ, energy);
      }
    }
    int iAtom0 = atomSetCollection.getLastAtomSetAtomIndex();
    for (int i = 0; i < nBF; i++)
      slaterArray[i].iAtom += iAtom0;
    setSlaters(true, true);
    sortOrbitals();
    setMOs("eV");
  }

  private void addMo(SymmetryData sd, int moPt, float occ, float energy) {
    Hashtable mo = sd.mos[moPt - 1];
    mo.put("occupancy", new Float(occ));
    mo.put("energy", new Float(energy)); //eV
    mo.put("symmetry", sd.sym + "_" + moPt);
    setMO(mo);
 
}
TOP

Related Classes of org.jmol.adapter.readers.quantum.AdfReader$SymmetryData

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.