Clazz.declarePackage("J.adapter.readers.xtal");
Clazz.load(["J.adapter.smarter.AtomSetCollectionReader", "JU.Lst", "$.P3"], "J.adapter.readers.xtal.CrystalReader", ["java.util.Arrays", "$.Hashtable", "JU.DF", "$.M3", "$.M4", "$.PT", "$.Quat", "$.SB", "$.V3", "JS.SymmetryOperation", "JU.Logger", "$.Tensor"], function(){
var c$ = Clazz.decorateAsClass(function(){
this.isVersion3 = false;
this.isPolymer = false;
this.isSlab = false;
this.haveCharges = false;
this.inputOnly = false;
this.isLongMode = false;
this.getLastConventional = false;
this.havePrimitiveMapping = false;
this.isProperties = false;
this.state = 0;
this.ac = 0;
this.atomIndexLast = 0;
this.atomFrag = null;
this.primitiveToIndex = null;
this.nuclearCharges = null;
this.lstCoords = null;
this.energy = null;
this.ptOriginShift = null;
this.directLatticeVectors = null;
this.spaceGroupName = null;
this.checkModelTrigger = false;
this.fullSymmetry = false;
this.htCriticalPoints = null;
this.directLatticeVectorsFirst = false;
this.cpno = -1;
this.symops = null;
this.f14 = null;
this.f16 = null;
this.primitiveVolume = 0;
this.primitiveDensity = 0;
this.firstLine = null;
this.type = null;
Clazz.instantialize(this, arguments);}, J.adapter.readers.xtal, "CrystalReader", J.adapter.smarter.AtomSetCollectionReader);
Clazz.prepareFields (c$, function(){
this.ptOriginShift =  new JU.P3();
this.symops =  new JU.Lst();
this.f14 =  Clazz.newFloatArray (14, 0);
this.f16 =  Clazz.newFloatArray (16, 0);
});
Clazz.defineMethod(c$, "rd", 
function(){
while (Clazz.superCall(this, J.adapter.readers.xtal.CrystalReader, "rd", []) != null && (this.line.startsWith(" PROCESS") || this.line.startsWith(" INFORMATION") || this.line.startsWith(" WARNING"))) {
}
return this.line;
});
Clazz.overrideMethod(c$, "initializeReader", 
function(){
this.doProcessLines = false;
this.inputOnly = this.checkFilterKey("INPUT");
this.isPrimitive = !this.inputOnly && !this.checkFilterKey("CONV");
this.addVibrations = new Boolean (this.addVibrations & (!this.inputOnly && this.desiredModelNumber < 0)).valueOf();
this.getLastConventional = (!this.isPrimitive && this.desiredModelNumber == 0);
this.fullSymmetry = this.checkFilterKey("FULLSYM");
this.setFractionalCoordinates(this.readHeader());
this.asc.crystalReaderLatticeOpsOnly = !this.inputOnly;
});
Clazz.overrideMethod(c$, "checkLine", 
function(){
if (this.firstLine != null) {
this.line = this.firstLine;
this.firstLine = null;
}if (this.line.startsWith(" TYPE OF CALCULATION")) {
this.calculationType = this.line.substring(this.line.indexOf(":") + 1).trim();
return true;
}if (this.line.indexOf("DIMENSIONALITY OF THE SYSTEM") >= 0) {
this.isMolecular = this.isSlab = this.isPolymer = false;
if (this.line.indexOf("2") >= 0) this.isSlab = true;
 else if (this.line.indexOf("1") >= 0) this.isPolymer = true;
 else if (this.line.indexOf("0") >= 0) this.isMolecular = true;
return true;
}if (!this.isPolymer && this.line.indexOf("CONSTRUCTION OF A NANOTUBE FROM A SLAB") >= 0) {
this.isPolymer = true;
this.isSlab = false;
return true;
}if (!this.isMolecular && this.line.indexOf("* CLUSTER CALCULATION") >= 0) {
this.isMolecular = true;
this.isSlab = false;
this.isPolymer = false;
return true;
}if (this.line.startsWith(" INPUT COORDINATES")) {
this.state = 1;
if (this.inputOnly) {
this.newAtomSet();
this.readCoordLines();
this.continuing = false;
}return true;
}if (this.line.startsWith(" GEOMETRY INPUT FROM EXTERNAL")) {
this.state = 2;
if (this.inputOnly) this.continuing = false;
return true;
}if (this.line.startsWith(" GEOMETRY FOR WAVE FUNCTION")) {
this.state = 3;
return true;
}if (this.line.startsWith(" COORDINATE OPTIMIZATION - POINT")) {
this.state = 4;
return true;
}if (this.line.startsWith(" FINAL OPTIMIZED GEOMETRY")) {
this.getLastConventional = false;
this.state = 5;
return true;
}if (this.addVibrations && this.line.contains(this.isVersion3 ? "EIGENVALUES (EV) OF THE MASS" : "EIGENVALUES (EIGV) OF THE MASS") || this.line.indexOf("LONGITUDINAL OPTICAL (LO)") >= 0) {
this.state = 6;
this.isLongMode = (this.line.indexOf("LONGITUDINAL OPTICAL (LO)") >= 0);
this.readFrequencies();
return true;
}if (this.line.startsWith(" TRANSFORMATION MATRIX")) {
this.readPrimitiveLatticeVectors();
return true;
}if (this.line.startsWith(" COORDINATES OF THE EQUIVALENT ATOMS") || this.line.startsWith(" INPUT LIST - ATOM N.")) {
return true;
}if (this.line.indexOf("SYMMOPS - ") >= 0) {
this.readSymmetryOperators();
return true;
}if (this.line.startsWith(" LATTICE PARAMETER")) {
this.newLattice(this.line.indexOf("- CONVENTIONAL") >= 0);
return true;
}if (this.line.startsWith(" CRYSTALLOGRAPHIC CELL")) {
if (!this.isPrimitive) {
this.newLattice(true);
}return true;
}if (this.line.startsWith(" DIRECT LATTICE VECTOR")) {
this.getDirect();
return true;
}if (this.line.startsWith(" COORDINATES IN THE CRYSTALLOGRAPHIC CELL")) {
this.checkModelTrigger = !this.isPrimitive;
if (this.checkModelTrigger) {
this.readCoordLines();
}return true;
}if (this.addVibrations && this.line.startsWith(" FREQUENCIES COMPUTED ON A FRAGMENT")) {
this.readFreqFragments();
return true;
}if (this.checkModelTrigger) {
if (this.line.indexOf("CARTESIAN COORDINATES") >= 0 || this.line.indexOf("TOTAL ENERGY") >= 0 || this.line.indexOf("REFERENCE GEOMETRY DEFINED") >= 0 || this.line.indexOf("FUNCTIONS") >= 0) {
this.checkModelTrigger = false;
if (!this.addModel()) return true;
}}if (this.line.startsWith(" ATOMS IN THE ASYMMETRIC UNIT")) {
if (this.isMolecular) return (this.doGetModel(++this.modelNumber, null) ? this.readAtoms() : this.checkLastModel());
this.readCoordLines();
this.checkModelTrigger = true;
}if (this.isProperties && this.line.startsWith("   ATOM N.AT.")) {
if (this.doGetModel(++this.modelNumber, null)) this.readAtoms();
 else this.checkLastModel();
}if (!this.doProcessLines) return true;
if (this.line.startsWith(" TOTAL ENERGY(")) {
this.line = JU.PT.rep(this.line, "( ", "(");
var tokens = this.getTokens();
this.energy = Double.$valueOf(Double.parseDouble(tokens[2]));
this.setEnergy();
this.rd();
if (this.line.startsWith(" ********")) this.discardLinesUntilContains("SYMMETRY ALLOWED");
 else if (this.line.startsWith(" TTTTTTTT")) this.discardLinesUntilContains(" *******");
return true;
}if (this.line.startsWith(" MULLIKEN POPULATION ANALYSIS")) return this.readPartialCharges();
if (this.line.startsWith(" TOTAL ATOMIC CHARGES")) return this.readTotalAtomicCharges();
if (this.line.startsWith(" MAX GRADIENT")) return this.readGradient();
if (this.line.startsWith(" ATOMIC SPINS SET")) return this.readData("spin", 3);
if (this.line.startsWith(" TOTAL ATOMIC SPINS  :")) return this.readData("magneticMoment", 1);
if (this.line.startsWith(" BORN CHARGE TENSOR.")) return this.readBornChargeTensors();
if (!this.isProperties) return true;
if (this.line.startsWith(" DEFINITION OF TRACELESS")) return this.getQuadrupoleTensors();
if (this.line.startsWith(" MULTIPOLE ANALYSIS BY ATOMS")) {
this.appendLoadNote("Multipole Analysis");
return true;
}if (this.line.startsWith(" CP N. ")) {
this.cpno = this.parseIntAt(this.line, 6);
return true;
}if (this.line.startsWith(" CP TYPE ")) {
this.processNextCriticalPoint();
return true;
}return true;
});
Clazz.defineMethod(c$, "processNextCriticalPoint", 
function(){
if (this.htCriticalPoints == null) {
this.htCriticalPoints =  new java.util.Hashtable();
this.asc.setModelInfoForSet("criticalPoints", this.htCriticalPoints, 0);
}var nblank = 0;
var id = null;
var entry = null;
var f = 0.5291772;
var m = null;
var v = NaN;
var g = NaN;
var rho = NaN;
var evalues = null;
var type = null;
while (this.line != null || this.rd().length > 0 || ++nblank < 2) {
if (this.line.indexOf("CLUSTER") >= 0) {
break;
}if (this.line.length > 0) nblank = 0;
var pt = this.line.indexOf(":");
if (pt > 0) {
var key = this.line.substring(0, pt).trim();
var value = this.line.substring(pt + 1);
if (key.equals("CP TYPE")) {
type = J.adapter.readers.xtal.CrystalReader.crtypes[Clazz.doubleToInt("??,-3,-1,+1,+3".indexOf(value.substring(5, 7)) / 3)];
entry = this.htCriticalPoints.get(type);
if (entry == null) {
this.htCriticalPoints.put(type, entry =  new JU.Lst());
}m =  new java.util.Hashtable();
entry.addLast(m);
var i = entry.size();
id = "cp_" + i;
m.put("cpno", Integer.$valueOf(this.cpno));
m.put("id", id);
m.put("type", type);
m.put("index", Integer.$valueOf(i));
} else if (key.equals("COORD(AU)  (X  Y  Z)")) {
var xyz = JU.P3.new3(f * this.parseFloatStr(value.substring(0, 12)), f * this.parseFloatStr(value.substring(12, 24)), f * this.parseFloatStr(value.substring(24, 36)));
m.put("point", xyz);
JU.Logger.info("CRYSTAL TOPOND critical point " + type + " " + xyz);
} else if (key.equals("PROPERTIES (RHO,GRHO,LAP)")) {
rho = this.parseFloatStr(value.substring(0, 12));
m.put("rho", Float.$valueOf(rho));
m.put("lap", Float.$valueOf(this.parseFloatStr(value.substring(24, 36))));
} else if (key.equals("PROPERTIES (-LAP,GLAP,RHO)")) {
m.put("lap", Float.$valueOf(-this.parseFloatStr(value.substring(0, 12))));
rho = this.parseFloatStr(value.substring(24, 36));
m.put("rho", Float.$valueOf(rho));
} else if (key.equals("KINETIC ENERGY DENSITIES (G,K)")) {
g = this.parseFloatStr(value.substring(0, 12));
m.put("kineticEnergyG", Float.$valueOf(g));
} else if (key.equals("VIRIAL DENSITY")) {
v = this.parseFloatStr(value.substring(0, 12));
m.put("virialDensityV", Float.$valueOf(v));
m.put("ratioVG", Float.$valueOf(Math.abs(v) / g));
m.put("energyDensityH", Float.$valueOf(g + v));
m.put("ratioHRho", Float.$valueOf((g + v) / rho));
} else if (key.equals("EIGENVALUES (L1 L2 L3)")) {
var e1 = this.parseFloatStr(value.substring(0, 12));
var e2 = this.parseFloatStr(value.substring(12, 24));
var e3 = this.parseFloatStr(value.substring(24, 36));
evalues =  Clazz.newFloatArray(-1, [e1, e2, e3]);
m.put("eigenvalues", evalues);
m.put("ellipticity", Float.$valueOf(e1 / e2 - 1));
m.put("anisotropy", Float.$valueOf(e3 - Math.abs(e1 + e2) / 2));
} else if (key.equals("EIGENVECTORS")) {
value = value + this.rd().substring(33) + this.rd().substring(33);
var ev =  Clazz.newDoubleArray (3, 3, 0);
for (var ei = 0, p = 0; ei < 3; ei++) {
for (var ej = 0; ej < 3; ej++, p += 12) {
ev[ej][ei] = this.parseFloatStr(value.substring(p, p + 12));
}
}
var evectors =  new Array(3);
evectors[0] = JU.P3.new3(ev[0][0], ev[0][1], ev[0][2]);
evectors[1] = JU.P3.new3(ev[1][0], ev[1][1], ev[1][2]);
evectors[2] = JU.P3.new3(ev[2][0], ev[2][1], ev[2][2]);
System.out.println("evpts " + evectors[0] + " " + evectors[1] + " " + evectors[2]);
m.put("eigenvectors", evectors);
var t =  new JU.Tensor().setFromEigenVectors(evectors, evalues, "cp", id, null);
m.put("tensor", t);
}}this.line = null;
}
});
Clazz.defineMethod(c$, "newLattice", 
function(isConv){
this.lstCoords = null;
this.readLatticeParams(!isConv);
this.symops.clear();
if (!isConv) this.primitiveToCrystal = null;
if (!this.directLatticeVectorsFirst) this.directLatticeVectors = null;
}, "~B");
Clazz.defineMethod(c$, "addModel", 
function(){
if (this.getLastConventional) {
return true;
}if (!this.doGetModel(++this.modelNumber, null)) {
this.lstCoords = null;
this.checkLastModel();
if (this.asc.iSet >= 0) this.asc.removeAtomSet(this.asc.iSet);
return false;
}this.processCoordLines();
return true;
});
Clazz.defineMethod(c$, "readSymmetryOperators", 
function(){
this.symops.clear();
this.rd();
this.f16[15] = 1;
while (this.rd() != null && this.line.length > 0 && this.line.indexOf("END") < 0) {
if (this.line.indexOf("V INV") >= 0) continue;
this.fillFloatArray(this.line, 0, this.f14);
if (Float.isNaN(this.f14[0])) break;
for (var i = 0; i < 12; i++) this.f16[i] = this.f14[J.adapter.readers.xtal.CrystalReader.smap[i]];

JU.Logger.info("CrystalReader: " + this.line);
if (this.isSlab || this.isPolymer) continue;
var m4 = JU.M4.newA16(this.f16);
var xyz = JS.SymmetryOperation.getXYZFromMatrix(m4, false, false, false);
if (xyz.indexOf("0y") >= 0 || xyz.indexOf("0z") >= 0) {
JU.Logger.error("CrystalReader: Symmetry operator could not be created for " + xyz);
} else {
this.symops.addLast(xyz);
JU.Logger.info("CrystalReader: state=" + this.state + " Symmop " + this.symops.size() + ": " + xyz);
}}
});
Clazz.overrideMethod(c$, "finalizeSubclassReader", 
function(){
this.asc.setInfo("symmetryType", (this.isSlab ? "2D - SLAB" : this.isPolymer ? "1D - POLYMER" : this.type));
this.processCoordLines();
if (this.energy != null) this.setEnergy();
this.finalizeReaderASCR();
this.asc.checkNoEmptyModel();
if (this.htCriticalPoints != null) {
var note = "";
var list;
list = this.htCriticalPoints.get("nuclei");
if (list != null) note += "\n _M.criticalPoints.nuclei.length = " + list.size();
list = this.htCriticalPoints.get("bonds");
if (list != null) note += "\n _M.criticalPoints.bonds.length = " + list.size();
list = this.htCriticalPoints.get("rings");
if (list != null) note += "\n _M.criticalPoints.rings.length = " + list.size();
list = this.htCriticalPoints.get("cages");
if (list != null) note += "\n _M.criticalPoints.cages.length = " + list.size();
note += "\n Use MACRO TOPOND for TOPOND functions.";
this.addJmolScript("set drawHover");
this.appendLoadNote(note);
this.setLoadNote();
}});
Clazz.defineMethod(c$, "getDirect", 
function(){
this.directLatticeVectors = this.read3Vectors(this.line.indexOf("(BOHR") >= 0);
if (!this.iHaveUnitCell) this.directLatticeVectorsFirst = true;
});
Clazz.defineMethod(c$, "setUnitCellOrientation", 
function(){
if (this.directLatticeVectors == null) return;
var a =  new JU.V3();
var b =  new JU.V3();
if (this.isPrimitive) {
a = this.directLatticeVectors[0];
b = this.directLatticeVectors[1];
} else {
if (this.primitiveToCrystal == null) return;
var mp =  new JU.M3();
mp.setColumnV(0, this.directLatticeVectors[0]);
mp.setColumnV(1, this.directLatticeVectors[1]);
mp.setColumnV(2, this.directLatticeVectors[2]);
mp.mul(this.primitiveToCrystal);
a =  new JU.V3();
b =  new JU.V3();
mp.getColumnV(0, a);
mp.getColumnV(1, b);
}this.matUnitCellOrientation = JU.Quat.getQuaternionFrame( new JU.P3(), a, b).getMatrix();
JU.Logger.info("oriented unit cell is in model " + this.asc.atomSetCount);
});
Clazz.defineMethod(c$, "readPrimitiveLatticeVectors", 
function(){
this.primitiveToCrystal = JU.M3.newA9(this.fillFloatArray(null, 0,  Clazz.newFloatArray (9, 0)));
});
Clazz.defineMethod(c$, "readHeader", 
function(){
this.havePrimitiveMapping = true;
this.discardLinesUntilContains("*******************************************************************************");
this.readLines(2);
this.isVersion3 = (this.line.indexOf("CRYSTAL03") >= 0);
this.discardLinesUntilContains("EEEEEEEEEE");
this.rd();
var name;
if (this.line.length == 0) {
this.discardLinesUntilContains("*********");
name = this.rd().trim();
} else {
name = this.line.trim();
this.rd();
}this.type = this.rd().trim();
var pt = this.type.indexOf("- PROPERTIES");
if (pt >= 0) {
this.isProperties = true;
this.type = this.type.substring(0, pt).trim();
}this.asc.setCollectionName(name + (!this.isProperties && this.desiredModelNumber == 0 ? " (optimized)" : ""));
if (this.type.indexOf("GEOMETRY INPUT FROM EXTERNAL FILE") >= 0) {
this.firstLine = this.line;
this.type = this.rd().trim();
}this.isPolymer = (this.type.equals("1D - POLYMER") || this.type.equals("POLYMER CALCULATION"));
this.isSlab = (this.type.equals("2D - SLAB") || this.type.equals("SLAB CALCULATION"));
if ((this.isPolymer || this.isSlab) && !this.isPrimitive) {
JU.Logger.error("Cannot use FILTER \"conventional\" with POLYMER or SLAB");
this.isPrimitive = true;
}this.asc.setInfo("unitCellType", (this.isPrimitive ? "primitive" : "conventional"));
if (this.type.indexOf("MOLECULAR") >= 0) {
this.isMolecular = this.doProcessLines = true;
this.rd();
this.asc.setInfo("molecularCalculationPointGroup", this.line.substring(this.line.indexOf(" OR ") + 4).trim());
return false;
}this.discardLinesUntilContains2("SPACE GROUP", "****");
pt = this.line.indexOf(":");
if (pt >= 0 && !this.isPrimitive) this.spaceGroupName = this.line.substring(pt + 1).trim();
this.doApplySymmetry = this.isProperties;
return !this.isProperties;
});
Clazz.defineMethod(c$, "readLatticeParams", 
function(isPrimitive){
var f = (this.line.indexOf("(BOHR") >= 0 ? 0.5291772 : 1);
if (isPrimitive) this.newAtomSet();
this.primitiveVolume = 0;
this.primitiveDensity = 0;
if (this.isPolymer && !isPrimitive && this.line.indexOf("BOHR =") < 0) {
this.setUnitCell(this.parseFloatStr(this.line.substring(this.line.indexOf("CELL") + 4)) * f, -1, -1, 90, 90, 90);
} else {
while (this.rd().indexOf("GAMMA") < 0) if (this.line.indexOf("VOLUME=") >= 0) {
this.primitiveVolume = this.parseFloatStr(this.line.substring(43));
this.primitiveDensity = this.parseFloatStr(this.line.substring(66));
}
var tokens = JU.PT.getTokens(this.rd());
var a = this.parseFloatStr(tokens[0]);
var b = this.parseFloatStr(tokens[1]);
if (!this.isSlab && !this.isPolymer && tokens.length == 7) {
this.primitiveVolume = this.parseFloatStr(tokens[6]);
if (Math.abs(this.primitiveVolume - a * b) < 0.1) {
this.isSlab = true;
}}if (this.isSlab) {
if (isPrimitive) this.setUnitCell(a * f, b * f, -1, this.parseFloatStr(tokens[3]), this.parseFloatStr(tokens[4]), this.parseFloatStr(tokens[5]));
 else this.setUnitCell(a * f, b * f, -1, 90, 90, this.parseFloatStr(tokens[2]));
} else if (this.isPolymer) {
this.setUnitCell(a, -1, -1, this.parseFloatStr(tokens[3]), this.parseFloatStr(tokens[4]), this.parseFloatStr(tokens[5]));
} else {
this.setUnitCell(a * f, b * f, this.parseFloatStr(tokens[2]) * f, this.parseFloatStr(tokens[3]), this.parseFloatStr(tokens[4]), this.parseFloatStr(tokens[5]));
}}}, "~B");
Clazz.defineMethod(c$, "getAtomIndexFromPrimitiveIndex", 
function(iPrim){
return (this.primitiveToIndex == null ? iPrim : this.primitiveToIndex[iPrim]);
}, "~N");
Clazz.defineMethod(c$, "readAtoms", 
function(){
if (this.isMolecular) this.newAtomSet();
this.lstCoords = null;
while (this.rd() != null && this.line.indexOf("*") < 0) {
if (this.line.indexOf("X(ANGSTROM") >= 0) {
this.setFractionalCoordinates(false);
this.isMolecular = true;
}}
var i = this.atomIndexLast;
var doNormalizePrimitive = false;
this.atomIndexLast = this.asc.ac;
var isFractional = this.iHaveFractionalCoordinates;
if (!isFractional) {
this.setUnitCellOrientation();
if (this.matUnitCellOrientation != null) this.getSymmetry().initializeOrientation(this.matUnitCellOrientation);
}while (this.rd() != null && this.line.length > 0 && this.line.indexOf(this.isPrimitive ? "*" : "=") < 0) {
var atom = this.asc.addNewAtom();
var tokens = this.getTokens();
var pt = (this.isProperties ? 1 : 2);
atom.elementSymbol = J.adapter.smarter.AtomSetCollectionReader.getElementSymbol(this.getAtomicNumber(tokens[pt++]));
atom.atomName = J.adapter.readers.xtal.CrystalReader.fixAtomName(tokens[pt++]);
if (this.isProperties) pt++;
var x = this.parseFloatStr(tokens[pt++]);
var y = this.parseFloatStr(tokens[pt++]);
var z = this.parseFloatStr(tokens[pt]);
if (this.haveCharges) atom.partialCharge = this.asc.atoms[i++].partialCharge;
if (isFractional && !this.isProperties) {
if (x < 0 && (this.isPolymer || this.isSlab || doNormalizePrimitive)) x += 1;
if (y < 0 && (this.isSlab || doNormalizePrimitive)) y += 1;
if (z < 0 && doNormalizePrimitive) z += 1;
}this.setAtomCoordXYZ(atom, x, y, z);
}
this.ac = this.asc.ac - this.atomIndexLast;
return true;
});
c$.fixAtomName = Clazz.defineMethod(c$, "fixAtomName", 
function(s){
return (s.length > 1 && JU.PT.isLetter(s.charAt(1)) ? s.substring(0, 1) + Character.toLowerCase(s.charAt(1)) + s.substring(2) : s);
}, "~S");
Clazz.defineMethod(c$, "getAtomicNumber", 
function(token){
return this.parseIntStr(token) % 100;
}, "~S");
Clazz.defineMethod(c$, "readCoordLines", 
function(){
var atom = (this.inputOnly ? " ATOM" : "  ATOM");
if (this.line.indexOf(atom) < 0) this.discardLinesUntilContains(atom);
this.lstCoords =  new JU.Lst();
while (this.rd() != null && this.line.length > 0) if (this.line.indexOf("****") < 0) this.lstCoords.addLast(this.line);

});
Clazz.defineMethod(c$, "processCoordLines", 
function(){
if (this.lstCoords == null) return;
this.ac = this.lstCoords.size();
var irreducible = null;
for (var i = 0; i < this.ac; i++) {
var atom = this.asc.addNewAtom();
var tokens = JU.PT.getTokens(this.lstCoords.get(i));
atom.atomSerial = this.parseIntStr(tokens[0]);
var atomicNumber;
var offset;
switch (tokens.length) {
case 8:
case 7:
atomicNumber = this.getAtomicNumber(tokens[2]);
offset = 4;
if (i == 0) irreducible =  Clazz.newFloatArray (this.ac, 0);
if (tokens[1].equals("T")) irreducible[i] = 1;
break;
default:
atomicNumber = this.getAtomicNumber(tokens[1]);
offset = 2;
break;
}
var x = this.parseFloatStr(tokens[offset++]) + this.ptOriginShift.x;
var y = this.parseFloatStr(tokens[offset++]) + this.ptOriginShift.y;
var z = this.parseFloatStr(tokens[offset]) + this.ptOriginShift.z;
this.setAtomCoordXYZ(atom, x, y, z);
atom.elementSymbol = J.adapter.smarter.AtomSetCollectionReader.getElementSymbol(atomicNumber);
}
this.lstCoords = null;
if (irreducible != null) {
this.asc.setAtomProperties("irreducible", irreducible, -1, false);
}if (this.primitiveVolume > 0) {
this.asc.setAtomSetModelProperty("volumePrimitive", JU.DF.formatDecimal(this.primitiveVolume, 3));
this.asc.setModelInfoForSet("primitiveVolume", Float.$valueOf(this.primitiveVolume), this.asc.iSet);
}if (this.primitiveDensity > 0) {
this.asc.setAtomSetModelProperty("densityPrimitive", JU.DF.formatDecimal(this.primitiveDensity, 3));
this.asc.setModelInfoForSet("primitiveDensity", Float.$valueOf(this.primitiveDensity), this.asc.iSet);
}});
Clazz.overrideMethod(c$, "applySymmetryAndSetTrajectory", 
function(){
this.setUnitCellOrientation();
var m4p2c;
var m4c2p;
if (this.primitiveToCrystal != null) {
this.asc.setModelInfoForSet("primitiveToCrystal", this.primitiveToCrystal, this.asc.iSet);
m4p2c =  new JU.M4();
m4p2c.setRotationScale(this.primitiveToCrystal);
m4p2c.m33 = 1;
this.asc.setModelInfoForSet("mat4PrimitiveToCrystal", m4p2c, this.asc.iSet);
m4c2p = JU.M4.newM4(m4p2c);
m4c2p.invert();
this.asc.setModelInfoForSet("mat4CrystalToPrimitive", m4c2p, this.asc.iSet);
if (this.symops.size() > 0) {
this.asc.setModelInfoForSet("fileSymmetryOperations", this.symops.clone(), this.asc.iSet);
}}this.iHaveSymmetryOperators = false;
this.applySymTrajASCR();
});
Clazz.defineMethod(c$, "newAtomSet", 
function(){
if (this.ac > 0 && this.asc.ac > 0) {
this.applySymmetryAndSetTrajectory();
this.asc.newAtomSet();
}if (this.spaceGroupName != null) {
this.setSpaceGroupName(this.spaceGroupName);
}this.ac = 0;
});
Clazz.defineMethod(c$, "setEnergy", 
function(){
this.asc.setAtomSetEnergy("" + this.energy, this.energy.floatValue());
this.asc.setCurrentModelInfo("Energy", this.energy);
this.asc.setInfo("Energy", this.energy);
this.asc.setAtomSetName("Energy = " + this.energy + " Hartree");
});
Clazz.defineMethod(c$, "readPartialCharges", 
function(){
if (this.haveCharges || this.asc.ac == 0) return true;
this.haveCharges = true;
this.readLines(3);
var atoms = this.asc.atoms;
var i0 = this.asc.getLastAtomSetAtomIndex();
var iPrim = 0;
while (this.rd() != null && this.line.length > 3) if (this.line.charAt(3) != ' ') {
var iConv = this.getAtomIndexFromPrimitiveIndex(iPrim);
if (iConv >= 0) atoms[i0 + iConv].partialCharge = this.parseFloatRange(this.line, 9, 11) - this.parseFloatRange(this.line, 12, 18);
iPrim++;
}
return true;
});
Clazz.defineMethod(c$, "readTotalAtomicCharges", 
function(){
var data =  new JU.SB();
while (this.rd() != null && this.line.indexOf("T") < 0) data.append(this.line);

var tokens = JU.PT.getTokens(data.toString());
var charges =  Clazz.newFloatArray (tokens.length, 0);
if (this.nuclearCharges == null || this.nuclearCharges.length != charges.length) this.nuclearCharges = charges;
if (this.asc.ac == 0) return true;
var atoms = this.asc.atoms;
var i0 = this.asc.getLastAtomSetAtomIndex();
for (var i = 0; i < charges.length; i++) {
var iConv = this.getAtomIndexFromPrimitiveIndex(i);
if (iConv >= 0) {
charges[i] = this.parseFloatStr(tokens[i]);
atoms[i0 + iConv].partialCharge = this.nuclearCharges[i] - charges[i];
}}
return true;
});
Clazz.defineMethod(c$, "readFreqFragments", 
function(){
var numAtomsFrag = this.parseIntRange(this.line, 39, 44);
if (numAtomsFrag < 0) return;
this.atomFrag =  Clazz.newIntArray (numAtomsFrag, 0);
var Sfrag = "";
while (this.rd() != null && this.line.indexOf("(") >= 0) Sfrag += this.line;

Sfrag = JU.PT.rep(Sfrag, "(", " ");
Sfrag = JU.PT.rep(Sfrag, ")", " ");
var tokens = JU.PT.getTokens(Sfrag);
for (var i = 0, pos = 0; i < numAtomsFrag; i++, pos += 3) this.atomFrag[i] = this.getAtomIndexFromPrimitiveIndex(this.parseIntStr(tokens[pos]) - 1);

java.util.Arrays.sort(this.atomFrag);
});
Clazz.defineMethod(c$, "readFrequencies", 
function(){
this.getLastConventional = false;
this.addModel();
this.energy = null;
this.discardLinesUntilContains("MODES");
var haveIntensities = (this.line.indexOf("INTENS") >= 0);
this.rd();
var vData =  new JU.Lst();
var freqAtomCount = (this.atomFrag == null ? this.ac : 0);
while (this.rd() != null && this.line.length > 0) {
var i0 = this.parseIntRange(this.line, 1, 5);
var i1 = this.parseIntRange(this.line, 6, 10);
var irrep = (this.isLongMode ? this.line.substring(48, 51) : this.line.substring(49, 52)).trim();
var intens = (!haveIntensities ? "not available" : (this.isLongMode ? this.line.substring(53, 61) : this.line.substring(59, 69).$replace(')', ' ')).trim());
var irActivity = (this.isLongMode ? "A" : this.line.substring(55, 58).trim());
var ramanActivity = (this.isLongMode ? "I" : this.line.substring(71, 73).trim());
var data =  Clazz.newArray(-1, [irrep, intens, irActivity, ramanActivity]);
for (var i = i0; i <= i1; i++) vData.addLast(data);

}
var test = (this.isLongMode ? "LO MODES FOR IRREP" : this.isVersion3 ? "THE CORRESPONDING MODES" : "NORMAL MODES NORMALIZED TO CLASSICAL AMPLITUDES");
this.rd();
var ramanData = null;
if (this.line.indexOf("<RAMAN>") >= 0) ramanData = this.readRaman(null);
if (!this.line.contains(test)) this.discardLinesUntilContains(test);
this.rd();
var modelAtomCount = -1;
while (this.rd() != null && this.line.startsWith(" FREQ(CM**-1)")) {
var tokens = JU.PT.getTokens(this.line.substring(15));
var frequencies =  Clazz.newFloatArray (tokens.length, 0);
var frequencyCount = frequencies.length;
for (var i = 0; i < frequencyCount; i++) {
frequencies[i] = this.parseFloatStr(tokens[i]);
if (this.debugging) JU.Logger.debug((this.vibrationNumber + i) + " frequency=" + frequencies[i]);
}
var ignore =  Clazz.newBooleanArray(frequencyCount, false);
var iAtom0 = 0;
var nData = vData.size();
var isFirst = true;
for (var i = 0; i < frequencyCount; i++) {
tokens = vData.get(this.vibrationNumber % nData);
ignore[i] = (!this.doGetVibration(++this.vibrationNumber) || tokens == null);
if (ignore[i]) continue;
this.applySymmetryAndSetTrajectory();
if (isFirst) {
modelAtomCount = this.asc.getLastAtomSetAtomCount();
}this.cloneLastAtomSet(this.ac, null);
if (isFirst) {
iAtom0 = this.asc.getLastAtomSetAtomIndex();
isFirst = false;
}this.setFreqValue(frequencies[i], tokens);
}
this.rd();
this.fillFrequencyData(iAtom0, freqAtomCount, modelAtomCount, ignore, false, 14, 10, this.atomFrag, 0, null);
this.rd();
}
if (ramanData != null) this.readRaman(ramanData);
});
Clazz.defineMethod(c$, "setFreqValue", 
function(freq, data){
var activity = "IR: " + data[2] + ", Ram.: " + data[3];
this.asc.setAtomSetFrequency(this.vibrationNumber, null, activity, "" + freq, null);
this.asc.setAtomSetModelProperty("IRintensity", data[1] + " km/Mole");
this.asc.setAtomSetModelProperty("vibrationalSymmetry", data[0]);
this.asc.setAtomSetModelProperty("IRactivity", data[2]);
this.asc.setAtomSetModelProperty("Ramanactivity", data[3]);
this.asc.setAtomSetName((this.isLongMode ? "LO " : "") + data[0] + " " + JU.DF.formatDecimal(freq, 2) + " cm-1 (" + JU.DF.formatDecimal(Float.parseFloat(data[1]), 0) + " km/Mole), " + activity);
}, "~N,~A");
Clazz.defineMethod(c$, "readRaman", 
function(ramanData){
if (ramanData == null) {
ramanData =  new JU.Lst();
this.rd();
while (this.rd() != null && !this.line.contains("<RAMAN>")) ramanData.addLast(this.line);

return ramanData;
}var info;
var i = 0;
var n = ramanData.size();
for (; i < n; i++) {
this.line = ramanData.get(i);
if (this.line.contains("---")) break;
}
for (++i; i < n; i++) {
this.line = ramanData.get(i);
if (this.line.length == 0) break;
var mode1 = this.parseIntRange(this.line, 1, 5);
var mode2 = this.parseIntRange(this.line, 6, 10);
var i_tot = this.parseFloatRange(this.line, 30, 40);
var i_par = this.parseFloatRange(this.line, 40, 50);
var i_perp = this.parseFloatRange(this.line, 50, 60);
for (var i0 = 0, mode = mode1; mode <= mode2; mode++) {
var imodel = this.getModelForMode(i0, mode);
if (imodel < 0) continue;
i0 = imodel + 1;
info = this.asc.getAtomSetAuxiliaryInfoValue(imodel, "ramanInfo");
if (info == null) this.asc.setModelInfoForSet("ramanInfo", info =  new java.util.Hashtable(), imodel);
info.put("isotropicIntensities",  Clazz.newFloatArray(-1, [i_tot, i_par, i_perp]));
}
}
for (; i < n; i++) {
this.line = ramanData.get(i);
if (this.line.contains("---")) break;
}
for (++i; i < n; i++) {
this.line = ramanData.get(i);
if (this.line.length == 0) break;
var mode1 = this.parseIntRange(this.line, 1, 5);
var mode2 = this.parseIntRange(this.line, 6, 10);
var i_xx = this.parseFloatRange(this.line, 30, 38);
var i_xy = this.parseFloatRange(this.line, 38, 46);
var i_xz = this.parseFloatRange(this.line, 46, 54);
var i_yy = this.parseFloatRange(this.line, 54, 62);
var i_yz = this.parseFloatRange(this.line, 62, 70);
var i_zz = this.parseFloatRange(this.line, 70, 78);
for (var i0 = 0, mode = mode1; mode <= mode2; mode++) {
var imodel = this.getModelForMode(i0, mode);
if (imodel < 0) continue;
i0 = imodel + 1;
var a =  Clazz.newArray(-1, [ Clazz.newDoubleArray(-1, [i_xx, i_xy, i_xz]),  Clazz.newDoubleArray(-1, [i_xy, i_yy, i_yz]),  Clazz.newDoubleArray(-1, [i_xz, i_yz, i_zz])]);
this.asc.atoms[this.asc.getAtomSetAtomIndex(imodel)].addTensor( new JU.Tensor().setFromAsymmetricTensor(a, "raman", "mode" + mode), "raman", false);
}
}
this.appendLoadNote("Ellipsoids set \"raman\": Raman tensors");
return null;
}, "JU.Lst");
Clazz.defineMethod(c$, "getModelForMode", 
function(i0, mode){
var n = this.asc.atomSetCount;
for (var i = i0; i < n; i++) {
var imode = this.asc.getAtomSetAuxiliaryInfoValue(i, "vibrationalMode");
var m = (imode == null ? 0 : imode.intValue());
if (m == mode) return i;
}
return -1;
}, "~N,~N");
Clazz.defineMethod(c$, "readGradient", 
function(){
var key = null;
while (this.line != null) {
var tokens = this.getTokens();
if (this.line.indexOf("MAX GRAD") >= 0) key = "maxGradient";
 else if (this.line.indexOf("RMS GRAD") >= 0) key = "rmsGradient";
 else if (this.line.indexOf("MAX DISP") >= 0) key = "maxDisplacement";
 else if (this.line.indexOf("RMS DISP") >= 0) key = "rmsDisplacement";
 else break;
if (this.asc.ac > 0) this.asc.setAtomSetModelProperty(key, tokens[2]);
this.rd();
}
return true;
});
Clazz.defineMethod(c$, "readData", 
function(name, nfields){
this.processCoordLines();
var f =  Clazz.newFloatArray (this.ac, 0);
for (var i = 0; i < this.ac; i++) f[i] = 0;

var data = "";
while (this.rd() != null && (this.line.length < 4 || JU.PT.isDigit(this.line.charAt(3)))) data += this.line;

data = JU.PT.rep(data, "-", " -");
var tokens = JU.PT.getTokens(data);
for (var i = 0, pt = nfields - 1; i < this.ac; i++, pt += nfields) {
var iConv = this.getAtomIndexFromPrimitiveIndex(i);
if (iConv >= 0) f[iConv] = this.parseFloatStr(tokens[pt]);
}
this.asc.setAtomProperties(name, f, -1, false);
return true;
}, "~S,~N");
Clazz.defineMethod(c$, "getQuadrupoleTensors", 
function(){
this.readLines(6);
var atoms = this.asc.atoms;
var vectors =  new Array(3);
if (this.directLatticeVectors == null) vectors =  Clazz.newArray(-1, [JU.V3.new3(1, 0, 0), JU.V3.new3(0, 1, 0), JU.V3.new3(0, 0, 1)]);
 else for (var i = 0; i < 3; i++) {
vectors[i] = JU.V3.newV(this.directLatticeVectors[i]);
vectors[i].normalize();
}
while (this.rd() != null && this.line.startsWith(" *** ATOM")) {
var tokens = this.getTokens();
var index = this.parseIntStr(tokens[3]) - 1;
tokens = JU.PT.getTokens(this.readLines(3));
atoms[index].addTensor( new JU.Tensor().setFromEigenVectors(vectors,  Clazz.newFloatArray(-1, [this.parseFloatStr(tokens[1]), this.parseFloatStr(tokens[3]), this.parseFloatStr(tokens[5])]), "quadrupole", atoms[index].atomName, null), null, false);
this.rd();
}
this.appendLoadNote("Ellipsoids set \"quadrupole\": Quadrupole tensors");
return true;
});
Clazz.defineMethod(c$, "readBornChargeTensors", 
function(){
this.processCoordLines();
this.rd();
var atoms = this.asc.atoms;
while (this.rd().startsWith(" ATOM")) {
var index = this.parseIntAt(this.line, 5) - 1;
var atom = atoms[index];
this.readLines(2);
atom.addTensor( new JU.Tensor().setFromAsymmetricTensor(this.fill3x3(null, -3), "charge", atom.elementSymbol + (index + 1)), null, false);
this.rd();
}
this.appendLoadNote("Ellipsoids set \"charge\": Born charge tensors");
return false;
});
c$.crtypes =  Clazz.newArray(-1, ["??", "nuclei", "bonds", "rings", "cages"]);
c$.smap =  Clazz.newIntArray(-1, [2, 3, 4, 11, 5, 6, 7, 12, 8, 9, 10, 13]);
});
;//5.0.1-v7 Mon Aug 17 10:07:10 MDT 2026
