matsci-parse 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +694 -327
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1,42 +1,61 @@
|
|
|
1
|
-
class
|
|
2
|
-
constructor(
|
|
3
|
-
this.speciesIndex =
|
|
1
|
+
class S {
|
|
2
|
+
constructor(s, e, t = {}) {
|
|
3
|
+
this.speciesIndex = s, this.cart = e, this.props = t;
|
|
4
4
|
}
|
|
5
|
-
getProp(
|
|
6
|
-
return this.props[
|
|
5
|
+
getProp(s) {
|
|
6
|
+
return this.props[s];
|
|
7
7
|
}
|
|
8
|
-
setProp(
|
|
9
|
-
this.props[
|
|
8
|
+
setProp(s, e) {
|
|
9
|
+
this.props[s] = e;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
function
|
|
13
|
-
return
|
|
12
|
+
function B(i) {
|
|
13
|
+
return i.sites.some((s) => Array.isArray(s.props.selectiveDynamics));
|
|
14
14
|
}
|
|
15
|
-
function
|
|
16
|
-
return
|
|
15
|
+
function M(i) {
|
|
16
|
+
return i * Math.PI / 180;
|
|
17
17
|
}
|
|
18
|
-
function
|
|
19
|
-
return
|
|
20
|
-
(e) => e[0] *
|
|
18
|
+
function O(i, s) {
|
|
19
|
+
return i.map(
|
|
20
|
+
(e) => e[0] * s[0] + e[1] * s[1] + e[2] * s[2]
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
|
-
function
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
function k(i, s, e, t, m, o) {
|
|
24
|
+
const n = M(t), u = M(m), a = M(o), b = [i, 0, 0], h = [
|
|
25
|
+
s * Math.cos(a),
|
|
26
|
+
s * Math.sin(a),
|
|
27
27
|
0
|
|
28
|
-
], r = e * Math.cos(
|
|
29
|
-
return [
|
|
28
|
+
], r = e * Math.cos(u), l = e * (Math.cos(n) - Math.cos(u) * Math.cos(a)) / Math.sin(a), y = Math.sqrt(e * e - r * r - l * l);
|
|
29
|
+
return [b, h, [r, l, y]];
|
|
30
30
|
}
|
|
31
|
-
function
|
|
32
|
-
const [e,
|
|
31
|
+
function U(i, s) {
|
|
32
|
+
const [e, t, m] = s;
|
|
33
33
|
return [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
i[0] * e[0] + i[1] * t[0] + i[2] * m[0],
|
|
35
|
+
i[0] * e[1] + i[1] * t[1] + i[2] * m[1],
|
|
36
|
+
i[0] * e[2] + i[1] * t[2] + i[2] * m[2]
|
|
37
37
|
];
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
function X(i) {
|
|
40
|
+
const [[s, e, t], [m, o, n], [u, a, b]] = i, h = o * b - n * a, r = -(m * b - n * u), l = m * a - o * u, y = -(e * b - t * a), c = s * b - t * u, p = -(s * a - e * u), N = e * n - t * o, g = -(s * n - t * m), _ = s * o - e * m, v = s * h + e * r + t * l;
|
|
41
|
+
if (Math.abs(v) < 1e-12)
|
|
42
|
+
throw new Error("Matrix is singular and cannot be inverted");
|
|
43
|
+
const f = 1 / v;
|
|
44
|
+
return [
|
|
45
|
+
[h * f, y * f, N * f],
|
|
46
|
+
[r * f, c * f, g * f],
|
|
47
|
+
[l * f, p * f, _ * f]
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
function J(i, s) {
|
|
51
|
+
const [e, t, m] = s, o = [
|
|
52
|
+
[e[0], t[0], m[0]],
|
|
53
|
+
[e[1], t[1], m[1]],
|
|
54
|
+
[e[2], t[2], m[2]]
|
|
55
|
+
], n = X(o);
|
|
56
|
+
return O(n, i);
|
|
57
|
+
}
|
|
58
|
+
class F {
|
|
40
59
|
/**
|
|
41
60
|
* Creates a new CrystalStructure.
|
|
42
61
|
*
|
|
@@ -48,11 +67,11 @@ class S {
|
|
|
48
67
|
* @throws Will throw an error if lattice is not 3x3, species is not an array of strings, or sites are invalid
|
|
49
68
|
*/
|
|
50
69
|
constructor({
|
|
51
|
-
lattice:
|
|
70
|
+
lattice: s,
|
|
52
71
|
species: e,
|
|
53
|
-
sites:
|
|
72
|
+
sites: t
|
|
54
73
|
}) {
|
|
55
|
-
this.lattice = this._validateLattice(
|
|
74
|
+
this.lattice = this._validateLattice(s), this.species = this._validateSpecies(e), this.sites = this._validateSites(t);
|
|
56
75
|
}
|
|
57
76
|
// ---------- Simple methods ----------
|
|
58
77
|
/** Number of sites in the structure */
|
|
@@ -63,22 +82,22 @@ class S {
|
|
|
63
82
|
* Returns the site at the specified index.
|
|
64
83
|
* @param i - Site index
|
|
65
84
|
*/
|
|
66
|
-
site(
|
|
67
|
-
return this.sites[
|
|
85
|
+
site(s) {
|
|
86
|
+
return this.sites[s];
|
|
68
87
|
}
|
|
69
88
|
/**
|
|
70
89
|
* Returns the Cartesian coordinates of a site.
|
|
71
90
|
* @param i - Site index
|
|
72
91
|
*/
|
|
73
|
-
cartCoords(
|
|
74
|
-
return this.sites[
|
|
92
|
+
cartCoords(s) {
|
|
93
|
+
return this.sites[s].cart;
|
|
75
94
|
}
|
|
76
95
|
/**
|
|
77
96
|
* Returns the chemical species of a site.
|
|
78
97
|
* @param i - Site index
|
|
79
98
|
*/
|
|
80
|
-
siteSpecies(
|
|
81
|
-
return this.species[this.sites[
|
|
99
|
+
siteSpecies(s) {
|
|
100
|
+
return this.species[this.sites[s].speciesIndex];
|
|
82
101
|
}
|
|
83
102
|
/** Returns the array of elements (species) in the structure */
|
|
84
103
|
get elements() {
|
|
@@ -92,11 +111,11 @@ class S {
|
|
|
92
111
|
* @param cart - Cartesian coordinates of the new site
|
|
93
112
|
* @param position - Optional index at which to insert the site. Defaults to appending at the end.
|
|
94
113
|
*/
|
|
95
|
-
addSite(
|
|
96
|
-
let
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
114
|
+
addSite(s, e, t) {
|
|
115
|
+
let m = this.species.indexOf(s);
|
|
116
|
+
m === -1 && (this.species.push(s), m = this.species.length - 1);
|
|
117
|
+
const o = new S(m, e);
|
|
118
|
+
t === void 0 || t >= this.sites.length ? this.sites.push(o) : t < 0 ? this.sites.unshift(o) : this.sites.splice(t, 0, o);
|
|
100
119
|
}
|
|
101
120
|
/**
|
|
102
121
|
* Removes a site from the crystal.
|
|
@@ -107,14 +126,14 @@ class S {
|
|
|
107
126
|
*
|
|
108
127
|
* @throws Will throw an error if index is out of bounds
|
|
109
128
|
*/
|
|
110
|
-
removeSite(
|
|
111
|
-
if (
|
|
129
|
+
removeSite(s) {
|
|
130
|
+
if (s < 0 || s >= this.sites.length)
|
|
112
131
|
throw new Error("siteIndex out of bounds");
|
|
113
|
-
const
|
|
132
|
+
const t = this.sites.splice(s, 1)[0].speciesIndex;
|
|
114
133
|
this.sites.some(
|
|
115
|
-
(
|
|
116
|
-
) || (this.species.splice(
|
|
117
|
-
|
|
134
|
+
(o) => o.speciesIndex === t
|
|
135
|
+
) || (this.species.splice(t, 1), this.sites.forEach((o) => {
|
|
136
|
+
o.speciesIndex > t && (o.speciesIndex -= 1);
|
|
118
137
|
}));
|
|
119
138
|
}
|
|
120
139
|
/**
|
|
@@ -127,11 +146,11 @@ class S {
|
|
|
127
146
|
*
|
|
128
147
|
* @throws Will throw an error if siteIndex is out of bounds
|
|
129
148
|
*/
|
|
130
|
-
replaceSite(
|
|
131
|
-
if (
|
|
149
|
+
replaceSite(s, e) {
|
|
150
|
+
if (s < 0 || s >= this.sites.length)
|
|
132
151
|
throw new Error("siteIndex out of bounds");
|
|
133
|
-
const
|
|
134
|
-
this.removeSite(
|
|
152
|
+
const t = [...this.sites[s].cart];
|
|
153
|
+
this.removeSite(s), this.addSite(e, t, s);
|
|
135
154
|
}
|
|
136
155
|
/**
|
|
137
156
|
* Returns a new CrystalStructure transformed by a linear matrix.
|
|
@@ -146,39 +165,39 @@ class S {
|
|
|
146
165
|
*
|
|
147
166
|
* @throws Will throw an error if scale is not a number, a 3-element array, or a 3x3 matrix
|
|
148
167
|
*/
|
|
149
|
-
applyLatticeTransformation(
|
|
168
|
+
applyLatticeTransformation(s) {
|
|
150
169
|
let e;
|
|
151
|
-
if (typeof
|
|
170
|
+
if (typeof s == "number")
|
|
152
171
|
e = [
|
|
153
|
-
[
|
|
154
|
-
[0,
|
|
155
|
-
[0, 0,
|
|
172
|
+
[s, 0, 0],
|
|
173
|
+
[0, s, 0],
|
|
174
|
+
[0, 0, s]
|
|
156
175
|
];
|
|
157
|
-
else if (Array.isArray(
|
|
176
|
+
else if (Array.isArray(s) && s.length === 3 && s.every((o) => typeof o == "number"))
|
|
158
177
|
e = [
|
|
159
|
-
[
|
|
160
|
-
[0,
|
|
161
|
-
[0, 0,
|
|
178
|
+
[s[0], 0, 0],
|
|
179
|
+
[0, s[1], 0],
|
|
180
|
+
[0, 0, s[2]]
|
|
162
181
|
];
|
|
163
|
-
else if (Array.isArray(
|
|
164
|
-
e =
|
|
182
|
+
else if (Array.isArray(s) && s.length === 3 && s.every((o) => Array.isArray(o) && o.length === 3))
|
|
183
|
+
e = s;
|
|
165
184
|
else
|
|
166
185
|
throw new Error(
|
|
167
186
|
"Scale must be a number, a 3-element array, or a 3x3 matrix"
|
|
168
187
|
);
|
|
169
|
-
const
|
|
170
|
-
(
|
|
171
|
-
),
|
|
172
|
-
const
|
|
188
|
+
const t = this.lattice.map(
|
|
189
|
+
(o) => O(e, o)
|
|
190
|
+
), m = this.sites.map((o) => {
|
|
191
|
+
const n = O(
|
|
173
192
|
e,
|
|
174
|
-
|
|
193
|
+
o.cart
|
|
175
194
|
);
|
|
176
|
-
return new
|
|
195
|
+
return new S(o.speciesIndex, n, o.props);
|
|
177
196
|
});
|
|
178
|
-
return new
|
|
179
|
-
lattice:
|
|
197
|
+
return new F({
|
|
198
|
+
lattice: t,
|
|
180
199
|
species: [...this.species],
|
|
181
|
-
sites:
|
|
200
|
+
sites: m
|
|
182
201
|
});
|
|
183
202
|
}
|
|
184
203
|
// ---------- Internal validation ----------
|
|
@@ -186,35 +205,35 @@ class S {
|
|
|
186
205
|
* Validates that the lattice is a 3x3 array of Cartesian vectors.
|
|
187
206
|
* @throws Will throw an error if lattice is invalid
|
|
188
207
|
*/
|
|
189
|
-
_validateLattice(
|
|
190
|
-
if (!Array.isArray(
|
|
208
|
+
_validateLattice(s) {
|
|
209
|
+
if (!Array.isArray(s) || s.length !== 3)
|
|
191
210
|
throw new Error("Lattice must be a 3x3 matrix");
|
|
192
|
-
return
|
|
211
|
+
return s.forEach((e) => {
|
|
193
212
|
if (!Array.isArray(e) || e.length !== 3)
|
|
194
213
|
throw new Error("Lattice vectors must be length 3");
|
|
195
|
-
}),
|
|
214
|
+
}), s;
|
|
196
215
|
}
|
|
197
216
|
/**
|
|
198
217
|
* Validates that species is an array of strings.
|
|
199
218
|
* @throws Will throw an error if species array is invalid
|
|
200
219
|
*/
|
|
201
|
-
_validateSpecies(
|
|
202
|
-
if (!Array.isArray(
|
|
203
|
-
return
|
|
220
|
+
_validateSpecies(s) {
|
|
221
|
+
if (!Array.isArray(s)) throw new Error("Species must be an array");
|
|
222
|
+
return s.forEach((e) => {
|
|
204
223
|
if (typeof e != "string")
|
|
205
224
|
throw new Error("Species entries must be strings");
|
|
206
|
-
}),
|
|
225
|
+
}), s;
|
|
207
226
|
}
|
|
208
227
|
/**
|
|
209
228
|
* Validates the sites array, ensuring each site is a Site instance or a valid object.
|
|
210
229
|
* @throws Will throw an error if sites array is invalid
|
|
211
230
|
*/
|
|
212
|
-
_validateSites(
|
|
213
|
-
if (!Array.isArray(
|
|
214
|
-
return
|
|
215
|
-
if (e instanceof
|
|
231
|
+
_validateSites(s) {
|
|
232
|
+
if (!Array.isArray(s)) throw new Error("Sites must be an array");
|
|
233
|
+
return s.map((e) => {
|
|
234
|
+
if (e instanceof S) return e;
|
|
216
235
|
if (typeof e == "object" && typeof e.speciesIndex == "number" && Array.isArray(e.cart) && e.cart.length === 3)
|
|
217
|
-
return this._validateSpeciesIndex(e.speciesIndex), new
|
|
236
|
+
return this._validateSpeciesIndex(e.speciesIndex), new S(
|
|
218
237
|
e.speciesIndex,
|
|
219
238
|
e.cart,
|
|
220
239
|
e.props ?? {}
|
|
@@ -228,230 +247,305 @@ class S {
|
|
|
228
247
|
* Validates that a species index is within bounds.
|
|
229
248
|
* @throws Will throw an error if index is out of range
|
|
230
249
|
*/
|
|
231
|
-
_validateSpeciesIndex(
|
|
232
|
-
if (
|
|
250
|
+
_validateSpeciesIndex(s) {
|
|
251
|
+
if (s < 0 || s >= this.species.length)
|
|
233
252
|
throw new Error("speciesIndex out of bounds");
|
|
234
253
|
}
|
|
235
254
|
}
|
|
236
|
-
|
|
237
|
-
|
|
255
|
+
class Z {
|
|
256
|
+
constructor(s) {
|
|
257
|
+
this.spatialUnits = "angstrom", this._invalid = !0;
|
|
258
|
+
const { origin: e, basis: t, shape: m, values: o, components: n = 1, units: u } = s, [a, b, h] = m;
|
|
259
|
+
if (o.length !== a * b * h * n)
|
|
260
|
+
throw new Error(
|
|
261
|
+
`Invalid values length: expected ${a * b * h * n}, got ${o.length}`
|
|
262
|
+
);
|
|
263
|
+
this.origin = e, this.basis = t, this.shape = m, this.values = o, this.components = n, this.units = u;
|
|
264
|
+
}
|
|
265
|
+
invalidate() {
|
|
266
|
+
this._invalid = !0;
|
|
267
|
+
}
|
|
268
|
+
map(s) {
|
|
269
|
+
const [e, t, m] = this.shape;
|
|
270
|
+
for (let o = 0; o < m; o++)
|
|
271
|
+
for (let n = 0; n < t; n++)
|
|
272
|
+
for (let u = 0; u < e; u++)
|
|
273
|
+
for (let a = 0; a < this.components; a++) {
|
|
274
|
+
const b = this.index(u, n, o, a);
|
|
275
|
+
this.values[b] = s(this.values[b], u, n, o, a);
|
|
276
|
+
}
|
|
277
|
+
this.invalidate();
|
|
278
|
+
}
|
|
279
|
+
min() {
|
|
280
|
+
return (this._invalid || this._min === void 0) && this.computeStats(), this._min;
|
|
281
|
+
}
|
|
282
|
+
max() {
|
|
283
|
+
return (this._invalid || this._max === void 0) && this.computeStats(), this._max;
|
|
284
|
+
}
|
|
285
|
+
mean() {
|
|
286
|
+
return (this._invalid || this._mean === void 0) && this.computeStats(), this._mean;
|
|
287
|
+
}
|
|
288
|
+
index(s, e, t, m = 0) {
|
|
289
|
+
const [o, n] = this.shape;
|
|
290
|
+
return (s + o * (e + n * t)) * this.components + m;
|
|
291
|
+
}
|
|
292
|
+
get(s, e, t, m = 0) {
|
|
293
|
+
return this.values[this.index(s, e, t, m)];
|
|
294
|
+
}
|
|
295
|
+
set(s, e, t, m, o = 0) {
|
|
296
|
+
this.values[this.index(s, e, t, o)] = m, this.invalidate();
|
|
297
|
+
}
|
|
298
|
+
normalize() {
|
|
299
|
+
const s = this.min(), e = this.max();
|
|
300
|
+
this.map((t) => (t - s) / (e - s));
|
|
301
|
+
}
|
|
302
|
+
/** Convert grid index → Cartesian position */
|
|
303
|
+
position(s, e, t) {
|
|
304
|
+
const [m, o, n] = this.basis;
|
|
305
|
+
return [
|
|
306
|
+
this.origin[0] + s * m[0] + e * o[0] + t * n[0],
|
|
307
|
+
this.origin[1] + s * m[1] + e * o[1] + t * n[1],
|
|
308
|
+
this.origin[2] + s * m[2] + e * o[2] + t * n[2]
|
|
309
|
+
];
|
|
310
|
+
}
|
|
311
|
+
voxelVolume() {
|
|
312
|
+
const [s, e, t] = this.basis;
|
|
313
|
+
return Math.abs(
|
|
314
|
+
s[0] * (e[1] * t[2] - e[2] * t[1]) - s[1] * (e[0] * t[2] - e[2] * t[0]) + s[2] * (e[0] * t[1] - e[1] * t[0])
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
integral() {
|
|
318
|
+
return this.mean() * this.values.length * this.voxelVolume();
|
|
319
|
+
}
|
|
320
|
+
computeStats() {
|
|
321
|
+
const s = this.values.length;
|
|
322
|
+
let e = 1 / 0, t = -1 / 0, m = 0;
|
|
323
|
+
for (let o = 0; o < s; o++) {
|
|
324
|
+
const n = this.values[o];
|
|
325
|
+
n < e && (e = n), n > t && (t = n), m += n;
|
|
326
|
+
}
|
|
327
|
+
this._min = e, this._max = t, this._mean = m / s, this._invalid = !1;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function I(i) {
|
|
331
|
+
return i.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
238
332
|
}
|
|
239
|
-
function
|
|
240
|
-
const e = [],
|
|
241
|
-
e.push("Generated by matsci-parse"), e.push("1.0"),
|
|
242
|
-
e.push(
|
|
333
|
+
function Q(i, s = 6) {
|
|
334
|
+
const e = [], t = B(i);
|
|
335
|
+
e.push("Generated by matsci-parse"), e.push("1.0"), i.lattice.forEach((n) => {
|
|
336
|
+
e.push(n.map((u) => u.toFixed(s)).join(" "));
|
|
243
337
|
});
|
|
244
|
-
const
|
|
245
|
-
new Set(
|
|
246
|
-
),
|
|
247
|
-
(
|
|
338
|
+
const m = Array.from(
|
|
339
|
+
new Set(i.sites.map((n) => i.species[n.speciesIndex]))
|
|
340
|
+
), o = m.map(
|
|
341
|
+
(n) => i.sites.filter((u) => i.species[u.speciesIndex] === n).length
|
|
248
342
|
);
|
|
249
|
-
return e.push(
|
|
250
|
-
|
|
251
|
-
const
|
|
252
|
-
if (
|
|
253
|
-
const
|
|
254
|
-
e.push(`${
|
|
343
|
+
return e.push(m.join(" ")), e.push(o.join(" ")), t && e.push("Selective dynamics"), e.push("Cartesian"), m.forEach((n) => {
|
|
344
|
+
i.sites.filter((u) => i.species[u.speciesIndex] === n).forEach((u) => {
|
|
345
|
+
const a = u.cart.map((b) => b.toFixed(s)).join(" ");
|
|
346
|
+
if (t) {
|
|
347
|
+
const h = (Array.isArray(u.props?.selectiveDynamics) ? u.props.selectiveDynamics : [!0, !0, !0]).map((r) => r ? "T" : "F").join(" ");
|
|
348
|
+
e.push(`${a} ${h}`);
|
|
255
349
|
} else
|
|
256
|
-
e.push(
|
|
350
|
+
e.push(a);
|
|
257
351
|
});
|
|
258
352
|
}), e.join(`
|
|
259
353
|
`);
|
|
260
354
|
}
|
|
261
|
-
function
|
|
262
|
-
let
|
|
263
|
-
|
|
264
|
-
const e = parseFloat(s
|
|
355
|
+
function z(i) {
|
|
356
|
+
let s = 0;
|
|
357
|
+
s++;
|
|
358
|
+
const e = parseFloat(i[s++]), t = [];
|
|
265
359
|
for (let r = 0; r < 3; r++)
|
|
266
|
-
|
|
267
|
-
s
|
|
360
|
+
t.push(
|
|
361
|
+
i[s++].split(/\s+/).map((l) => parseFloat(l) * e)
|
|
268
362
|
);
|
|
269
|
-
let
|
|
270
|
-
/^[A-Za-z]/.test(
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
let
|
|
274
|
-
s
|
|
275
|
-
const
|
|
276
|
-
return
|
|
277
|
-
for (let
|
|
278
|
-
const c = s
|
|
279
|
-
let
|
|
280
|
-
|
|
281
|
-
c[0] *
|
|
282
|
-
c[0] *
|
|
283
|
-
c[0] *
|
|
284
|
-
] :
|
|
285
|
-
const
|
|
286
|
-
if (
|
|
287
|
-
const
|
|
288
|
-
|
|
363
|
+
let m = i[s].trim(), o;
|
|
364
|
+
/^[A-Za-z]/.test(m) && (o = m.split(/\s+/), s++);
|
|
365
|
+
const n = i[s++].split(/\s+/).map(Number);
|
|
366
|
+
o || (o = n.map((r, l) => `X${l + 1}`));
|
|
367
|
+
let u = !1;
|
|
368
|
+
i[s]?.toLowerCase().startsWith("s") && (u = !0, s++);
|
|
369
|
+
const b = i[s++].toLowerCase().startsWith("d"), h = [];
|
|
370
|
+
return o.forEach((r, l) => {
|
|
371
|
+
for (let y = 0; y < n[l]; y++) {
|
|
372
|
+
const c = i[s++].split(/\s+/).map(Number);
|
|
373
|
+
let p;
|
|
374
|
+
b ? p = [
|
|
375
|
+
c[0] * t[0][0] + c[1] * t[1][0] + c[2] * t[2][0],
|
|
376
|
+
c[0] * t[0][1] + c[1] * t[1][1] + c[2] * t[2][1],
|
|
377
|
+
c[0] * t[0][2] + c[1] * t[1][2] + c[2] * t[2][2]
|
|
378
|
+
] : p = c.slice(0, 3);
|
|
379
|
+
const N = {};
|
|
380
|
+
if (u) {
|
|
381
|
+
const g = c.slice(3, 6).map((_) => _ === 1);
|
|
382
|
+
g.length === 3 && (N.selectiveDynamics = g);
|
|
289
383
|
}
|
|
290
|
-
|
|
384
|
+
h.push(new S(l, p, N));
|
|
291
385
|
}
|
|
292
386
|
}), {
|
|
293
|
-
structure: new
|
|
294
|
-
linesConsumed:
|
|
387
|
+
structure: new F({ lattice: t, species: o, sites: h }),
|
|
388
|
+
linesConsumed: s
|
|
295
389
|
};
|
|
296
390
|
}
|
|
297
|
-
function
|
|
298
|
-
const
|
|
299
|
-
return
|
|
391
|
+
function ss(i) {
|
|
392
|
+
const s = I(i);
|
|
393
|
+
return z(s).structure;
|
|
300
394
|
}
|
|
301
|
-
function
|
|
395
|
+
function es(i, s = 6) {
|
|
302
396
|
const e = [];
|
|
303
|
-
return e.push("CRYSTAL"), e.push("PRIMVEC"),
|
|
304
|
-
e.push(
|
|
305
|
-
}), e.push("PRIMCOORD"), e.push(`${
|
|
306
|
-
const
|
|
397
|
+
return e.push("CRYSTAL"), e.push("PRIMVEC"), i.lattice.forEach((t) => {
|
|
398
|
+
e.push(t.map((m) => m.toFixed(s)).join(" "));
|
|
399
|
+
}), e.push("PRIMCOORD"), e.push(`${i.numSites} 1`), i.sites.forEach((t) => {
|
|
400
|
+
const m = i.species[t.speciesIndex];
|
|
307
401
|
e.push(
|
|
308
|
-
`${
|
|
402
|
+
`${m} ${t.cart.map((o) => o.toFixed(s)).join(" ")}`
|
|
309
403
|
);
|
|
310
404
|
}), e.join(`
|
|
311
405
|
`);
|
|
312
406
|
}
|
|
313
|
-
function
|
|
314
|
-
const
|
|
315
|
-
let
|
|
316
|
-
for (;
|
|
317
|
-
if (
|
|
318
|
-
|
|
319
|
-
for (let
|
|
320
|
-
e.push(
|
|
321
|
-
for (;
|
|
322
|
-
if (
|
|
323
|
-
|
|
324
|
-
const [
|
|
325
|
-
for (let
|
|
326
|
-
const
|
|
327
|
-
let r =
|
|
328
|
-
r === -1 && (
|
|
329
|
-
}
|
|
330
|
-
return new
|
|
407
|
+
function ts(i) {
|
|
408
|
+
const s = I(i), e = [], t = [], m = [];
|
|
409
|
+
let o = 0;
|
|
410
|
+
for (; o < s.length && s[o].toUpperCase() !== "PRIMVEC"; ) o++;
|
|
411
|
+
if (o === s.length) throw new Error("PRIMVEC block not found in XSF");
|
|
412
|
+
o++;
|
|
413
|
+
for (let u = 0; u < 3; u++)
|
|
414
|
+
e.push(s[o++].split(/\s+/).map(Number));
|
|
415
|
+
for (; o < s.length && s[o].toUpperCase() !== "PRIMCOORD"; ) o++;
|
|
416
|
+
if (o === s.length) throw new Error("PRIMCOORD block not found in XSF");
|
|
417
|
+
o++;
|
|
418
|
+
const [n] = s[o++].split(/\s+/).map(Number);
|
|
419
|
+
for (let u = 0; u < n; u++) {
|
|
420
|
+
const a = s[o++].split(/\s+/), b = a[0], h = a.slice(1, 4).map(Number);
|
|
421
|
+
let r = t.indexOf(b);
|
|
422
|
+
r === -1 && (t.push(b), r = t.length - 1), m.push(new S(r, h));
|
|
423
|
+
}
|
|
424
|
+
return new F({ lattice: e, species: t, sites: m });
|
|
331
425
|
}
|
|
332
|
-
function
|
|
333
|
-
const e = [],
|
|
334
|
-
e.push(String(
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
].join(" "),
|
|
426
|
+
function os(i, s = 6) {
|
|
427
|
+
const e = [], t = i.sites.length;
|
|
428
|
+
e.push(String(t));
|
|
429
|
+
const m = B(i), o = i.lattice, n = [
|
|
430
|
+
o[0][0],
|
|
431
|
+
o[1][0],
|
|
432
|
+
o[2][0],
|
|
433
|
+
o[0][1],
|
|
434
|
+
o[1][1],
|
|
435
|
+
o[2][1],
|
|
436
|
+
o[0][2],
|
|
437
|
+
o[1][2],
|
|
438
|
+
o[2][2]
|
|
439
|
+
].join(" "), u = [
|
|
346
440
|
"species:S:1",
|
|
347
441
|
"pos:R:3",
|
|
348
|
-
|
|
442
|
+
m ? "selectiveDynamics:L:3" : null
|
|
349
443
|
].filter(Boolean).join(":");
|
|
350
|
-
e.push(`Lattice="${
|
|
351
|
-
for (const
|
|
352
|
-
const
|
|
353
|
-
let
|
|
354
|
-
if (
|
|
355
|
-
const c = Array.isArray(
|
|
356
|
-
|
|
444
|
+
e.push(`Lattice="${n}" Properties=${u}`);
|
|
445
|
+
for (const a of i.sites) {
|
|
446
|
+
const b = i.species[a.speciesIndex], [h, r, l] = a.cart;
|
|
447
|
+
let y = `${b} ${h.toFixed(s)} ${r.toFixed(s)} ${l.toFixed(s)}`;
|
|
448
|
+
if (m) {
|
|
449
|
+
const c = Array.isArray(a.props?.selectiveDynamics) ? a.props.selectiveDynamics : [!0, !0, !0];
|
|
450
|
+
y += " " + c.map((p) => p ? "T" : "F").join(" ");
|
|
357
451
|
}
|
|
358
|
-
e.push(
|
|
452
|
+
e.push(y);
|
|
359
453
|
}
|
|
360
454
|
return e.join(`
|
|
361
455
|
`);
|
|
362
456
|
}
|
|
363
|
-
function
|
|
364
|
-
const
|
|
457
|
+
function is(i) {
|
|
458
|
+
const s = I(i);
|
|
365
459
|
let e = 0;
|
|
366
|
-
const
|
|
367
|
-
if (!Number.isFinite(
|
|
460
|
+
const t = parseInt(s[e++], 10);
|
|
461
|
+
if (!Number.isFinite(t))
|
|
368
462
|
throw new Error("Invalid XYZ: first line must be atom count");
|
|
369
|
-
const
|
|
370
|
-
for (const c of
|
|
371
|
-
let
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
let
|
|
375
|
-
if (
|
|
376
|
-
const c =
|
|
463
|
+
const m = s[e++], o = {}, n = /(\w+)=(".*?"|\S+)/g;
|
|
464
|
+
for (const c of m.matchAll(n)) {
|
|
465
|
+
let p = c[2];
|
|
466
|
+
p.startsWith('"') && (p = p.slice(1, -1)), o[c[1]] = p;
|
|
467
|
+
}
|
|
468
|
+
let u;
|
|
469
|
+
if (o.Lattice) {
|
|
470
|
+
const c = o.Lattice.split(/\s+/).map(Number);
|
|
377
471
|
if (c.length !== 9) throw new Error("Invalid Lattice in extended XYZ");
|
|
378
|
-
|
|
472
|
+
u = [
|
|
379
473
|
[c[0], c[3], c[6]],
|
|
380
474
|
[c[1], c[4], c[7]],
|
|
381
475
|
[c[2], c[5], c[8]]
|
|
382
476
|
];
|
|
383
477
|
} else
|
|
384
478
|
throw new Error("Lattice must be present in extended XYZ format");
|
|
385
|
-
let
|
|
386
|
-
if (
|
|
387
|
-
const c =
|
|
388
|
-
let
|
|
389
|
-
for (let
|
|
390
|
-
const
|
|
391
|
-
|
|
479
|
+
let a = 0, b = 1, h = null;
|
|
480
|
+
if (o.Properties) {
|
|
481
|
+
const c = o.Properties.split(":");
|
|
482
|
+
let p = 0;
|
|
483
|
+
for (let N = 0; N < c.length; N += 3) {
|
|
484
|
+
const g = c[N], _ = parseInt(c[N + 2], 10);
|
|
485
|
+
g === "species" && (a = p), g === "pos" && (b = p), g === "selectiveDynamics" && (h = p), p += _;
|
|
392
486
|
}
|
|
393
487
|
}
|
|
394
|
-
const r = [],
|
|
395
|
-
for (let c = 0; c <
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
const
|
|
399
|
-
if (
|
|
400
|
-
const
|
|
401
|
-
|
|
488
|
+
const r = [], l = /* @__PURE__ */ new Map(), y = [];
|
|
489
|
+
for (let c = 0; c < t; c++) {
|
|
490
|
+
const p = s[e++].split(/\s+/), N = p[a];
|
|
491
|
+
l.has(N) || (l.set(N, r.length), r.push(N));
|
|
492
|
+
const g = l.get(N), _ = p.slice(b, b + 3).map(Number), v = {};
|
|
493
|
+
if (h !== null) {
|
|
494
|
+
const f = p.slice(h, h + 3).map((d) => d.toUpperCase() === "T");
|
|
495
|
+
f.length === 3 && (v.selectiveDynamics = f);
|
|
402
496
|
}
|
|
403
|
-
|
|
497
|
+
y.push(new S(g, _, v));
|
|
404
498
|
}
|
|
405
|
-
return new
|
|
499
|
+
return new F({ lattice: u, species: r, sites: y });
|
|
406
500
|
}
|
|
407
|
-
function
|
|
408
|
-
return
|
|
501
|
+
function C(i, s) {
|
|
502
|
+
return i[0] * s[0] + i[1] * s[1] + i[2] * s[2];
|
|
409
503
|
}
|
|
410
|
-
function
|
|
411
|
-
return Math.sqrt(
|
|
504
|
+
function L(i) {
|
|
505
|
+
return Math.sqrt(C(i, i));
|
|
412
506
|
}
|
|
413
|
-
function
|
|
414
|
-
return
|
|
507
|
+
function P(i) {
|
|
508
|
+
return i * 180 / Math.PI;
|
|
415
509
|
}
|
|
416
|
-
function
|
|
417
|
-
const [e,
|
|
418
|
-
if (Math.abs(
|
|
510
|
+
function G(i, s) {
|
|
511
|
+
const [e, t, m] = s, o = e[0] * (t[1] * m[2] - t[2] * m[1]) - e[1] * (t[0] * m[2] - t[2] * m[0]) + e[2] * (t[0] * m[1] - t[1] * m[0]);
|
|
512
|
+
if (Math.abs(o) < 1e-12)
|
|
419
513
|
throw new Error("Singular lattice matrix");
|
|
420
|
-
const
|
|
514
|
+
const n = [
|
|
421
515
|
[
|
|
422
|
-
(
|
|
423
|
-
(e[2] *
|
|
424
|
-
(e[1] *
|
|
516
|
+
(t[1] * m[2] - t[2] * m[1]) / o,
|
|
517
|
+
(e[2] * m[1] - e[1] * m[2]) / o,
|
|
518
|
+
(e[1] * t[2] - e[2] * t[1]) / o
|
|
425
519
|
],
|
|
426
520
|
[
|
|
427
|
-
(
|
|
428
|
-
(e[0] *
|
|
429
|
-
(e[2] *
|
|
521
|
+
(t[2] * m[0] - t[0] * m[2]) / o,
|
|
522
|
+
(e[0] * m[2] - e[2] * m[0]) / o,
|
|
523
|
+
(e[2] * t[0] - e[0] * t[2]) / o
|
|
430
524
|
],
|
|
431
525
|
[
|
|
432
|
-
(
|
|
433
|
-
(e[1] *
|
|
434
|
-
(e[0] *
|
|
526
|
+
(t[0] * m[1] - t[1] * m[0]) / o,
|
|
527
|
+
(e[1] * m[0] - e[0] * m[1]) / o,
|
|
528
|
+
(e[0] * t[1] - e[1] * t[0]) / o
|
|
435
529
|
]
|
|
436
530
|
];
|
|
437
531
|
return [
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
532
|
+
i[0] * n[0][0] + i[1] * n[1][0] + i[2] * n[2][0],
|
|
533
|
+
i[0] * n[0][1] + i[1] * n[1][1] + i[2] * n[2][1],
|
|
534
|
+
i[0] * n[0][2] + i[1] * n[1][2] + i[2] * n[2][2]
|
|
441
535
|
];
|
|
442
536
|
}
|
|
443
|
-
function
|
|
444
|
-
const [e,
|
|
537
|
+
function ms(i, s = 6) {
|
|
538
|
+
const [e, t, m] = i.lattice, o = L(e), n = L(t), u = L(m), a = P(Math.acos(C(t, m) / (n * u))), b = P(Math.acos(C(e, m) / (o * u))), h = P(Math.acos(C(e, t) / (o * n)));
|
|
445
539
|
let r = `data_made_with_matsci-parse
|
|
446
540
|
_symmetry_space_group_name_H-M 'P 1'
|
|
447
541
|
_symmetry_Int_Tables_number 1
|
|
448
542
|
|
|
449
|
-
_cell_length_a ${
|
|
450
|
-
_cell_length_b ${
|
|
451
|
-
_cell_length_c ${
|
|
452
|
-
_cell_angle_alpha ${
|
|
453
|
-
_cell_angle_beta ${
|
|
454
|
-
_cell_angle_gamma ${
|
|
543
|
+
_cell_length_a ${o.toFixed(s)}
|
|
544
|
+
_cell_length_b ${n.toFixed(s)}
|
|
545
|
+
_cell_length_c ${u.toFixed(s)}
|
|
546
|
+
_cell_angle_alpha ${a.toFixed(s)}
|
|
547
|
+
_cell_angle_beta ${b.toFixed(s)}
|
|
548
|
+
_cell_angle_gamma ${h.toFixed(s)}
|
|
455
549
|
|
|
456
550
|
loop_
|
|
457
551
|
_atom_site_label
|
|
@@ -460,134 +554,407 @@ function V(s, t = 6) {
|
|
|
460
554
|
_atom_site_fract_y
|
|
461
555
|
_atom_site_fract_z
|
|
462
556
|
`;
|
|
463
|
-
return
|
|
464
|
-
const c =
|
|
465
|
-
r += `${c}${
|
|
557
|
+
return i.sites.forEach((l, y) => {
|
|
558
|
+
const c = i.species[l.speciesIndex], p = G(l.cart, i.lattice);
|
|
559
|
+
r += `${c}${y + 1} ${c} ${p[0].toFixed(s)} ${p[1].toFixed(
|
|
466
560
|
6
|
|
467
|
-
)} ${
|
|
561
|
+
)} ${p[2].toFixed(s)}
|
|
468
562
|
`;
|
|
469
563
|
}), r;
|
|
470
564
|
}
|
|
471
|
-
function
|
|
472
|
-
const
|
|
473
|
-
let e = 0,
|
|
474
|
-
const
|
|
475
|
-
let
|
|
476
|
-
for (const
|
|
477
|
-
const d =
|
|
565
|
+
function ns(i) {
|
|
566
|
+
const s = I(i);
|
|
567
|
+
let e = 0, t = 0, m = 0, o = 0, n = 0, u = 0, a = [];
|
|
568
|
+
const b = [];
|
|
569
|
+
let h = !1, r = [], l = !1;
|
|
570
|
+
for (const f of s) {
|
|
571
|
+
const d = f.trim();
|
|
478
572
|
if (d) {
|
|
479
573
|
if (d.startsWith("_cell_length_a")) e = parseFloat(d.split(/\s+/)[1]);
|
|
480
574
|
else if (d.startsWith("_cell_length_b"))
|
|
481
|
-
|
|
575
|
+
t = parseFloat(d.split(/\s+/)[1]);
|
|
482
576
|
else if (d.startsWith("_cell_length_c"))
|
|
483
|
-
|
|
577
|
+
m = parseFloat(d.split(/\s+/)[1]);
|
|
484
578
|
else if (d.startsWith("_cell_angle_alpha"))
|
|
485
|
-
|
|
579
|
+
o = parseFloat(d.split(/\s+/)[1]);
|
|
486
580
|
else if (d.startsWith("_cell_angle_beta"))
|
|
487
|
-
|
|
581
|
+
n = parseFloat(d.split(/\s+/)[1]);
|
|
488
582
|
else if (d.startsWith("_cell_angle_gamma"))
|
|
489
|
-
|
|
583
|
+
u = parseFloat(d.split(/\s+/)[1]);
|
|
490
584
|
else if (d.startsWith("loop_")) {
|
|
491
|
-
|
|
585
|
+
h = !0, r = [], l = !1;
|
|
492
586
|
continue;
|
|
493
587
|
}
|
|
494
|
-
if (
|
|
495
|
-
r.push(d), d.includes("_atom_site_") && (
|
|
588
|
+
if (h && d.startsWith("_")) {
|
|
589
|
+
r.push(d), d.includes("_atom_site_") && (l = !0);
|
|
496
590
|
continue;
|
|
497
591
|
}
|
|
498
|
-
if (
|
|
499
|
-
|
|
592
|
+
if (h && !d.startsWith("_")) {
|
|
593
|
+
l && (a.length === 0 && (a = [...r]), b.push(d.split(/\s+/)));
|
|
500
594
|
continue;
|
|
501
595
|
}
|
|
502
596
|
}
|
|
503
597
|
}
|
|
504
|
-
if (
|
|
598
|
+
if (a.length === 0)
|
|
505
599
|
throw new Error("No _atom_site loop found in CIF");
|
|
506
|
-
const
|
|
507
|
-
if (
|
|
600
|
+
const y = k(e, t, m, o, n, u), c = [], p = [], N = a.findIndex((f) => f.includes("fract_x")), g = a.findIndex((f) => f.includes("fract_y")), _ = a.findIndex((f) => f.includes("fract_z")), v = a.findIndex((f) => f.includes("type_symbol"));
|
|
601
|
+
if (N < 0 || g < 0 || _ < 0 || v < 0)
|
|
508
602
|
throw new Error("CIF missing required _atom_site columns");
|
|
509
|
-
for (const
|
|
603
|
+
for (const f of b) {
|
|
510
604
|
const d = [
|
|
511
|
-
parseFloat(
|
|
512
|
-
parseFloat(
|
|
513
|
-
parseFloat(_
|
|
514
|
-
],
|
|
515
|
-
let
|
|
516
|
-
|
|
517
|
-
}
|
|
518
|
-
return new
|
|
605
|
+
parseFloat(f[N]),
|
|
606
|
+
parseFloat(f[g]),
|
|
607
|
+
parseFloat(f[_])
|
|
608
|
+
], w = U(d, y);
|
|
609
|
+
let x = c.indexOf(f[v]);
|
|
610
|
+
x === -1 && (x = c.length, c.push(f[v])), p.push(new S(x, w));
|
|
611
|
+
}
|
|
612
|
+
return new F({ lattice: y, species: c, sites: p });
|
|
519
613
|
}
|
|
520
|
-
function
|
|
521
|
-
let
|
|
614
|
+
function Y(i) {
|
|
615
|
+
let s = [];
|
|
522
616
|
const e = [];
|
|
523
|
-
for (let
|
|
524
|
-
const
|
|
525
|
-
if (!(!
|
|
526
|
-
let
|
|
527
|
-
for (;
|
|
528
|
-
const
|
|
529
|
-
|
|
617
|
+
for (let a = 0; a < i.length; a++) {
|
|
618
|
+
const b = i[a].trim();
|
|
619
|
+
if (!(!b || b.startsWith("&")) && /^CELL_PARAMETERS/i.test(b)) {
|
|
620
|
+
let h = 0, r = a + 1;
|
|
621
|
+
for (; h < 3 && r < i.length; ) {
|
|
622
|
+
const l = i[r].trim();
|
|
623
|
+
l !== "" && (s.push(l.split(/\s+/).map(Number)), h++), r++;
|
|
530
624
|
}
|
|
531
|
-
if (
|
|
625
|
+
if (h < 3) throw new Error("Incomplete CELL_PARAMETERS block");
|
|
532
626
|
break;
|
|
533
627
|
}
|
|
534
628
|
}
|
|
535
|
-
if (
|
|
629
|
+
if (s.length !== 3)
|
|
536
630
|
throw new Error("CELL_PARAMETERS block not found or incomplete");
|
|
537
|
-
let
|
|
538
|
-
for (let
|
|
539
|
-
const
|
|
540
|
-
if (!(!
|
|
541
|
-
if (/^ATOMIC_POSITIONS/i.test(
|
|
542
|
-
|
|
543
|
-
const
|
|
544
|
-
|
|
631
|
+
let t = !1, m = "angstrom";
|
|
632
|
+
for (let a = 0; a < i.length; a++) {
|
|
633
|
+
const b = i[a].trim();
|
|
634
|
+
if (!(!b || b.startsWith("&"))) {
|
|
635
|
+
if (/^ATOMIC_POSITIONS/i.test(b)) {
|
|
636
|
+
t = !0;
|
|
637
|
+
const h = b.match(/^ATOMIC_POSITIONS\s+(\w+)/i);
|
|
638
|
+
m = h ? h[1].toLowerCase() : "angstrom";
|
|
545
639
|
continue;
|
|
546
640
|
}
|
|
547
|
-
if (
|
|
548
|
-
const
|
|
549
|
-
if (
|
|
641
|
+
if (t) {
|
|
642
|
+
const h = b.split(/\s+/);
|
|
643
|
+
if (h.length < 4 || !/^[A-Za-z]/.test(h[0]) || h.slice(1, 4).some((r) => Number.isNaN(Number(r))))
|
|
550
644
|
break;
|
|
551
|
-
e.push(
|
|
645
|
+
e.push(b);
|
|
552
646
|
}
|
|
553
647
|
}
|
|
554
648
|
}
|
|
555
649
|
if (e.length === 0)
|
|
556
650
|
throw new Error("ATOMIC_POSITIONS block not found");
|
|
557
|
-
const
|
|
558
|
-
for (const
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
}
|
|
562
|
-
const
|
|
563
|
-
for (const
|
|
564
|
-
const
|
|
565
|
-
let
|
|
566
|
-
|
|
567
|
-
r[0] *
|
|
568
|
-
r[0] *
|
|
569
|
-
r[0] *
|
|
570
|
-
] :
|
|
651
|
+
const o = m === "crystal", n = [];
|
|
652
|
+
for (const a of e) {
|
|
653
|
+
const b = a.split(/\s+/)[0];
|
|
654
|
+
n.includes(b) || n.push(b);
|
|
655
|
+
}
|
|
656
|
+
const u = [];
|
|
657
|
+
for (const a of e) {
|
|
658
|
+
const b = a.split(/\s+/), h = b[0], r = b.slice(1, 4).map(Number);
|
|
659
|
+
let l;
|
|
660
|
+
o ? l = [
|
|
661
|
+
r[0] * s[0][0] + r[1] * s[1][0] + r[2] * s[2][0],
|
|
662
|
+
r[0] * s[0][1] + r[1] * s[1][1] + r[2] * s[2][1],
|
|
663
|
+
r[0] * s[0][2] + r[1] * s[1][2] + r[2] * s[2][2]
|
|
664
|
+
] : l = r, u.push(new S(n.indexOf(h), l));
|
|
571
665
|
}
|
|
572
666
|
return {
|
|
573
|
-
structure: new
|
|
574
|
-
linesConsumed:
|
|
667
|
+
structure: new F({ lattice: s, species: n, sites: u }),
|
|
668
|
+
linesConsumed: i.length
|
|
575
669
|
};
|
|
576
670
|
}
|
|
577
|
-
function
|
|
578
|
-
const
|
|
579
|
-
return
|
|
671
|
+
function as(i) {
|
|
672
|
+
const s = I(i);
|
|
673
|
+
return Y(s).structure;
|
|
674
|
+
}
|
|
675
|
+
const D = {
|
|
676
|
+
1: { atomicNumber: 1, symbol: "H", name: "Hydrogen", mass: 1.008 },
|
|
677
|
+
2: { atomicNumber: 2, symbol: "He", name: "Helium", mass: 4.0026 },
|
|
678
|
+
3: { atomicNumber: 3, symbol: "Li", name: "Lithium", mass: 6.94 },
|
|
679
|
+
4: { atomicNumber: 4, symbol: "Be", name: "Beryllium", mass: 9.0122 },
|
|
680
|
+
5: { atomicNumber: 5, symbol: "B", name: "Boron", mass: 10.81 },
|
|
681
|
+
6: { atomicNumber: 6, symbol: "C", name: "Carbon", mass: 12.011 },
|
|
682
|
+
7: { atomicNumber: 7, symbol: "N", name: "Nitrogen", mass: 14.007 },
|
|
683
|
+
8: { atomicNumber: 8, symbol: "O", name: "Oxygen", mass: 15.999 },
|
|
684
|
+
9: { atomicNumber: 9, symbol: "F", name: "Fluorine", mass: 18.998 },
|
|
685
|
+
10: { atomicNumber: 10, symbol: "Ne", name: "Neon", mass: 20.18 },
|
|
686
|
+
11: { atomicNumber: 11, symbol: "Na", name: "Sodium", mass: 22.99 },
|
|
687
|
+
12: { atomicNumber: 12, symbol: "Mg", name: "Magnesium", mass: 24.305 },
|
|
688
|
+
13: { atomicNumber: 13, symbol: "Al", name: "Aluminum", mass: 26.982 },
|
|
689
|
+
14: { atomicNumber: 14, symbol: "Si", name: "Silicon", mass: 28.085 },
|
|
690
|
+
15: { atomicNumber: 15, symbol: "P", name: "Phosphorus", mass: 30.974 },
|
|
691
|
+
16: { atomicNumber: 16, symbol: "S", name: "Sulfur", mass: 32.06 },
|
|
692
|
+
17: { atomicNumber: 17, symbol: "Cl", name: "Chlorine", mass: 35.45 },
|
|
693
|
+
18: { atomicNumber: 18, symbol: "Ar", name: "Argon", mass: 39.948 },
|
|
694
|
+
19: { atomicNumber: 19, symbol: "K", name: "Potassium", mass: 39.098 },
|
|
695
|
+
20: { atomicNumber: 20, symbol: "Ca", name: "Calcium", mass: 40.078 },
|
|
696
|
+
21: { atomicNumber: 21, symbol: "Sc", name: "Scandium", mass: 44.956 },
|
|
697
|
+
22: { atomicNumber: 22, symbol: "Ti", name: "Titanium", mass: 47.867 },
|
|
698
|
+
23: { atomicNumber: 23, symbol: "V", name: "Vanadium", mass: 50.942 },
|
|
699
|
+
24: { atomicNumber: 24, symbol: "Cr", name: "Chromium", mass: 51.996 },
|
|
700
|
+
25: { atomicNumber: 25, symbol: "Mn", name: "Manganese", mass: 54.938 },
|
|
701
|
+
26: { atomicNumber: 26, symbol: "Fe", name: "Iron", mass: 55.845 },
|
|
702
|
+
27: { atomicNumber: 27, symbol: "Co", name: "Cobalt", mass: 58.933 },
|
|
703
|
+
28: { atomicNumber: 28, symbol: "Ni", name: "Nickel", mass: 58.693 },
|
|
704
|
+
29: { atomicNumber: 29, symbol: "Cu", name: "Copper", mass: 63.546 },
|
|
705
|
+
30: { atomicNumber: 30, symbol: "Zn", name: "Zinc", mass: 65.38 },
|
|
706
|
+
31: { atomicNumber: 31, symbol: "Ga", name: "Gallium", mass: 69.723 },
|
|
707
|
+
32: { atomicNumber: 32, symbol: "Ge", name: "Germanium", mass: 72.63 },
|
|
708
|
+
33: { atomicNumber: 33, symbol: "As", name: "Arsenic", mass: 74.922 },
|
|
709
|
+
34: { atomicNumber: 34, symbol: "Se", name: "Selenium", mass: 78.971 },
|
|
710
|
+
35: { atomicNumber: 35, symbol: "Br", name: "Bromine", mass: 79.904 },
|
|
711
|
+
36: { atomicNumber: 36, symbol: "Kr", name: "Krypton", mass: 83.798 },
|
|
712
|
+
37: { atomicNumber: 37, symbol: "Rb", name: "Rubidium", mass: 85.468 },
|
|
713
|
+
38: { atomicNumber: 38, symbol: "Sr", name: "Strontium", mass: 87.62 },
|
|
714
|
+
39: { atomicNumber: 39, symbol: "Y", name: "Yttrium", mass: 88.906 },
|
|
715
|
+
40: { atomicNumber: 40, symbol: "Zr", name: "Zirconium", mass: 91.224 },
|
|
716
|
+
41: { atomicNumber: 41, symbol: "Nb", name: "Niobium", mass: 92.906 },
|
|
717
|
+
42: { atomicNumber: 42, symbol: "Mo", name: "Molybdenum", mass: 95.95 },
|
|
718
|
+
43: { atomicNumber: 43, symbol: "Tc", name: "Technetium", mass: 98 },
|
|
719
|
+
44: { atomicNumber: 44, symbol: "Ru", name: "Ruthenium", mass: 101.07 },
|
|
720
|
+
45: { atomicNumber: 45, symbol: "Rh", name: "Rhodium", mass: 102.91 },
|
|
721
|
+
46: { atomicNumber: 46, symbol: "Pd", name: "Palladium", mass: 106.42 },
|
|
722
|
+
47: { atomicNumber: 47, symbol: "Ag", name: "Silver", mass: 107.868 },
|
|
723
|
+
48: { atomicNumber: 48, symbol: "Cd", name: "Cadmium", mass: 112.414 },
|
|
724
|
+
49: { atomicNumber: 49, symbol: "In", name: "Indium", mass: 114.818 },
|
|
725
|
+
50: { atomicNumber: 50, symbol: "Sn", name: "Tin", mass: 118.71 },
|
|
726
|
+
51: { atomicNumber: 51, symbol: "Sb", name: "Antimony", mass: 121.76 },
|
|
727
|
+
52: { atomicNumber: 52, symbol: "Te", name: "Tellurium", mass: 127.6 },
|
|
728
|
+
53: { atomicNumber: 53, symbol: "I", name: "Iodine", mass: 126.904 },
|
|
729
|
+
54: { atomicNumber: 54, symbol: "Xe", name: "Xenon", mass: 131.293 },
|
|
730
|
+
55: { atomicNumber: 55, symbol: "Cs", name: "Cesium", mass: 132.905 },
|
|
731
|
+
56: { atomicNumber: 56, symbol: "Ba", name: "Barium", mass: 137.33 },
|
|
732
|
+
57: { atomicNumber: 57, symbol: "La", name: "Lanthanum", mass: 138.905 },
|
|
733
|
+
58: { atomicNumber: 58, symbol: "Ce", name: "Cerium", mass: 140.12 },
|
|
734
|
+
59: { atomicNumber: 59, symbol: "Pr", name: "Praseodymium", mass: 140.91 },
|
|
735
|
+
60: { atomicNumber: 60, symbol: "Nd", name: "Neodymium", mass: 144.24 },
|
|
736
|
+
61: { atomicNumber: 61, symbol: "Pm", name: "Promethium", mass: 145 },
|
|
737
|
+
62: { atomicNumber: 62, symbol: "Sm", name: "Samarium", mass: 150.36 },
|
|
738
|
+
63: { atomicNumber: 63, symbol: "Eu", name: "Europium", mass: 151.964 },
|
|
739
|
+
64: { atomicNumber: 64, symbol: "Gd", name: "Gadolinium", mass: 157.25 },
|
|
740
|
+
65: { atomicNumber: 65, symbol: "Tb", name: "Terbium", mass: 158.93 },
|
|
741
|
+
66: { atomicNumber: 66, symbol: "Dy", name: "Dysprosium", mass: 162.5 },
|
|
742
|
+
67: { atomicNumber: 67, symbol: "Ho", name: "Holmium", mass: 164.93 },
|
|
743
|
+
68: { atomicNumber: 68, symbol: "Er", name: "Erbium", mass: 167.26 },
|
|
744
|
+
69: { atomicNumber: 69, symbol: "Tm", name: "Thulium", mass: 168.93 },
|
|
745
|
+
70: { atomicNumber: 70, symbol: "Yb", name: "Ytterbium", mass: 173.05 },
|
|
746
|
+
71: { atomicNumber: 71, symbol: "Lu", name: "Lutetium", mass: 174.97 },
|
|
747
|
+
72: { atomicNumber: 72, symbol: "Hf", name: "Hafnium", mass: 178.49 },
|
|
748
|
+
73: { atomicNumber: 73, symbol: "Ta", name: "Tantalum", mass: 180.95 },
|
|
749
|
+
74: { atomicNumber: 74, symbol: "W", name: "Tungsten", mass: 183.84 },
|
|
750
|
+
75: { atomicNumber: 75, symbol: "Re", name: "Rhenium", mass: 186.207 },
|
|
751
|
+
76: { atomicNumber: 76, symbol: "Os", name: "Osmium", mass: 190.23 },
|
|
752
|
+
77: { atomicNumber: 77, symbol: "Ir", name: "Iridium", mass: 192.217 },
|
|
753
|
+
78: { atomicNumber: 78, symbol: "Pt", name: "Platinum", mass: 195.084 },
|
|
754
|
+
79: { atomicNumber: 79, symbol: "Au", name: "Gold", mass: 196.967 },
|
|
755
|
+
80: { atomicNumber: 80, symbol: "Hg", name: "Mercury", mass: 200.592 },
|
|
756
|
+
81: { atomicNumber: 81, symbol: "Tl", name: "Thallium", mass: 204.38 },
|
|
757
|
+
82: { atomicNumber: 82, symbol: "Pb", name: "Lead", mass: 207.2 },
|
|
758
|
+
83: { atomicNumber: 83, symbol: "Bi", name: "Bismuth", mass: 208.98 },
|
|
759
|
+
84: { atomicNumber: 84, symbol: "Po", name: "Polonium", mass: 209 },
|
|
760
|
+
85: { atomicNumber: 85, symbol: "At", name: "Astatine", mass: 210 },
|
|
761
|
+
86: { atomicNumber: 86, symbol: "Rn", name: "Radon", mass: 222 },
|
|
762
|
+
87: { atomicNumber: 87, symbol: "Fr", name: "Francium", mass: 223 },
|
|
763
|
+
88: { atomicNumber: 88, symbol: "Ra", name: "Radium", mass: 226 },
|
|
764
|
+
89: { atomicNumber: 89, symbol: "Ac", name: "Actinium", mass: 227 },
|
|
765
|
+
90: { atomicNumber: 90, symbol: "Th", name: "Thorium", mass: 232.04 },
|
|
766
|
+
91: { atomicNumber: 91, symbol: "Pa", name: "Protactinium", mass: 231.04 },
|
|
767
|
+
92: { atomicNumber: 92, symbol: "U", name: "Uranium", mass: 238.03 },
|
|
768
|
+
93: { atomicNumber: 93, symbol: "Np", name: "Neptunium", mass: 237 },
|
|
769
|
+
94: { atomicNumber: 94, symbol: "Pu", name: "Plutonium", mass: 244 },
|
|
770
|
+
95: { atomicNumber: 95, symbol: "Am", name: "Americium", mass: 243 },
|
|
771
|
+
96: { atomicNumber: 96, symbol: "Cm", name: "Curium", mass: 247 },
|
|
772
|
+
97: { atomicNumber: 97, symbol: "Bk", name: "Berkelium", mass: 247 },
|
|
773
|
+
98: { atomicNumber: 98, symbol: "Cf", name: "Californium", mass: 251 },
|
|
774
|
+
99: { atomicNumber: 99, symbol: "Es", name: "Einsteinium", mass: 252 },
|
|
775
|
+
100: { atomicNumber: 100, symbol: "Fm", name: "Fermium", mass: 257 },
|
|
776
|
+
101: { atomicNumber: 101, symbol: "Md", name: "Mendelevium", mass: 258 },
|
|
777
|
+
102: { atomicNumber: 102, symbol: "No", name: "Nobelium", mass: 259 },
|
|
778
|
+
103: { atomicNumber: 103, symbol: "Lr", name: "Lawrencium", mass: 262 },
|
|
779
|
+
104: { atomicNumber: 104, symbol: "Rf", name: "Rutherfordium", mass: 267 },
|
|
780
|
+
105: { atomicNumber: 105, symbol: "Db", name: "Dubnium", mass: 270 },
|
|
781
|
+
106: { atomicNumber: 106, symbol: "Sg", name: "Seaborgium", mass: 269 },
|
|
782
|
+
107: { atomicNumber: 107, symbol: "Bh", name: "Bohrium", mass: 270 },
|
|
783
|
+
108: { atomicNumber: 108, symbol: "Hs", name: "Hassium", mass: 277 },
|
|
784
|
+
109: { atomicNumber: 109, symbol: "Mt", name: "Meitnerium", mass: 278 },
|
|
785
|
+
110: { atomicNumber: 110, symbol: "Ds", name: "Darmstadtium", mass: 281 },
|
|
786
|
+
111: { atomicNumber: 111, symbol: "Rg", name: "Roentgenium", mass: 282 },
|
|
787
|
+
112: { atomicNumber: 112, symbol: "Cn", name: "Copernicium", mass: 285 },
|
|
788
|
+
113: { atomicNumber: 113, symbol: "Nh", name: "Nihonium", mass: 286 },
|
|
789
|
+
114: { atomicNumber: 114, symbol: "Fl", name: "Flerovium", mass: 289 },
|
|
790
|
+
115: { atomicNumber: 115, symbol: "Mc", name: "Moscovium", mass: 289 },
|
|
791
|
+
116: { atomicNumber: 116, symbol: "Lv", name: "Livermorium", mass: 293 },
|
|
792
|
+
117: { atomicNumber: 117, symbol: "Ts", name: "Tennessine", mass: 294 },
|
|
793
|
+
118: { atomicNumber: 118, symbol: "Og", name: "Oganesson", mass: 294 }
|
|
794
|
+
}, q = {
|
|
795
|
+
angstrom: 1,
|
|
796
|
+
// canonical
|
|
797
|
+
bohr: 0.529177,
|
|
798
|
+
nm: 10,
|
|
799
|
+
pm: 0.01,
|
|
800
|
+
um: 1e4,
|
|
801
|
+
cm: 1e8,
|
|
802
|
+
m: 1e10,
|
|
803
|
+
fm: 1e-5
|
|
804
|
+
}, K = {
|
|
805
|
+
Å: "angstrom",
|
|
806
|
+
μm: "um"
|
|
807
|
+
}, $ = {
|
|
808
|
+
conversions: q,
|
|
809
|
+
aliases: K,
|
|
810
|
+
convert(i, s, e) {
|
|
811
|
+
const t = (n) => this.aliases[n] ?? n, m = t(s), o = t(e);
|
|
812
|
+
return m === o ? i : i * this.conversions[m] / this.conversions[o];
|
|
813
|
+
},
|
|
814
|
+
convertArray(i, s, e) {
|
|
815
|
+
return i.map((t) => this.convert(t, s, e));
|
|
816
|
+
}
|
|
817
|
+
}, R = 1.8897268;
|
|
818
|
+
function rs(i, s) {
|
|
819
|
+
const e = [];
|
|
820
|
+
e.push("Generated by matsci-parse"), e.push("Volumetric data export");
|
|
821
|
+
const m = [...s.origin].map((l) => l * R);
|
|
822
|
+
e.push(
|
|
823
|
+
`${i.numSites} ${m.map((l) => l.toFixed(6)).join(" ")}`
|
|
824
|
+
);
|
|
825
|
+
const o = s.shape, n = s.basis;
|
|
826
|
+
for (let l = 0; l < 3; l++) {
|
|
827
|
+
n[l];
|
|
828
|
+
const y = n[l].map((c) => c * R);
|
|
829
|
+
e.push(`${o[l]} ${y.map((c) => c.toFixed(6)).join(" ")}`);
|
|
830
|
+
}
|
|
831
|
+
for (const l of i.sites) {
|
|
832
|
+
const y = i.species[l.speciesIndex], c = Object.values(D).find(
|
|
833
|
+
(g) => g.symbol === y
|
|
834
|
+
)?.atomicNumber;
|
|
835
|
+
if (!c)
|
|
836
|
+
throw new Error(`Unknown element symbol: ${y}`);
|
|
837
|
+
[...l.cart];
|
|
838
|
+
const p = l.cart.map((g) => g * R), N = (l.getProp("charge") ?? 0).toFixed(6);
|
|
839
|
+
e.push(
|
|
840
|
+
`${c} ${N} ${p.map((g) => g.toFixed(6)).join(" ")}`
|
|
841
|
+
);
|
|
842
|
+
}
|
|
843
|
+
const u = s.values, [a, b, h] = o;
|
|
844
|
+
let r = [];
|
|
845
|
+
for (let l = 0; l < h; l++)
|
|
846
|
+
for (let y = 0; y < b; y++)
|
|
847
|
+
for (let c = 0; c < a; c++) {
|
|
848
|
+
const p = s.index(c, y, l);
|
|
849
|
+
r.push(u[p].toExponential(8)), r.length === 6 && (e.push(r.join(" ")), r = []);
|
|
850
|
+
}
|
|
851
|
+
return r.length > 0 && e.push(r.join(" ")), e.join(`
|
|
852
|
+
`);
|
|
853
|
+
}
|
|
854
|
+
function H(i, s = "bohr", e = "bohr", t = "bohr") {
|
|
855
|
+
let m = 0;
|
|
856
|
+
m += 2;
|
|
857
|
+
const o = i[m].split(/\s+/), n = parseInt(o[0]);
|
|
858
|
+
let u = [
|
|
859
|
+
parseFloat(o[1]),
|
|
860
|
+
parseFloat(o[2]),
|
|
861
|
+
parseFloat(o[3])
|
|
862
|
+
];
|
|
863
|
+
m++;
|
|
864
|
+
const a = i[m++].split(/\s+/), b = i[m++].split(/\s+/), h = i[m++].split(/\s+/);
|
|
865
|
+
let r = [
|
|
866
|
+
[parseFloat(a[1]), parseFloat(a[2]), parseFloat(a[3])],
|
|
867
|
+
[parseFloat(b[1]), parseFloat(b[2]), parseFloat(b[3])],
|
|
868
|
+
[
|
|
869
|
+
parseFloat(h[1]),
|
|
870
|
+
parseFloat(h[2]),
|
|
871
|
+
parseFloat(h[3])
|
|
872
|
+
]
|
|
873
|
+
];
|
|
874
|
+
const l = [
|
|
875
|
+
parseInt(a[0], 10),
|
|
876
|
+
parseInt(b[0], 10),
|
|
877
|
+
parseInt(h[0], 10)
|
|
878
|
+
], y = [], c = /* @__PURE__ */ new Map(), p = [];
|
|
879
|
+
for (let w = 0; w < n; w++, m++) {
|
|
880
|
+
const x = i[m].trim().split(/\s+/);
|
|
881
|
+
if (x.length < 5) throw new Error(`Malformed atom line: "${i[m]}"`);
|
|
882
|
+
const A = parseInt(x[0], 10), V = parseFloat(x[1]), W = [
|
|
883
|
+
parseFloat(x[2]),
|
|
884
|
+
parseFloat(x[3]),
|
|
885
|
+
parseFloat(x[4])
|
|
886
|
+
], j = D[A];
|
|
887
|
+
if (!j) throw new Error(`Unknown atomic number: ${A}`);
|
|
888
|
+
const E = j.symbol;
|
|
889
|
+
let T = c.get(E);
|
|
890
|
+
T === void 0 && (T = y.length, y.push(E), c.set(E, T)), p.push(new S(T, W, { charge: V }));
|
|
891
|
+
}
|
|
892
|
+
u = $.convertArray(
|
|
893
|
+
u,
|
|
894
|
+
s,
|
|
895
|
+
"angstrom"
|
|
896
|
+
), r = r.map(
|
|
897
|
+
(w) => $.convertArray(
|
|
898
|
+
w,
|
|
899
|
+
t,
|
|
900
|
+
"angstrom"
|
|
901
|
+
)
|
|
902
|
+
), p.forEach((w) => {
|
|
903
|
+
w.cart = $.convertArray(
|
|
904
|
+
w.cart,
|
|
905
|
+
e,
|
|
906
|
+
"angstrom"
|
|
907
|
+
);
|
|
908
|
+
});
|
|
909
|
+
const N = r.map(
|
|
910
|
+
(w, x) => w.map((A) => A * l[x])
|
|
911
|
+
), g = new F({
|
|
912
|
+
lattice: N,
|
|
913
|
+
species: y,
|
|
914
|
+
sites: p
|
|
915
|
+
}), _ = l[0] * l[1] * l[2], v = new Float32Array(_);
|
|
916
|
+
let f = 0;
|
|
917
|
+
for (; m < i.length && f < _; ) {
|
|
918
|
+
const w = i[m++].trim().split(/\s+/);
|
|
919
|
+
for (const x of w)
|
|
920
|
+
x && f < _ && (v[f] = parseFloat(x), f++);
|
|
921
|
+
}
|
|
922
|
+
if (f !== _)
|
|
923
|
+
throw new Error(`Cube file truncated: expected ${_}, got ${f}`);
|
|
924
|
+
const d = new Z({
|
|
925
|
+
origin: u,
|
|
926
|
+
basis: r,
|
|
927
|
+
shape: l,
|
|
928
|
+
values: v,
|
|
929
|
+
units: "e/ų"
|
|
930
|
+
});
|
|
931
|
+
return { structure: g, volumetricData: d, linesConsumed: m };
|
|
932
|
+
}
|
|
933
|
+
function cs(i) {
|
|
934
|
+
const s = I(i);
|
|
935
|
+
return H(s).volumetricData;
|
|
936
|
+
}
|
|
937
|
+
function ls(i) {
|
|
938
|
+
const s = I(i);
|
|
939
|
+
return H(s).structure;
|
|
580
940
|
}
|
|
581
941
|
export {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
942
|
+
F as CrystalStructure,
|
|
943
|
+
S as Site,
|
|
944
|
+
Z as VolumetricData,
|
|
945
|
+
J as cartesianToFractional,
|
|
946
|
+
ns as cifToStructure,
|
|
947
|
+
ls as cubeToStructure,
|
|
948
|
+
cs as cubeToVolumetric,
|
|
949
|
+
U as fractionalToCartesian,
|
|
950
|
+
H as parseCube,
|
|
951
|
+
ss as poscarToStructure,
|
|
952
|
+
as as pwToStructure,
|
|
953
|
+
ms as structureToCif,
|
|
954
|
+
Q as structureToPoscar,
|
|
955
|
+
es as structureToXsf,
|
|
956
|
+
os as structureToXyz,
|
|
957
|
+
rs as volumetricToCube,
|
|
958
|
+
ts as xsfToStructure,
|
|
959
|
+
is as xyzToStructure
|
|
593
960
|
};
|