Clazz.declarePackage ("JS");
Clazz.load (["JU.P3"], "JS.SpaceGroupFinder", ["java.lang.Float", "JU.BS", "$.Lst", "$.M3", "JS.SpaceGroup", "$.SymmetryOperation", "JU.BSUtil", "$.SimpleUnitCell", "JV.FileManager"], function () {
c$ = Clazz.decorateAsClass (function () {
this.SLOP = 0.001;
this.atoms = null;
this.nAtoms = 0;
this.pt = null;
if (!Clazz.isClassDefined ("JS.SpaceGroupFinder.SGAtom")) {
JS.SpaceGroupFinder.$SpaceGroupFinder$SGAtom$ ();
}
Clazz.instantialize (this, arguments);
}, JS, "SpaceGroupFinder");
Clazz.prepareFields (c$, function () {
this.pt =  new JU.P3 ();
});
Clazz.makeConstructor (c$, 
function () {
});
Clazz.defineMethod (c$, "findSpaceGroup", 
function (vwr, atoms0, uc, asString) {
var cartesians = vwr.ms.at;
var isg = 0;
var bsAtoms = JU.BSUtil.copy (atoms0);
var bsGroups =  new JU.BS ();
var targets = JU.BS.newN (this.nAtoms);
var bsOps =  new JU.BS ();
this.nAtoms = bsAtoms.cardinality ();
var n = 0;
var nChecked = 0;
var scaling = JU.P3.new3 (1, 1, 1);
try {
if (JS.SpaceGroupFinder.bsOpGroups == null) JS.SpaceGroupFinder.loadData (vwr, this);
uc = uc.getUnitCellMultiplied ();
bsGroups.setBits (0, JS.SpaceGroupFinder.GROUP_COUNT);
bsOps.setBits (1, JS.SpaceGroupFinder.OP_COUNT);
var withinCell = vwr.ms.getAtoms (1814695966, uc);
var extraAtoms = JU.BSUtil.copy (bsAtoms);
extraAtoms.andNot (withinCell);
var nExtra = extraAtoms.cardinality ();
this.atoms =  new Array (bsAtoms.cardinality ());
System.out.println ("bsAtoms = " + bsAtoms);
for (var p = 0, i = bsAtoms.nextSetBit (0); i >= 0; i = bsAtoms.nextSetBit (i + 1), p++) {
var a = cartesians[i];
var type = a.getAtomicAndIsotopeNumber ();
(this.atoms[p] = Clazz.innerTypeInstance (JS.SpaceGroupFinder.SGAtom, this, null, type, i)).setT (this.toFractional (a, uc));
}
var bsPoints = JU.BSUtil.newBitSet2 (0, this.nAtoms);
var uc0 = uc;
var mtet =  new JU.M3 ();
uc = this.checkTetragonal (vwr, uc, mtet);
if (uc === uc0) {
mtet = null;
} else {
System.out.println ("tetragonoal setting issue detected");
}if (nExtra > 0) {
var packedAtoms =  new JU.BS ();
this.checkPackingAtoms (bsPoints, extraAtoms, 1, packedAtoms);
this.checkPackingAtoms (bsPoints, extraAtoms, 2, packedAtoms);
this.checkPackingAtoms (bsPoints, extraAtoms, 3, packedAtoms);
if (packedAtoms.cardinality () == nExtra) bsPoints.andNot (packedAtoms);
 else bsPoints.clearAll ();
}this.nAtoms = bsPoints.cardinality ();
uc0 = uc;
var isSupercell = false;
if (this.nAtoms > 0) {
for (var i = bsPoints.nextSetBit (0); i >= 0; i = bsPoints.nextSetBit (i + 1)) {
JU.SimpleUnitCell.unitizeDim (3, this.atoms[i]);
}
uc = this.checkSupercell (vwr, uc, bsPoints, 1, scaling);
uc = this.checkSupercell (vwr, uc, bsPoints, 2, scaling);
uc = this.checkSupercell (vwr, uc, bsPoints, 3, scaling);
isSupercell = (uc !== uc0);
if (isSupercell) {
if (scaling.x != 1) System.out.println ("supercell found; a scaled by 1/" + scaling.x);
if (scaling.y != 1) System.out.println ("supercell found; b scaled by 1/" + scaling.y);
if (scaling.z != 1) System.out.println ("supercell found; c scaled by 1/" + scaling.z);
}}n = bsPoints.cardinality ();
bsAtoms =  new JU.BS ();
var newAtoms =  new Array (n);
for (var p = 0, i = bsPoints.nextSetBit (0); i >= 0; i = bsPoints.nextSetBit (i + 1)) {
var a = this.atoms[i];
newAtoms[p++] = a;
if (isSupercell) {
a.setT (this.toFractional (cartesians[a.index], uc));
if (mtet != null) mtet.rotate (a);
}bsAtoms.set (this.atoms[i].index);
}
this.atoms = newAtoms;
this.nAtoms = n;
System.out.println ("bsAtoms(within cell) = " + bsAtoms);
bsPoints.clearAll ();
bsPoints.setBits (0, this.nAtoms);
var bsPoints0 = JU.BS.copy (bsPoints);
var temp1 = JU.BS.newN (JS.SpaceGroupFinder.OP_COUNT);
var targeted = JU.BS.newN (this.nAtoms);
if (this.nAtoms == 0) {
bsGroups.clearBits (1, JS.SpaceGroupFinder.GROUP_COUNT);
bsOps.clearAll ();
}var uncheckedOps = JU.BS.newN (JS.SpaceGroupFinder.OP_COUNT);
var opsChecked = JU.BS.newN (JS.SpaceGroupFinder.OP_COUNT);
opsChecked.set (0);
while (bsGroups.cardinality () > 0 && !bsOps.isEmpty ()) {
System.out.println ("bsGroups = " + bsGroups);
System.out.println ("bsOps = " + bsOps);
var iop = bsOps.nextSetBit (1);
var op = JS.SpaceGroupFinder.getOp (iop);
System.out.println ("Checking operation " + iop + " " + JS.SpaceGroupFinder.opXYZ[iop]);
nChecked++;
var isOK = true;
bsPoints.clearAll ();
bsPoints.or (bsPoints0);
targeted.clearAll ();
for (var i = bsPoints.nextSetBit (0); i >= 0; i = bsPoints.nextSetBit (i + 1)) {
bsPoints.clear (i);
var j = this.findEquiv (op, i, bsPoints, this.pt);
if (j < 0) {
isOK = false;
break;
}if (i != j) targeted.set (Math.max (this.atoms[i].index, this.atoms[j].index));
}
var myGroups = JS.SpaceGroupFinder.bsOpGroups[iop];
bsOps.clear (iop);
opsChecked.set (iop);
if (isOK) {
System.out.println ("OK!");
targets.or (targeted);
bsGroups.and (myGroups);
temp1.setBits (1, JS.SpaceGroupFinder.OP_COUNT);
for (var i = bsGroups.nextSetBit (0); i >= 0; i = bsGroups.nextSetBit (i + 1)) {
temp1.and (JS.SpaceGroupFinder.bsGroupOps[i]);
}
uncheckedOps.or (temp1);
bsOps.andNot (temp1);
} else {
bsGroups.andNot (myGroups);
temp1.clearAll ();
for (var i = bsGroups.nextSetBit (0); i >= 0; i = bsGroups.nextSetBit (i + 1)) {
temp1.or (JS.SpaceGroupFinder.bsGroupOps[i]);
}
bsOps.and (temp1);
}}
n = bsGroups.cardinality ();
isg = bsGroups.nextSetBit (0);
if (n == 1 && !asString) {
uncheckedOps.and (JS.SpaceGroupFinder.bsGroupOps[isg]);
uncheckedOps.andNot (opsChecked);
this.checkBasis (uncheckedOps, bsPoints, targets);
}} catch (e) {
if (Clazz.exceptionOf (e, Exception)) {
e.printStackTrace ();
bsGroups.clearAll ();
} else {
throw e;
}
}
System.out.println ("checked " + nChecked + " operations; now " + n + " " + bsGroups + " " + bsOps);
for (var i = bsGroups.nextSetBit (0); i >= 0; i = bsGroups.nextSetBit (i + 1)) {
System.out.println (JS.SpaceGroup.nameToGroup.get (JS.SpaceGroupFinder.groupNames[i]));
}
if (n != 1) return null;
var sg = JS.SpaceGroup.nameToGroup.get (JS.SpaceGroupFinder.groupNames[isg]);
var name = sg.toString ();
uc.setSpaceGroupName (name);
System.out.println ("found " + name);
if (asString) return name;
var map = sg.dumpInfoObj ();
var basis = JU.BSUtil.copy (bsAtoms);
basis.andNot (targets);
System.out.println ("basis is " + basis);
System.out.println ("unitcell is " + uc.getUnitCellInfo (true));
map.put ("name", name);
map.put ("basis", basis);
map.put ("supercell", scaling);
var params = uc.getUnitCellParams ();
if (Float.isNaN (params[6])) System.arraycopy (params, 0, params =  Clazz.newFloatArray (6, 0), 0, 6);
map.put ("unitcell", params);
return map;
}, "JV.Viewer,JU.BS,J.api.SymmetryInterface,~B");
Clazz.defineMethod (c$, "checkTetragonal", 
 function (vwr, uc, mtet) {
return uc;
}, "JV.Viewer,J.api.SymmetryInterface,JU.M3");
Clazz.defineMethod (c$, "toFractional", 
function (a, uc) {
this.pt.setT (a);
uc.toFractional (this.pt, false);
return this.pt;
}, "JM.Atom,J.api.SymmetryInterface");
c$.getOp = Clazz.defineMethod (c$, "getOp", 
 function (iop) {
var op = JS.SpaceGroupFinder.ops[iop];
if (op == null) {
JS.SpaceGroupFinder.ops[iop] = op =  new JS.SymmetryOperation (null, null, 0, iop, false);
op.setMatrixFromXYZ (JS.SpaceGroupFinder.opXYZ[iop], 0, false);
op.doFinalize ();
}return op;
}, "~N");
Clazz.defineMethod (c$, "checkBasis", 
 function (uncheckedOps, bsPoints, targets) {
var n = uncheckedOps.cardinality ();
if (n == 0) return;
var bs =  new JU.BS ();
bs.or (bsPoints);
System.out.println ("finishing check for basis for " + n + " operations");
for (var iop = uncheckedOps.nextSetBit (0); iop >= 0; iop = uncheckedOps.nextSetBit (iop + 1)) {
if (bs.cardinality () == 0) return;
var op = JS.SpaceGroupFinder.getOp (iop);
for (var i = bs.nextSetBit (0); i >= 0; i = bs.nextSetBit (i + 1)) {
var j = this.findEquiv (op, i, bsPoints, this.pt);
if (i != j) {
j = Math.max (i, j);
targets.set (this.atoms[j].index);
bs.clear (j);
}}
}
}, "JU.BS,JU.BS,JU.BS");
Clazz.defineMethod (c$, "checkPackingAtoms", 
 function (bsPoints, extraAtoms, abc, packedAtoms) {
var nextra = extraAtoms.cardinality ();
if (nextra == 0) return;
var nbase = 0;
var npacked = 0;
var f = 0;
for (var i = bsPoints.nextSetBit (0); i >= 0; i = bsPoints.nextSetBit (i + 1)) {
var a = this.atoms[i];
var isExtra = extraAtoms.get (a.index);
switch (abc) {
case 1:
f = a.x;
break;
case 2:
f = a.y;
break;
case 3:
f = a.z;
break;
}
if (isExtra) {
if (this.approx0 (f)) isExtra = false;
 else f -= 1;
}if (this.approx0 (f)) {
if (isExtra) {
npacked++;
packedAtoms.set (i);
} else {
nbase++;
}}}
if (nbase != npacked) {
bsPoints.clearAll ();
extraAtoms.clearAll ();
}}, "JU.BS,JU.BS,~N,JU.BS");
Clazz.defineMethod (c$, "checkSupercell", 
function (vwr, uc, bsPoints, abc, scaling) {
if (bsPoints.cardinality () == 0) return uc;
var minF = 2147483647;
var maxF = -2147483648;
var counts =  Clazz.newIntArray (101, 0);
for (var i = bsPoints.nextSetBit (0); i >= 0; i = bsPoints.nextSetBit (i + 1)) {
var a = this.atoms[i];
var type = a.type;
var b;
var f;
for (var j = bsPoints.nextSetBit (0); j >= 0; j = bsPoints.nextSetBit (j + 1)) {
if (j == i || (b = this.atoms[j]).type != type) continue;
this.pt.sub2 (b, a);
switch (abc) {
case 1:
if (this.approx0 (f = this.pt.x) || !this.approx0 (this.pt.y) || !this.approx0 (this.pt.z)) continue;
break;
case 2:
if (this.approx0 (f = this.pt.y) || !this.approx0 (this.pt.x) || !this.approx0 (this.pt.z)) continue;
break;
default:
case 3:
if (this.approx0 (f = this.pt.z) || !this.approx0 (this.pt.x) || !this.approx0 (this.pt.y)) continue;
break;
}
var n = this.approxInt (1 / f);
System.out.println (f + " " + n);
if (n == 0 || Clazz.doubleToInt (this.nAtoms / n) != 1 * this.nAtoms / n || n > 100) continue;
if (n > maxF) maxF = n;
if (n < minF) minF = n;
counts[n]++;
}
}
var n = maxF;
while (n >= minF) {
if (counts[n] > 0 && counts[n] == Clazz.doubleToInt ((n - 1) * this.nAtoms / n)) {
break;
}--n;
}
if (n < minF) return uc;
var oabc = uc.getUnitCellVectors ();
oabc[abc].scale (1 / n);
switch (abc) {
case 1:
scaling.x = n;
break;
case 2:
scaling.y = n;
break;
case 3:
scaling.z = n;
break;
}
uc = vwr.getSymTemp ().getUnitCell (oabc, false, "scaled");
var f = 0;
for (var i = bsPoints.nextSetBit (0); i >= 0; i = bsPoints.nextSetBit (i + 1)) {
switch (abc) {
case 1:
f = this.approxInt (n * this.atoms[i].x);
break;
case 2:
f = this.approxInt (n * this.atoms[i].y);
break;
case 3:
f = this.approxInt (n * this.atoms[i].x);
break;
}
if (f != 0) {
this.atoms[i] = null;
bsPoints.clear (i);
}}
this.nAtoms = bsPoints.cardinality ();
return uc;
}, "JV.Viewer,J.api.SymmetryInterface,JU.BS,~N,JU.P3");
Clazz.defineMethod (c$, "approx0", 
 function (f) {
return (Math.abs (f) < this.SLOP);
}, "~N");
Clazz.defineMethod (c$, "approxInt", 
 function (finv) {
var i = Clazz.floatToInt (finv + this.SLOP);
return (Math.abs (finv - i) < this.SLOP ? i : 0);
}, "~N");
Clazz.defineMethod (c$, "findEquiv", 
 function (op, i, bsPoints, pt) {
var a = this.atoms[i];
pt.setT (a);
op.rotTrans (pt);
JU.SimpleUnitCell.unitizeDim (3, pt);
if (pt.distanceSquared (a) == 0) {
return i;
}var type = a.type;
for (var j = this.nAtoms; --j >= 0; ) {
var b = this.atoms[j];
var d = b.distanceSquared (pt);
if (d < 0.001) {
bsPoints.clear (j);
return (b.type == type ? j : -1);
}}
return -1;
}, "JS.SymmetryOperation,~N,JU.BS,JU.P3");
c$.main = Clazz.defineMethod (c$, "main", 
function (args) {
if (JS.SpaceGroupFinder.loadData (null,  new JS.SpaceGroupFinder ())) System.out.println ("OK");
}, "~A");
c$.loadData = Clazz.defineMethod (c$, "loadData", 
 function (vwr, me) {
try {
JS.SpaceGroupFinder.groupNames = JS.SpaceGroupFinder.getList (vwr, me, null, "sggroups_ordered.txt");
JS.SpaceGroupFinder.GROUP_COUNT = JS.SpaceGroupFinder.groupNames.length;
JS.SpaceGroupFinder.opXYZ = JS.SpaceGroupFinder.getList (vwr, me, null, "sgops_ordered.txt");
JS.SpaceGroupFinder.OP_COUNT = JS.SpaceGroupFinder.opXYZ.length;
var map = JS.SpaceGroupFinder.getList (vwr, me,  new Array (JS.SpaceGroupFinder.OP_COUNT), "sgmap.txt");
JS.SpaceGroupFinder.bsGroupOps =  new Array (JS.SpaceGroupFinder.GROUP_COUNT);
JS.SpaceGroupFinder.bsOpGroups =  new Array (JS.SpaceGroupFinder.OP_COUNT);
for (var j = 0; j < JS.SpaceGroupFinder.GROUP_COUNT; j++) JS.SpaceGroupFinder.bsGroupOps[j] = JU.BS.newN (JS.SpaceGroupFinder.OP_COUNT);

for (var i = 0; i < JS.SpaceGroupFinder.OP_COUNT; i++) {
var m = map[i];
JS.SpaceGroupFinder.bsOpGroups[i] = JU.BS.newN (JS.SpaceGroupFinder.GROUP_COUNT);
for (var j = 0; j < JS.SpaceGroupFinder.GROUP_COUNT; j++) {
if (m.charAt (j) == '1') {
JS.SpaceGroupFinder.bsGroupOps[j].set (i);
JS.SpaceGroupFinder.bsOpGroups[i].set (j);
}}
}
JS.SpaceGroupFinder.ops =  new Array (JS.SpaceGroupFinder.OP_COUNT);
return true;
} catch (e) {
if (Clazz.exceptionOf (e, Exception)) {
e.printStackTrace ();
return false;
} else {
throw e;
}
} finally {
if (JS.SpaceGroupFinder.rdr != null) try {
JS.SpaceGroupFinder.rdr.close ();
} catch (e) {
if (Clazz.exceptionOf (e, java.io.IOException)) {
} else {
throw e;
}
}
}
}, "JV.Viewer,~O");
c$.getList = Clazz.defineMethod (c$, "getList", 
 function (vwr, me, list, fileName) {
JS.SpaceGroupFinder.rdr = JV.FileManager.getBufferedReaderForResource (vwr, me, "J/symmetry/", "sg/" + fileName);
if (list == null) {
var l =  new JU.Lst ();
var line;
while ((line = JS.SpaceGroupFinder.rdr.readLine ()) != null) {
if (line.length > 0) {
l.addLast (line);
}}
l.toArray (list =  new Array (l.size ()));
} else {
for (var i = 0; i < list.length; i++) list[i] = JS.SpaceGroupFinder.rdr.readLine ();

}JS.SpaceGroupFinder.rdr.close ();
return list;
}, "JV.Viewer,~O,~A,~S");
c$.$SpaceGroupFinder$SGAtom$ = function () {
Clazz.pu$h(self.c$);
c$ = Clazz.decorateAsClass (function () {
Clazz.prepareCallback (this, arguments);
this.type = 0;
this.index = 0;
Clazz.instantialize (this, arguments);
}, JS.SpaceGroupFinder, "SGAtom", JU.P3);
Clazz.makeConstructor (c$, 
function (a, b) {
Clazz.superConstructor (this, JS.SpaceGroupFinder.SGAtom, []);
this.type = a;
this.index = b;
}, "~N,~N");
c$ = Clazz.p0p ();
};
Clazz.defineStatics (c$,
"MAX_COUNT", 100,
"GROUP_COUNT", 0,
"OP_COUNT", 0,
"bsOpGroups", null,
"bsGroupOps", null,
"groupNames", null,
"opXYZ", null,
"ops", null,
"rdr", null);
});
