@mat3ra/made 2026.6.29-0 → 2026.7.8-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/js/basis/basis.js +8 -8
- package/dist/js/basis/coordinates.js +2 -2
- package/dist/js/cell/cell.js +11 -10
- package/dist/js/cell/conventional_cell.js +2 -2
- package/dist/js/cell/primitive_cell.js +19 -21
- package/dist/js/lattice/lattice.js +42 -30
- package/dist/js/lattice/lattice_types.js +1 -1
- package/dist/js/lattice/reciprocal/lattice_reciprocal.js +16 -16
- package/dist/js/lattice/reciprocal/symmetry_points.js +1 -2
- package/dist/js/material.d.ts +15 -15
- package/dist/js/parsers/poscar.js +2 -4
- package/dist/js/parsers/xyz.js +2 -2
- package/dist/js/parsers/xyz_combinatorial_basis.d.ts +2 -1
- package/dist/js/parsers/xyz_combinatorial_basis.js +19 -9
- package/dist/js/tools/basis.js +3 -3
- package/dist/js/tools/cell.js +3 -3
- package/dist/js/tools/material.js +3 -3
- package/dist/js/tools/supercell.js +3 -3
- package/dist/js/tools/surface.js +14 -12
- package/package.json +41 -40
- package/pyproject.toml +6 -7
- package/src/js/basis/basis.ts +9 -8
- package/src/js/basis/coordinates.ts +3 -2
- package/src/js/cell/cell.ts +12 -10
- package/src/js/cell/primitive_cell.ts +23 -19
- package/src/js/lattice/lattice.ts +25 -23
- package/src/js/lattice/reciprocal/lattice_reciprocal.ts +19 -18
- package/src/js/parsers/poscar.ts +2 -2
- package/src/js/parsers/xyz_combinatorial_basis.ts +3 -2
- package/src/js/tools/basis.ts +4 -3
- package/src/js/tools/cell.ts +4 -3
- package/src/js/tools/material.ts +5 -4
- package/src/js/tools/supercell.ts +4 -3
- package/src/js/tools/surface.ts +18 -12
- package/src/py/mat3ra/made/cell/primitive_cell.py +156 -0
- package/tests/fixtures/hashes.json +3 -0
- package/tests/js/cell/cell.ts +1 -1
- package/tests/js/fixtures.ts +7 -1
- package/tests/js/material.test.ts +8 -1
- package/tests/py/conftest.py +1 -1
- package/tests/py/unit/test_material.py +10 -0
- package/tests/py/unit/test_primitive_cell.py +118 -0
- /package/src/py/mat3ra/made/{cell.py → cell/__init__.py} +0 -0
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { HASH_TOLERANCE } from "@mat3ra/code/dist/js/constants";
|
|
2
1
|
import { InMemoryEntity } from "@mat3ra/code/dist/js/entity";
|
|
3
|
-
import { math } from "@mat3ra/code/dist/js/math";
|
|
4
2
|
import {
|
|
5
3
|
Coordinate3DSchema,
|
|
6
4
|
LatticeSchema,
|
|
@@ -9,6 +7,7 @@ import {
|
|
|
9
7
|
LatticeVectorsSchema,
|
|
10
8
|
Matrix3X3Schema,
|
|
11
9
|
} from "@mat3ra/esse/dist/js/types";
|
|
10
|
+
import { Utils } from "@mat3ra/utils";
|
|
12
11
|
import * as lodash from "lodash";
|
|
13
12
|
|
|
14
13
|
import { Cell } from "../cell/cell";
|
|
@@ -16,6 +15,7 @@ import { getPrimitiveLatticeVectorsFromConfig } from "../cell/primitive_cell";
|
|
|
16
15
|
import { LATTICE_TYPE_CONFIGS } from "./lattice_types";
|
|
17
16
|
import { UnitCell, UnitCellProps } from "./unit_cell";
|
|
18
17
|
|
|
18
|
+
const { HASH_TOLERANCE } = Utils.constants;
|
|
19
19
|
/**
|
|
20
20
|
* Scaling factor used to calculate the new lattice size for non-periodic systems.
|
|
21
21
|
* The scaling factor ensures that a non-periodic structure will have have a lattice greater than the structures size.
|
|
@@ -86,19 +86,21 @@ export class Lattice extends InMemoryEntity implements LatticeSchema {
|
|
|
86
86
|
const { b } = this;
|
|
87
87
|
const { c } = this;
|
|
88
88
|
|
|
89
|
-
const alphaRad = math.unit(this.alpha, "deg").toNumber("rad");
|
|
90
|
-
const betaRad = math.unit(this.beta, "deg").toNumber("rad");
|
|
91
|
-
const gammaRad = math.unit(this.gamma, "deg").toNumber("rad");
|
|
89
|
+
const alphaRad = Utils.math.unit(this.alpha, "deg").toNumber("rad");
|
|
90
|
+
const betaRad = Utils.math.unit(this.beta, "deg").toNumber("rad");
|
|
91
|
+
const gammaRad = Utils.math.unit(this.gamma, "deg").toNumber("rad");
|
|
92
92
|
|
|
93
|
-
const cosAlpha = math.cos(alphaRad);
|
|
94
|
-
const cosBeta = math.cos(betaRad);
|
|
95
|
-
const cosGamma = math.cos(gammaRad);
|
|
96
|
-
const sinAlpha = math.sin(alphaRad);
|
|
97
|
-
const sinBeta = math.sin(betaRad);
|
|
93
|
+
const cosAlpha = Utils.math.cos(alphaRad);
|
|
94
|
+
const cosBeta = Utils.math.cos(betaRad);
|
|
95
|
+
const cosGamma = Utils.math.cos(gammaRad);
|
|
96
|
+
const sinAlpha = Utils.math.sin(alphaRad);
|
|
97
|
+
const sinBeta = Utils.math.sin(betaRad);
|
|
98
98
|
|
|
99
|
-
const gammaStar = math.acos((cosAlpha * cosBeta - cosGamma) / (sinAlpha * sinBeta));
|
|
100
|
-
|
|
101
|
-
const
|
|
99
|
+
const gammaStar = Utils.math.acos((cosAlpha * cosBeta - cosGamma) / (sinAlpha * sinBeta));
|
|
100
|
+
// @ts-ignore - mathjs v12 acos return type includes Complex, but inputs are always real
|
|
101
|
+
const cosGammaStar = Utils.math.cos(gammaStar);
|
|
102
|
+
// @ts-ignore
|
|
103
|
+
const sinGammaStar = Utils.math.sin(gammaStar);
|
|
102
104
|
|
|
103
105
|
const vectorA: Coordinate3DSchema = [a * sinBeta, 0.0, a * cosBeta];
|
|
104
106
|
const vectorB: Coordinate3DSchema = [
|
|
@@ -121,12 +123,12 @@ export class Lattice extends InMemoryEntity implements LatticeSchema {
|
|
|
121
123
|
type: LatticeTypeEnum = "TRI",
|
|
122
124
|
): Lattice {
|
|
123
125
|
const [aVec, bVec, cVec] = vectors;
|
|
124
|
-
const a = math.vlen(aVec);
|
|
125
|
-
const b = math.vlen(bVec);
|
|
126
|
-
const c = math.vlen(cVec);
|
|
127
|
-
const alpha = math.angle(bVec, cVec, "deg");
|
|
128
|
-
const beta = math.angle(aVec, cVec, "deg");
|
|
129
|
-
const gamma = math.angle(aVec, bVec, "deg");
|
|
126
|
+
const a = Utils.math.vlen(aVec);
|
|
127
|
+
const b = Utils.math.vlen(bVec);
|
|
128
|
+
const c = Utils.math.vlen(cVec);
|
|
129
|
+
const alpha = Utils.math.angle(bVec, cVec, "deg");
|
|
130
|
+
const beta = Utils.math.angle(aVec, cVec, "deg");
|
|
131
|
+
const gamma = Utils.math.angle(aVec, bVec, "deg");
|
|
130
132
|
|
|
131
133
|
return new Lattice({
|
|
132
134
|
a,
|
|
@@ -183,7 +185,7 @@ export class Lattice extends InMemoryEntity implements LatticeSchema {
|
|
|
183
185
|
*/
|
|
184
186
|
get typeExtended(): LatticeTypeExtendedEnum {
|
|
185
187
|
const { a, b, c, alpha, beta, gamma, type } = this;
|
|
186
|
-
const cosAlpha = math.cos((alpha / 180) * math.PI);
|
|
188
|
+
const cosAlpha = Utils.math.cos((alpha / 180) * Utils.math.PI);
|
|
187
189
|
|
|
188
190
|
switch (type) {
|
|
189
191
|
case "BCT":
|
|
@@ -220,7 +222,7 @@ export class Lattice extends InMemoryEntity implements LatticeSchema {
|
|
|
220
222
|
* Calculate the volume of the lattice cell.
|
|
221
223
|
*/
|
|
222
224
|
get volume(): number {
|
|
223
|
-
return math.abs(math.det(this.vectorArrays));
|
|
225
|
+
return Utils.math.abs(Utils.math.det(this.vectorArrays));
|
|
224
226
|
}
|
|
225
227
|
|
|
226
228
|
/*
|
|
@@ -228,7 +230,7 @@ export class Lattice extends InMemoryEntity implements LatticeSchema {
|
|
|
228
230
|
* @param latticeConfig {Object} LatticeBravais config (see constructor)
|
|
229
231
|
*/
|
|
230
232
|
static getDefaultPrimitiveLatticeConfigByType(latticeConfig: LatticeSchema) {
|
|
231
|
-
const f_ = math.roundArrayOrNumber;
|
|
233
|
+
const f_ = Utils.math.roundArrayOrNumber;
|
|
232
234
|
// construct new primitive cell using lattice parameters and skip rounding the vectors
|
|
233
235
|
const vectors = getPrimitiveLatticeVectorsFromConfig(latticeConfig);
|
|
234
236
|
// create new lattice from primitive cell
|
|
@@ -268,7 +270,7 @@ export class Lattice extends InMemoryEntity implements LatticeSchema {
|
|
|
268
270
|
scaledLattice.beta,
|
|
269
271
|
scaledLattice.gamma,
|
|
270
272
|
]
|
|
271
|
-
.map((x) => math.
|
|
273
|
+
.map((x) => Utils.math.roundCustom(x, HASH_TOLERANCE))
|
|
272
274
|
.join(";")};`;
|
|
273
275
|
}
|
|
274
276
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ATOMIC_COORD_UNITS, units as UNITS } from "@mat3ra/code/dist/js/constants";
|
|
2
|
-
import { math } from "@mat3ra/code/dist/js/math";
|
|
3
2
|
import { Vector3DSchema } from "@mat3ra/esse/dist/js/types";
|
|
3
|
+
import { Utils } from "@mat3ra/utils";
|
|
4
4
|
import lodash from "lodash";
|
|
5
5
|
|
|
6
6
|
import { Lattice } from "../lattice";
|
|
7
7
|
import { paths } from "./paths";
|
|
8
8
|
import { symmetryPoints } from "./symmetry_points";
|
|
9
9
|
|
|
10
|
+
|
|
10
11
|
export type KPointCoordinates = number[];
|
|
11
12
|
export type KPointPath = Array<{
|
|
12
13
|
point: string;
|
|
@@ -39,16 +40,16 @@ export class ReciprocalLattice extends Lattice {
|
|
|
39
40
|
*/
|
|
40
41
|
get reciprocalVectors(): Vector3DSchema[] {
|
|
41
42
|
const vectors_: Vector3DSchema[] = this.vectors.vectorArrays as Vector3DSchema[];
|
|
42
|
-
const a: number = math.vlen(vectors_[0]);
|
|
43
|
+
const a: number = Utils.math.vlen(vectors_[0]);
|
|
43
44
|
const divider: number =
|
|
44
|
-
(math.multiply(
|
|
45
|
+
(Utils.math.multiply(
|
|
45
46
|
vectors_[0],
|
|
46
|
-
math.cross(vectors_[1], vectors_[2]),
|
|
47
|
+
Utils.math.cross(vectors_[1], vectors_[2]),
|
|
47
48
|
) as unknown as number) / a;
|
|
48
49
|
return [
|
|
49
|
-
math.multiply(math.cross(vectors_[1], vectors_[2]), 1 / divider) as Vector3DSchema,
|
|
50
|
-
math.multiply(math.cross(vectors_[2], vectors_[0]), 1 / divider) as Vector3DSchema,
|
|
51
|
-
math.multiply(math.cross(vectors_[0], vectors_[1]), 1 / divider) as Vector3DSchema,
|
|
50
|
+
Utils.math.multiply(Utils.math.cross(vectors_[1], vectors_[2]), 1 / divider) as Vector3DSchema,
|
|
51
|
+
Utils.math.multiply(Utils.math.cross(vectors_[2], vectors_[0]), 1 / divider) as Vector3DSchema,
|
|
52
|
+
Utils.math.multiply(Utils.math.cross(vectors_[0], vectors_[1]), 1 / divider) as Vector3DSchema,
|
|
52
53
|
];
|
|
53
54
|
}
|
|
54
55
|
|
|
@@ -56,7 +57,7 @@ export class ReciprocalLattice extends Lattice {
|
|
|
56
57
|
* Norms of reciprocal vectors.
|
|
57
58
|
*/
|
|
58
59
|
get reciprocalVectorNorms(): Vector3DSchema {
|
|
59
|
-
return this.reciprocalVectors.map((vec) => math.norm(vec) as number) as Vector3DSchema;
|
|
60
|
+
return this.reciprocalVectors.map((vec) => Utils.math.norm(vec) as number) as Vector3DSchema;
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
/**
|
|
@@ -64,7 +65,7 @@ export class ReciprocalLattice extends Lattice {
|
|
|
64
65
|
*/
|
|
65
66
|
get reciprocalVectorRatios(): Vector3DSchema {
|
|
66
67
|
const norms: number[] = this.reciprocalVectorNorms;
|
|
67
|
-
const maxNorm: number = math.max(...norms) as number;
|
|
68
|
+
const maxNorm: number = Utils.math.max(...norms) as number;
|
|
68
69
|
return norms.map((n: number) => n / maxNorm) as Vector3DSchema;
|
|
69
70
|
}
|
|
70
71
|
|
|
@@ -74,7 +75,7 @@ export class ReciprocalLattice extends Lattice {
|
|
|
74
75
|
* @return {KPointCoordinates}
|
|
75
76
|
*/
|
|
76
77
|
getCartesianCoordinates(point: KPointCoordinates): KPointCoordinates {
|
|
77
|
-
return math.multiply(point, this.reciprocalVectors) as KPointCoordinates;
|
|
78
|
+
return Utils.math.multiply(point, this.reciprocalVectors) as KPointCoordinates;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
/**
|
|
@@ -105,7 +106,7 @@ export class ReciprocalLattice extends Lattice {
|
|
|
105
106
|
|
|
106
107
|
dataPoints.forEach((point: KPointCoordinates, index: number) => {
|
|
107
108
|
const symmPoint: SymmetryPoint | undefined = symmPoints.find((x) => {
|
|
108
|
-
return math.vEqualWithTolerance(x.coordinates, point, 1e-4);
|
|
109
|
+
return Utils.math.vEqualWithTolerance(x.coordinates, point, 1e-4);
|
|
109
110
|
});
|
|
110
111
|
if (symmPoint) {
|
|
111
112
|
kpointPath.push({
|
|
@@ -128,10 +129,10 @@ export class ReciprocalLattice extends Lattice {
|
|
|
128
129
|
calculateDimension(nPoints: number, index: number): number {
|
|
129
130
|
const norms: number[] = this.reciprocalVectorNorms;
|
|
130
131
|
const [j, k] = [0, 1, 2].filter((i) => i !== index); // get indices of other two dimensions
|
|
131
|
-
const N: number = math.cbrt(
|
|
132
|
+
const N: number = Utils.math.cbrt(
|
|
132
133
|
(nPoints * norms[index] ** 2) / (norms[j] * norms[k]),
|
|
133
134
|
) as number;
|
|
134
|
-
return math.max(1, math.ceil(N)) as number;
|
|
135
|
+
return Utils.math.max(1, Utils.math.ceil(N)) as number;
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
/**
|
|
@@ -148,10 +149,10 @@ export class ReciprocalLattice extends Lattice {
|
|
|
148
149
|
const { a } = this;
|
|
149
150
|
return {
|
|
150
151
|
[ATOMIC_COORD_UNITS.cartesian]: {
|
|
151
|
-
[UNITS.angstrom]: (2 * math.PI) / a,
|
|
152
|
+
[UNITS.angstrom]: (2 * Utils.math.PI) / a,
|
|
152
153
|
},
|
|
153
154
|
[UNITS.angstrom]: {
|
|
154
|
-
[ATOMIC_COORD_UNITS.cartesian]: a / (2 * math.PI),
|
|
155
|
+
[ATOMIC_COORD_UNITS.cartesian]: a / (2 * Utils.math.PI),
|
|
155
156
|
},
|
|
156
157
|
};
|
|
157
158
|
}
|
|
@@ -166,7 +167,7 @@ export class ReciprocalLattice extends Lattice {
|
|
|
166
167
|
getDimensionsFromSpacing(spacing: number, units: string = ATOMIC_COORD_UNITS.cartesian) {
|
|
167
168
|
const factor: number = this.conversionTable[units][ATOMIC_COORD_UNITS.cartesian] || 1;
|
|
168
169
|
return this.reciprocalVectorNorms.map((norm: number) => {
|
|
169
|
-
return math.max(1, math.ceil(lodash.round(norm / (spacing * factor), 4))) as number;
|
|
170
|
+
return Utils.math.max(1, Utils.math.ceil(lodash.round(norm / (spacing * factor), 4))) as number;
|
|
170
171
|
}) as Vector3DSchema;
|
|
171
172
|
}
|
|
172
173
|
|
|
@@ -184,8 +185,8 @@ export class ReciprocalLattice extends Lattice {
|
|
|
184
185
|
const norms: number[] = this.reciprocalVectorNorms;
|
|
185
186
|
return (
|
|
186
187
|
factor *
|
|
187
|
-
(math.mean(
|
|
188
|
-
dimensions.map((dim: number, i: number) => norms[i] / math.max(1, dim)),
|
|
188
|
+
(Utils.math.mean(
|
|
189
|
+
dimensions.map((dim: number, i: number) => norms[i] / Utils.math.max(1, dim)),
|
|
189
190
|
) as number)
|
|
190
191
|
);
|
|
191
192
|
}
|
package/src/js/parsers/poscar.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { math } from "@mat3ra/code/dist/js/math";
|
|
2
1
|
import {
|
|
3
2
|
BasisSchema,
|
|
4
3
|
Coordinate3DSchema,
|
|
@@ -16,7 +15,8 @@ import { ATOMIC_COORD_UNITS } from "../constants";
|
|
|
16
15
|
import { AtomicConstraintValue } from "../constraints/constraints";
|
|
17
16
|
import { Lattice } from "../lattice/lattice";
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
|
|
19
|
+
const _print = (x: number, printFormat = "%14.9f") => s.sprintf(printFormat, Utils.math.precise(x));
|
|
20
20
|
const _latticeVectorsToString = (vectors: Vector3DSchema[]) =>
|
|
21
21
|
vectors.map((v) => v.map((c) => _print(c)).join("\t")).join("\n");
|
|
22
22
|
const atomicConstraintsCharFromBool = (bool: boolean): string => (bool ? "T" : "F");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { math } from "@mat3ra/code/dist/js/math";
|
|
2
1
|
import { BasisSchema } from "@mat3ra/esse/dist/js/types";
|
|
2
|
+
import { Utils } from "@mat3ra/utils";
|
|
3
3
|
import { chain, last, map } from "lodash";
|
|
4
4
|
import * as s from "underscore.string";
|
|
5
5
|
|
|
@@ -8,6 +8,7 @@ import { AtomicCoordinateValue } from "../basis/coordinates";
|
|
|
8
8
|
import { AtomicElementValue } from "../basis/elements";
|
|
9
9
|
import { Cell } from "../cell/cell";
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
/**
|
|
12
13
|
* @summary Combinatorial XYZ basis class and related. Create and get all information about basis and elements in it.
|
|
13
14
|
* Constructor accepts string in extended XYZ format. Extended XYZ format is as follows:
|
|
@@ -224,7 +225,7 @@ export class CombinatorialBasis {
|
|
|
224
225
|
dimensions.push(itemsSet);
|
|
225
226
|
});
|
|
226
227
|
// @ts-ignore // We're multiplying objects with math, not numbers. No type casting will help.
|
|
227
|
-
const basisSet = math.cartesianProduct.apply(null, dimensions) as ElementWithCoordinate[][];
|
|
228
|
+
const basisSet = Utils.math.cartesianProduct.apply(null, dimensions) as ElementWithCoordinate[][];
|
|
228
229
|
return basisSet.map((basis: ElementWithCoordinate[]) =>
|
|
229
230
|
basis.filter((entry) => entry.element !== VACANCY_CHARACTER),
|
|
230
231
|
);
|
package/src/js/tools/basis.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { math } from "@mat3ra/code/dist/js/math";
|
|
2
1
|
import { Coordinate3DSchema } from "@mat3ra/esse/dist/js/types";
|
|
2
|
+
import { Utils } from "@mat3ra/utils";
|
|
3
3
|
import { chunk, flatten } from "lodash";
|
|
4
4
|
|
|
5
5
|
import { Basis } from "../basis/basis";
|
|
6
6
|
import { AtomicCoordinateValue, Coordinate } from "../basis/coordinates";
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
const
|
|
8
|
+
|
|
9
|
+
const ADD = Utils.math.add;
|
|
10
|
+
const MULT = Utils.math.multiply;
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Returns a repeated basis of a crystal.
|
package/src/js/tools/cell.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { math } from "@mat3ra/code/dist/js/math";
|
|
2
1
|
import { Coordinate3DSchema, Matrix3X3Schema } from "@mat3ra/esse/dist/js/types";
|
|
2
|
+
import { Utils } from "@mat3ra/utils";
|
|
3
3
|
|
|
4
4
|
import { Cell } from "../cell/cell";
|
|
5
5
|
|
|
6
|
+
|
|
6
7
|
/**
|
|
7
8
|
* Returns the list of points on the original lattice contained in the supercell in fractional coordinates.
|
|
8
9
|
* Source: https://pymatgen.org/_modules/pymatgen/util/coord.html
|
|
@@ -22,8 +23,8 @@ function latticePointsInSupercell(supercellMatrix: Matrix3X3Schema) {
|
|
|
22
23
|
const d_points = diagonals.map((point) =>
|
|
23
24
|
supercell.convertPointToCartesian(point as Coordinate3DSchema),
|
|
24
25
|
);
|
|
25
|
-
const mins = [0, 1, 2].map((i) => math.min(...d_points.map((p) => p[i])));
|
|
26
|
-
const maxes = [0, 1, 2].map((i) => math.max(...d_points.map((p) => p[i])) + 1);
|
|
26
|
+
const mins = [0, 1, 2].map((i) => Utils.math.min(...d_points.map((p) => p[i])));
|
|
27
|
+
const maxes = [0, 1, 2].map((i) => Utils.math.max(...d_points.map((p) => p[i])) + 1);
|
|
27
28
|
const points = [];
|
|
28
29
|
for (let i = mins[0]; i <= maxes[0]; i++) {
|
|
29
30
|
for (let j = mins[1]; j <= maxes[1]; j++) {
|
package/src/js/tools/material.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { math } from "@mat3ra/code/dist/js/math";
|
|
2
1
|
import { LatticeSchema, Vector3DSchema } from "@mat3ra/esse/dist/js/types";
|
|
2
|
+
import { Utils } from "@mat3ra/utils";
|
|
3
3
|
|
|
4
4
|
import { ATOMIC_COORD_UNITS } from "../constants";
|
|
5
5
|
import { Lattice } from "../lattice/lattice";
|
|
6
6
|
import { Material } from "../material";
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
/**
|
|
9
10
|
* Scales one lattice vector for the given material
|
|
10
11
|
* @param material {Material} The material acted upon.
|
|
@@ -44,11 +45,11 @@ function translateAtomsToCenter(material: Material) {
|
|
|
44
45
|
material.toCartesian();
|
|
45
46
|
const updatedBasis = material.Basis;
|
|
46
47
|
const centerOfCoordinates = updatedBasis.centerOfCoordinatesPoint;
|
|
47
|
-
const centerOfLattice = math.multiply(
|
|
48
|
+
const centerOfLattice = Utils.math.multiply(
|
|
48
49
|
0.5,
|
|
49
|
-
material.Lattice.vectorArrays.reduce((a, b) => math.add(a, b) as Vector3DSchema),
|
|
50
|
+
material.Lattice.vectorArrays.reduce((a, b) => Utils.math.add(a, b) as Vector3DSchema),
|
|
50
51
|
);
|
|
51
|
-
const translationVector = math.subtract(centerOfLattice, centerOfCoordinates);
|
|
52
|
+
const translationVector = Utils.math.subtract(centerOfLattice, centerOfCoordinates);
|
|
52
53
|
updatedBasis.translateByVector(translationVector as Vector3DSchema);
|
|
53
54
|
material.setBasis(updatedBasis.toJSON());
|
|
54
55
|
if (originalUnits !== ATOMIC_COORD_UNITS.cartesian) material.toCrystal();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { math } from "@mat3ra/code/dist/js/math";
|
|
2
1
|
import { Coordinate3DSchema, Matrix3X3Schema } from "@mat3ra/esse/dist/js/types";
|
|
2
|
+
import { Utils } from "@mat3ra/utils";
|
|
3
3
|
|
|
4
4
|
import { Basis } from "../basis/basis";
|
|
5
5
|
import { ConstrainedBasis } from "../basis/constrained_basis";
|
|
@@ -8,7 +8,8 @@ import { Lattice } from "../lattice/lattice";
|
|
|
8
8
|
import type { Material } from "../material";
|
|
9
9
|
import cellTools from "./cell";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
const ADD = Utils.math.add;
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* @summary Generates new basis for a supercell. For each site from basis generates shifts that are within supercell.
|
|
@@ -56,7 +57,7 @@ function generateNewBasisWithinSupercell(
|
|
|
56
57
|
* @param supercellMatrix {Number[][]}
|
|
57
58
|
*/
|
|
58
59
|
function generateConfig(material: Material, supercellMatrix: Matrix3X3Schema) {
|
|
59
|
-
const det = math.det(supercellMatrix);
|
|
60
|
+
const det = Utils.math.det(supercellMatrix);
|
|
60
61
|
if (det === 0) {
|
|
61
62
|
throw new Error("Scaling matrix is degenerate.");
|
|
62
63
|
}
|
package/src/js/tools/surface.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { math } from "@mat3ra/code/dist/js/math";
|
|
2
1
|
import {
|
|
3
2
|
Coordinate3DSchema,
|
|
4
3
|
MaterialSchema,
|
|
5
4
|
Matrix3X3Schema,
|
|
6
5
|
Vector3DSchema,
|
|
7
6
|
} from "@mat3ra/esse/dist/js/types";
|
|
7
|
+
import { Utils } from "@mat3ra/utils";
|
|
8
8
|
|
|
9
9
|
import { Cell } from "../cell/cell";
|
|
10
10
|
import { Lattice } from "../lattice/lattice";
|
|
11
11
|
import { Material } from "../material";
|
|
12
12
|
import SupercellTools from "./supercell";
|
|
13
13
|
|
|
14
|
-
const MULT = math.multiply;
|
|
15
|
-
const ADD = math.add;
|
|
16
|
-
const DOT = math.product;
|
|
14
|
+
const MULT = Utils.math.multiply;
|
|
15
|
+
const ADD = Utils.math.add;
|
|
16
|
+
const DOT = Utils.math.product;
|
|
17
17
|
const getMatrixInLeftHandedRepresentation = (matrix: Matrix3X3Schema) => {
|
|
18
|
-
return math.det(matrix) < 0 ? MULT(matrix, -1) : matrix;
|
|
18
|
+
return Utils.math.det(matrix) < 0 ? MULT(matrix, -1) : matrix;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -27,10 +27,10 @@ const getMatrixInLeftHandedRepresentation = (matrix: Matrix3X3Schema) => {
|
|
|
27
27
|
*/
|
|
28
28
|
function extGCD(a: number, b: number): [number, number] {
|
|
29
29
|
if (b === 0) return [1, 0];
|
|
30
|
-
if (math.mod(a, b) === 0) return [0, 1];
|
|
30
|
+
if (Utils.math.mod(a, b) === 0) return [0, 1];
|
|
31
31
|
|
|
32
|
-
const [x, y] = extGCD(b, math.mod(a, b));
|
|
33
|
-
return [y, x - y * math.floor(a / b)];
|
|
32
|
+
const [x, y] = extGCD(b, Utils.math.mod(a, b));
|
|
33
|
+
return [y, x - y * Utils.math.floor(a / b)];
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -46,7 +46,7 @@ function getMillerScalingMatrix(
|
|
|
46
46
|
millerIndices: Coordinate3DSchema,
|
|
47
47
|
tol = 1e-8,
|
|
48
48
|
): Matrix3X3Schema {
|
|
49
|
-
if (!millerIndices.reduce((a, b) => math.abs(a) + math.abs(b)))
|
|
49
|
+
if (!millerIndices.reduce((a, b) => Utils.math.abs(a) + Utils.math.abs(b)))
|
|
50
50
|
throw new Error("Miller indices are zeros.");
|
|
51
51
|
|
|
52
52
|
let scalingMatrix;
|
|
@@ -94,20 +94,26 @@ function getMillerScalingMatrix(
|
|
|
94
94
|
// @ts-ignore
|
|
95
95
|
const k2 = DOT(ADD(MULT(l, z1), -MULT(k, z2)), z3);
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
// @ts-ignore
|
|
98
|
+
if (Utils.math.abs(k2) > tol) {
|
|
98
99
|
// For mathjs version 3.20: round(-0.5) = -0
|
|
99
100
|
// For mathjs version 5.10: round(-0.5) = -1
|
|
100
101
|
// Here we specify rounding method to Bankers
|
|
101
102
|
// For Python 3.11: round(-0.5) = 0
|
|
103
|
+
// @ts-ignore - mathjs v12 dot return type
|
|
102
104
|
const value = k1 / k2;
|
|
103
|
-
const roundedValue = math.roundCustom(
|
|
105
|
+
const roundedValue = Utils.math.roundCustom(
|
|
106
|
+
value,
|
|
107
|
+
0,
|
|
108
|
+
Utils.math.RoundingMethod.Bankers,
|
|
109
|
+
);
|
|
104
110
|
const i = -roundedValue;
|
|
105
111
|
[p, q] = [p + i * l, q - i * k];
|
|
106
112
|
}
|
|
107
113
|
|
|
108
114
|
const [a, b] = extGCD(p * k + q * l, h);
|
|
109
115
|
const c1 = [p * k + q * l, -p * h, -q * h];
|
|
110
|
-
const c2 = [0, l, -k].map((c) => math.trunc(c / math.gcd(l, k))); // floor division
|
|
116
|
+
const c2 = [0, l, -k].map((c) => Utils.math.trunc(c / Utils.math.gcd(l, k))); // floor division
|
|
111
117
|
const c3 = [b, a * p, a * q];
|
|
112
118
|
|
|
113
119
|
scalingMatrix = [c1, c2, c3];
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Routines for calculating primitive cell vectors from conventional cell Bravais parameters.
|
|
3
|
+
Python equivalent of src/js/cell/primitive_cell.ts.
|
|
4
|
+
|
|
5
|
+
Following Setyawan, W., & Curtarolo, S. (2010). doi:10.1016/j.commatsci.2010.05.010
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import math
|
|
9
|
+
from typing import List
|
|
10
|
+
|
|
11
|
+
from mat3ra.esse.models.properties_directory.structural.lattice import LatticeSchema
|
|
12
|
+
from mat3ra.made.cell import Cell
|
|
13
|
+
|
|
14
|
+
Matrix3x3 = List[List[float]]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _rhl(p: LatticeSchema) -> Matrix3x3:
|
|
18
|
+
a = p.a
|
|
19
|
+
alpha_rad = math.radians(p.alpha)
|
|
20
|
+
|
|
21
|
+
cos_alpha = math.cos(alpha_rad)
|
|
22
|
+
cos_half_alpha = math.cos(alpha_rad / 2.0)
|
|
23
|
+
sin_half_alpha = math.sin(alpha_rad / 2.0)
|
|
24
|
+
|
|
25
|
+
z_comp = a * math.sqrt(1.0 - (cos_alpha / cos_half_alpha) ** 2)
|
|
26
|
+
|
|
27
|
+
return [
|
|
28
|
+
[a * cos_half_alpha, -a * sin_half_alpha, 0.0],
|
|
29
|
+
[a * cos_half_alpha, a * sin_half_alpha, 0.0],
|
|
30
|
+
[(a * cos_alpha) / cos_half_alpha, 0.0, z_comp],
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _tri(p: LatticeSchema) -> Matrix3x3:
|
|
35
|
+
"""
|
|
36
|
+
Algorithm from pymatgen (from_params).
|
|
37
|
+
Mirrors the TRI case in primitive_cell.ts exactly.
|
|
38
|
+
"""
|
|
39
|
+
alpha = math.radians(p.alpha)
|
|
40
|
+
beta = math.radians(p.beta)
|
|
41
|
+
gamma = math.radians(p.gamma)
|
|
42
|
+
|
|
43
|
+
cos_alpha = math.cos(alpha)
|
|
44
|
+
cos_beta = math.cos(beta)
|
|
45
|
+
cos_gamma = math.cos(gamma)
|
|
46
|
+
sin_alpha = math.sin(alpha)
|
|
47
|
+
sin_beta = math.sin(beta)
|
|
48
|
+
|
|
49
|
+
acos_arg = (cos_alpha * cos_beta - cos_gamma) / (sin_alpha * sin_beta)
|
|
50
|
+
# Clamp to [-1, 1] to guard against floating-point drift
|
|
51
|
+
acos_arg = max(-1.0, min(1.0, acos_arg))
|
|
52
|
+
|
|
53
|
+
gamma_star = math.acos(acos_arg)
|
|
54
|
+
cos_gamma_star = math.cos(gamma_star)
|
|
55
|
+
sin_gamma_star = math.sin(gamma_star)
|
|
56
|
+
|
|
57
|
+
a, b, c = p.a, p.b, p.c
|
|
58
|
+
return [
|
|
59
|
+
[a * sin_beta, 0.0, a * cos_beta],
|
|
60
|
+
[-b * sin_alpha * cos_gamma_star, b * sin_alpha * sin_gamma_star, b * cos_alpha],
|
|
61
|
+
[0.0, 0.0, c],
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
PRIMITIVE_CELLS = {
|
|
66
|
+
"CUB": lambda p: [
|
|
67
|
+
[p.a, 0, 0],
|
|
68
|
+
[0, p.a, 0],
|
|
69
|
+
[0, 0, p.a],
|
|
70
|
+
],
|
|
71
|
+
"FCC": lambda p: [
|
|
72
|
+
[0.0, p.a / 2, p.a / 2],
|
|
73
|
+
[p.a / 2, 0.0, p.a / 2],
|
|
74
|
+
[p.a / 2, p.a / 2, 0.0],
|
|
75
|
+
],
|
|
76
|
+
"BCC": lambda p: [
|
|
77
|
+
[-p.a / 2, p.a / 2, p.a / 2],
|
|
78
|
+
[p.a / 2, -p.a / 2, p.a / 2],
|
|
79
|
+
[p.a / 2, p.a / 2, -p.a / 2],
|
|
80
|
+
],
|
|
81
|
+
"TET": lambda p: [
|
|
82
|
+
[p.a, 0, 0],
|
|
83
|
+
[0, p.a, 0],
|
|
84
|
+
[0, 0, p.c],
|
|
85
|
+
],
|
|
86
|
+
"BCT": lambda p: [
|
|
87
|
+
[-p.a / 2, p.a / 2, p.c / 2],
|
|
88
|
+
[p.a / 2, -p.a / 2, p.c / 2],
|
|
89
|
+
[p.a / 2, p.a / 2, -p.c / 2],
|
|
90
|
+
],
|
|
91
|
+
"ORC": lambda p: [
|
|
92
|
+
[p.a, 0, 0],
|
|
93
|
+
[0, p.b, 0],
|
|
94
|
+
[0, 0, p.c],
|
|
95
|
+
],
|
|
96
|
+
"ORCF": lambda p: [
|
|
97
|
+
[0, p.b / 2, p.c / 2],
|
|
98
|
+
[p.a / 2, 0, p.c / 2],
|
|
99
|
+
[p.a / 2, p.b / 2, 0],
|
|
100
|
+
],
|
|
101
|
+
"ORCI": lambda p: [
|
|
102
|
+
[-p.a / 2, p.b / 2, p.c / 2],
|
|
103
|
+
[p.a / 2, -p.b / 2, p.c / 2],
|
|
104
|
+
[p.a / 2, p.b / 2, -p.c / 2],
|
|
105
|
+
],
|
|
106
|
+
"ORCC": lambda p: [
|
|
107
|
+
[p.a / 2, p.b / 2, 0],
|
|
108
|
+
[-p.a / 2, p.b / 2, 0],
|
|
109
|
+
[0, 0, p.c],
|
|
110
|
+
],
|
|
111
|
+
"HEX": lambda p: [
|
|
112
|
+
[p.a / 2, -(p.a * math.sqrt(3)) / 2, 0],
|
|
113
|
+
[p.a / 2, (p.a * math.sqrt(3)) / 2, 0],
|
|
114
|
+
[0, 0, p.c],
|
|
115
|
+
],
|
|
116
|
+
"RHL": _rhl,
|
|
117
|
+
"MCL": lambda p: [
|
|
118
|
+
[p.a, 0, 0],
|
|
119
|
+
[0, p.b, 0],
|
|
120
|
+
[0, p.c * math.cos(math.radians(p.alpha)), p.c * math.sin(math.radians(p.alpha))],
|
|
121
|
+
],
|
|
122
|
+
"MCLC": lambda p: [
|
|
123
|
+
[p.a / 2, p.b / 2, 0],
|
|
124
|
+
[-p.a / 2, p.b / 2, 0],
|
|
125
|
+
[0, p.c * math.cos(math.radians(p.alpha)), p.c * math.sin(math.radians(p.alpha))],
|
|
126
|
+
],
|
|
127
|
+
"TRI": _tri,
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def get_primitive_lattice_vectors_from_config(lattice_config: LatticeSchema) -> Matrix3x3:
|
|
132
|
+
"""
|
|
133
|
+
Returns lattice vectors for a primitive cell for a given lattice config.
|
|
134
|
+
Python equivalent of getPrimitiveLatticeVectorsFromConfig() in primitive_cell.ts.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
lattice_config: LatticeSchema instance with fields:
|
|
138
|
+
type, a, b, c, alpha, beta, gamma.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
3x3 list of lists (rows = vectors a, b, c) in the same units as the
|
|
142
|
+
input lattice parameters (typically Angstroms).
|
|
143
|
+
"""
|
|
144
|
+
lattice_type = lattice_config.type.value if lattice_config.type else "TRI"
|
|
145
|
+
generator = PRIMITIVE_CELLS.get(lattice_type)
|
|
146
|
+
if generator is None:
|
|
147
|
+
raise ValueError(
|
|
148
|
+
f"Unsupported lattice type '{lattice_type}'. " f"Must be one of: {list(PRIMITIVE_CELLS.keys())}"
|
|
149
|
+
)
|
|
150
|
+
return generator(lattice_config)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def get_primitive_cell_from_config(lattice_config: LatticeSchema) -> Cell:
|
|
154
|
+
"""Returns a full Cell object instantiated with the primitive lattice vectors."""
|
|
155
|
+
vectors = get_primitive_lattice_vectors_from_config(lattice_config)
|
|
156
|
+
return Cell.from_vectors_array(vectors)
|
package/tests/js/cell/cell.ts
CHANGED
|
@@ -41,7 +41,7 @@ const VECTORS_EQUAL_UP_TO_PRECISION_4: Matrix3X3Schema = [
|
|
|
41
41
|
[0.0, 0.0, 3.00001],
|
|
42
42
|
];
|
|
43
43
|
|
|
44
|
-
const VECTORS_EQUAL_UP_TO_PRECISION_4_VOLUME = 6.
|
|
44
|
+
const VECTORS_EQUAL_UP_TO_PRECISION_4_VOLUME = 6.000110000600001;
|
|
45
45
|
const VECTORS_EQUAL_UP_TO_PRECISION_4_VOLUME_ROUNDED_TO_PRECISION_4 = 6.0001;
|
|
46
46
|
const VECTORS_EQUAL_UP_TO_PRECISION_4_VOLUME_ROUNDED_TO_PRECISION_5 = 6.00011;
|
|
47
47
|
|
package/tests/js/fixtures.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { AtomicConstraintsSchema, BasisSchema, MaterialSchema } from "@mat3ra/esse/dist/js/types";
|
|
2
|
+
import { MaterialStandata } from "@mat3ra/standata";
|
|
2
3
|
import fs from "fs";
|
|
3
4
|
import path from "path";
|
|
4
5
|
|
|
5
|
-
// TODO: use @mat3ra/standata
|
|
6
6
|
import AsGeBasis_JSON from "../fixtures/AsGe-basis.json";
|
|
7
7
|
import atomicConstraints_JSON from "../fixtures/atomic-constraints.json";
|
|
8
8
|
import C2H4_JSON from "../fixtures/C2H4.json";
|
|
9
9
|
import C2H4Translated_JSON from "../fixtures/C2H4-translated.json";
|
|
10
10
|
import FeLiSiBasis_JSON from "../fixtures/FeLiSi-basis.json";
|
|
11
11
|
import FeO_JSON from "../fixtures/FeO.json";
|
|
12
|
+
|
|
12
13
|
import Ge2Basis_JSON from "../fixtures/Ge2-basis.json";
|
|
13
14
|
import Graphene_JSON from "../fixtures/Graphene.json";
|
|
14
15
|
import H2HFinal_JSON from "../fixtures/H2+H-final.json";
|
|
@@ -27,6 +28,7 @@ import SiSlab111Gamma120_JSON from "../fixtures/si-slab-111-0.5-vacuum-gamma-120
|
|
|
27
28
|
import SiSlab111_JSON from "../fixtures/si-slab-111-0.5-vacuum-ratio.json";
|
|
28
29
|
import SiSlab111NoVacuum_JSON from "../fixtures/si-slab-111-0-vacuum.json";
|
|
29
30
|
import Silicon_JSON from "../fixtures/si-standata.json";
|
|
31
|
+
|
|
30
32
|
import SiSupercell_JSON from "../fixtures/Si-supercell.json";
|
|
31
33
|
import Si2Basis_JSON from "../fixtures/Si2-basis.json";
|
|
32
34
|
import Si2BasisRepeated_JSON from "../fixtures/Si2-basis-repeated.json";
|
|
@@ -41,6 +43,9 @@ const SiSlab111 = SiSlab111_JSON as unknown as MaterialSchema;
|
|
|
41
43
|
const SiSlab111Gamma120 = SiSlab111Gamma120_JSON as unknown as MaterialSchema;
|
|
42
44
|
const SiSlab111NoVacuum = SiSlab111NoVacuum_JSON as unknown as MaterialSchema;
|
|
43
45
|
const FeO = FeO_JSON as unknown as MaterialSchema;
|
|
46
|
+
const FeOStandata = MaterialStandata.getRuntimeDataConfigs().find(
|
|
47
|
+
(m: any) => m.name?.includes("FeO"),
|
|
48
|
+
) as MaterialSchema;
|
|
44
49
|
const Na4Cl4 = Na4Cl4_JSON as unknown as MaterialSchema;
|
|
45
50
|
const Na4Cl4Cartesian = Na4Cl4Cartesian_JSON as unknown as MaterialSchema;
|
|
46
51
|
const C2H4 = C2H4_JSON as unknown as MaterialSchema;
|
|
@@ -79,6 +84,7 @@ export {
|
|
|
79
84
|
Si2BasisRepeated,
|
|
80
85
|
// Other
|
|
81
86
|
FeO,
|
|
87
|
+
FeOStandata,
|
|
82
88
|
Na4Cl4,
|
|
83
89
|
Na4Cl4Cartesian,
|
|
84
90
|
C2H4,
|