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