@mat3ra/made 2024.3.22-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/.babelrc +10 -0
- package/.eslintrc.json +11 -0
- package/.mocharc.json +5 -0
- package/.prettierignore +1 -0
- package/.prettierrc +6 -0
- package/LICENSE.md +15 -0
- package/README.md +167 -0
- package/dist/abstract/array_with_ids.d.ts +43 -0
- package/dist/abstract/array_with_ids.js +88 -0
- package/dist/abstract/scalar_with_id.d.ts +25 -0
- package/dist/abstract/scalar_with_id.js +44 -0
- package/dist/basis/basis.d.ts +269 -0
- package/dist/basis/basis.js +499 -0
- package/dist/basis/constrained_basis.d.ts +56 -0
- package/dist/basis/constrained_basis.js +90 -0
- package/dist/basis/types.d.ts +1 -0
- package/dist/basis/types.js +2 -0
- package/dist/cell/cell.d.ts +45 -0
- package/dist/cell/cell.js +88 -0
- package/dist/cell/conventional_cell.d.ts +22 -0
- package/dist/cell/conventional_cell.js +83 -0
- package/dist/cell/primitive_cell.d.ts +9 -0
- package/dist/cell/primitive_cell.js +166 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +25 -0
- package/dist/constraints/constraints.d.ts +45 -0
- package/dist/constraints/constraints.js +49 -0
- package/dist/lattice/lattice.d.ts +104 -0
- package/dist/lattice/lattice.js +208 -0
- package/dist/lattice/lattice_bravais.d.ts +59 -0
- package/dist/lattice/lattice_bravais.js +120 -0
- package/dist/lattice/lattice_vectors.d.ts +46 -0
- package/dist/lattice/lattice_vectors.js +98 -0
- package/dist/lattice/reciprocal/lattice_reciprocal.d.ts +75 -0
- package/dist/lattice/reciprocal/lattice_reciprocal.js +148 -0
- package/dist/lattice/reciprocal/paths.d.ts +24 -0
- package/dist/lattice/reciprocal/paths.js +136 -0
- package/dist/lattice/reciprocal/symmetry_points.d.ts +8 -0
- package/dist/lattice/reciprocal/symmetry_points.js +866 -0
- package/dist/lattice/types.d.ts +49 -0
- package/dist/lattice/types.js +127 -0
- package/dist/lattice/unit_cell.d.ts +30 -0
- package/dist/lattice/unit_cell.js +31 -0
- package/dist/made.d.ts +40 -0
- package/dist/made.js +39 -0
- package/dist/material.d.ts +1562 -0
- package/dist/material.js +317 -0
- package/dist/math.d.ts +395 -0
- package/dist/math.js +7 -0
- package/dist/parsers/cif.d.ts +10 -0
- package/dist/parsers/cif.js +21 -0
- package/dist/parsers/errors.d.ts +5 -0
- package/dist/parsers/errors.js +11 -0
- package/dist/parsers/espresso.d.ts +10 -0
- package/dist/parsers/espresso.js +24 -0
- package/dist/parsers/native_format_parsers.d.ts +26 -0
- package/dist/parsers/native_format_parsers.js +52 -0
- package/dist/parsers/parsers.d.ts +13 -0
- package/dist/parsers/parsers.js +17 -0
- package/dist/parsers/poscar.d.ts +31 -0
- package/dist/parsers/poscar.js +180 -0
- package/dist/parsers/xyz.d.ts +62 -0
- package/dist/parsers/xyz.js +167 -0
- package/dist/parsers/xyz_combinatorial_basis.d.ts +64 -0
- package/dist/parsers/xyz_combinatorial_basis.js +241 -0
- package/dist/tools/basis.d.ts +22 -0
- package/dist/tools/basis.js +100 -0
- package/dist/tools/cell.d.ts +9 -0
- package/dist/tools/cell.js +39 -0
- package/dist/tools/index.d.ts +11 -0
- package/dist/tools/index.js +15 -0
- package/dist/tools/material.d.ts +25 -0
- package/dist/tools/material.js +54 -0
- package/dist/tools/supercell.d.ts +22 -0
- package/dist/tools/supercell.js +62 -0
- package/dist/tools/surface.d.ts +10 -0
- package/dist/tools/surface.js +147 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.js +2 -0
- package/package.json +89 -0
- package/pyproject.toml +77 -0
- package/src/js/abstract/array_with_ids.ts +100 -0
- package/src/js/abstract/scalar_with_id.ts +53 -0
- package/src/js/basis/basis.ts +607 -0
- package/src/js/basis/constrained_basis.ts +107 -0
- package/src/js/basis/types.ts +1 -0
- package/src/js/cell/cell.ts +109 -0
- package/src/js/cell/conventional_cell.ts +89 -0
- package/src/js/cell/primitive_cell.ts +189 -0
- package/src/js/constants.js +4 -0
- package/src/js/constraints/constraints.ts +63 -0
- package/src/js/lattice/lattice.ts +229 -0
- package/src/js/lattice/lattice_bravais.ts +170 -0
- package/src/js/lattice/lattice_vectors.ts +126 -0
- package/src/js/lattice/reciprocal/lattice_reciprocal.js +155 -0
- package/src/js/lattice/reciprocal/paths.js +134 -0
- package/src/js/lattice/reciprocal/symmetry_points.ts +886 -0
- package/src/js/lattice/types.ts +142 -0
- package/src/js/lattice/unit_cell.ts +66 -0
- package/src/js/made.js +36 -0
- package/src/js/material.ts +398 -0
- package/src/js/math.js +6 -0
- package/src/js/parsers/cif.js +22 -0
- package/src/js/parsers/errors.js +7 -0
- package/src/js/parsers/espresso.ts +30 -0
- package/src/js/parsers/native_format_parsers.js +51 -0
- package/src/js/parsers/parsers.js +13 -0
- package/src/js/parsers/poscar.ts +201 -0
- package/src/js/parsers/xyz.ts +216 -0
- package/src/js/parsers/xyz_combinatorial_basis.js +243 -0
- package/src/js/tools/basis.js +116 -0
- package/src/js/tools/cell.js +36 -0
- package/src/js/tools/index.js +11 -0
- package/src/js/tools/material.js +60 -0
- package/src/js/tools/supercell.ts +80 -0
- package/src/js/tools/surface.js +176 -0
- package/src/js/types.ts +4 -0
- package/src/py/__init__.py +0 -0
- package/src/py/mat3ra/__init__.py +0 -0
- package/src/py/mat3ra/made/__init__.py +5 -0
- package/tests/.gitattributes +1 -0
- package/tests/fixtures/AsGe-basis.json +3 -0
- package/tests/fixtures/C2H4-translated.json +3 -0
- package/tests/fixtures/C2H4.json +3 -0
- package/tests/fixtures/FeLiSi-basis.json +3 -0
- package/tests/fixtures/FeO.json +3 -0
- package/tests/fixtures/Ge2-basis.json +3 -0
- package/tests/fixtures/Graphene.json +3 -0
- package/tests/fixtures/Graphene.poscar +3 -0
- package/tests/fixtures/H2+H-final.json +3 -0
- package/tests/fixtures/H2+H-image.json +3 -0
- package/tests/fixtures/H2+H-initial.json +3 -0
- package/tests/fixtures/H2O.poscar +3 -0
- package/tests/fixtures/LiFeSi-basis.json +3 -0
- package/tests/fixtures/Na.json +3 -0
- package/tests/fixtures/Na4Cl4-cartesian.json +3 -0
- package/tests/fixtures/Na4Cl4.json +3 -0
- package/tests/fixtures/Na4Cl4.poscar +3 -0
- package/tests/fixtures/Ni-hex.json +3 -0
- package/tests/fixtures/Ni-hex.poscar +3 -0
- package/tests/fixtures/OSi-basis.json +3 -0
- package/tests/fixtures/Si-hex.json +3 -0
- package/tests/fixtures/Si-hex.poscar +3 -0
- package/tests/fixtures/Si-pwscf.in +3 -0
- package/tests/fixtures/Si-slab.json +3 -0
- package/tests/fixtures/Si-supercell.json +3 -0
- package/tests/fixtures/Si.json +3 -0
- package/tests/fixtures/Si2-basis-repeated.json +3 -0
- package/tests/fixtures/Si2-basis.json +3 -0
- package/tests/fixtures/Zr1H23Zr1H1.json +3 -0
- package/tests/fixtures/Zr1H23Zr1H1.poscar +3 -0
- package/tests/fixtures/atomic-constraints.json +3 -0
- package/tests/js/basis/basis.js +221 -0
- package/tests/js/cell/cell.js +21 -0
- package/tests/js/cell/primitive_cell.js +17 -0
- package/tests/js/constraints/constraints.js +27 -0
- package/tests/js/enums.js +40 -0
- package/tests/js/lattice/lattice.js +31 -0
- package/tests/js/lattice/lattice_bravais.js +17 -0
- package/tests/js/lattice/lattice_reciprocal.js +99 -0
- package/tests/js/lattice/lattice_vectors.js +10 -0
- package/tests/js/material.test.js +11 -0
- package/tests/js/parsers/espresso.js +12 -0
- package/tests/js/parsers/native_formats.js +30 -0
- package/tests/js/parsers/poscar.js +21 -0
- package/tests/js/parsers/xyz.js +25 -0
- package/tests/js/parsers/xyz_combinatorial_basis.js +153 -0
- package/tests/js/setup.js +6 -0
- package/tests/js/tools/basis.js +18 -0
- package/tests/js/tools/supercell.js +23 -0
- package/tests/js/tools/surface.js +12 -0
- package/tests/js/utils.js +17 -0
- package/tests/py/__init__.py +0 -0
- package/tests/py/unit/__init__.py +0 -0
- package/tests/py/unit/test_sample.py +10 -0
- package/tsconfig.json +3 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Coordinate = [number, number, number];
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { math } from "@exabyte-io/code.js/dist/math";
|
|
2
|
+
|
|
3
|
+
import { Coordinate } from "../basis/types";
|
|
4
|
+
import constants from "../constants";
|
|
5
|
+
import { Vector, VectorsAsArray } from "../lattice/types";
|
|
6
|
+
|
|
7
|
+
const MATRIX = math.matrix;
|
|
8
|
+
const MULT = math.multiply;
|
|
9
|
+
const INV = math.inv;
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
const MATRIX_MULT = (...args) => MULT(...args.map((x) => MATRIX(x))).toArray();
|
|
12
|
+
|
|
13
|
+
type Point = Coordinate | math.Matrix | math.MathType;
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* Cell represents a unit cell in geometrical form: 3x3 matrix where rows are cell vectors.
|
|
17
|
+
* Example: [[1, 0, 0], [0, 1, 0], [0, 0, 1]].
|
|
18
|
+
*/
|
|
19
|
+
export class Cell {
|
|
20
|
+
tolerance = 1;
|
|
21
|
+
|
|
22
|
+
vector1: Vector;
|
|
23
|
+
|
|
24
|
+
vector2: Vector;
|
|
25
|
+
|
|
26
|
+
vector3: Vector;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create a cell.
|
|
30
|
+
* @param nestedArray {Number[][]} is an array of cell vectors in cartesian Angstrom units.
|
|
31
|
+
*/
|
|
32
|
+
constructor(nestedArray: VectorsAsArray) {
|
|
33
|
+
[this.vector1, this.vector2, this.vector3] = nestedArray;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get cell vectors as (a nested) array.
|
|
38
|
+
* @example [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
|
|
39
|
+
*/
|
|
40
|
+
get vectorsAsArray(): VectorsAsArray {
|
|
41
|
+
return [
|
|
42
|
+
this.vector1,
|
|
43
|
+
this.vector2,
|
|
44
|
+
this.vector3,
|
|
45
|
+
// assert that no near-zero artifacts are present (ie. 1.6 x 10^-16) before attempting inversion
|
|
46
|
+
// @param tolerance {Number} Maximum tolerance to small numbers, used to avoid artifacts on matrix inversion
|
|
47
|
+
].map((v) => v.map((c) => (math.abs(c) < constants.tolerance.lengthAngstrom ? 0 : c))) as [
|
|
48
|
+
Vector,
|
|
49
|
+
Vector,
|
|
50
|
+
Vector,
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
clone(): Cell {
|
|
55
|
+
return new (this.constructor as typeof Cell)(this.vectorsAsArray);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
cloneAndScaleByMatrix(matrix: number[][]) {
|
|
59
|
+
const newCell = this.clone();
|
|
60
|
+
newCell.scaleByMatrix(matrix);
|
|
61
|
+
return newCell;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Convert a point (in crystal coordinates) to cartesian.
|
|
66
|
+
*/
|
|
67
|
+
convertPointToCartesian(point: Point) {
|
|
68
|
+
return MULT(point, this.vectorsAsArray);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Convert a point (in cartesian coordinates) to crystal (fractional).
|
|
73
|
+
*/
|
|
74
|
+
convertPointToFractional(point: Point): Coordinate {
|
|
75
|
+
return MULT(point, INV(this.vectorsAsArray)) as Coordinate;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check whether a point is inside the cell.
|
|
80
|
+
* @param point - the point to conduct the check for.
|
|
81
|
+
* @param tolerance - numerical tolerance.
|
|
82
|
+
*/
|
|
83
|
+
isPointInsideCell(point: Point, tolerance = constants.tolerance.length): boolean {
|
|
84
|
+
return (
|
|
85
|
+
this.convertPointToFractional(point)
|
|
86
|
+
.map((c: number) => math.isBetweenZeroInclusiveAndOne(c, tolerance))
|
|
87
|
+
// @ts-ignore
|
|
88
|
+
.reduce((a: boolean, b: boolean): boolean => a && b)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Returns the index of the cell vector, most collinear with the testVector.
|
|
94
|
+
* @param testVector
|
|
95
|
+
*/
|
|
96
|
+
getMostCollinearVectorIndex(testVector: Vector): number {
|
|
97
|
+
// @ts-ignore
|
|
98
|
+
const angles = this.vectorsAsArray.map((v) => math.angleUpTo90(v, testVector));
|
|
99
|
+
return angles.findIndex((el) => el === math.min(angles));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Scale this cell by right-multiplying it to a matrix (nested array)
|
|
104
|
+
*/
|
|
105
|
+
scaleByMatrix(matrix: number[][]) {
|
|
106
|
+
// @ts-ignore
|
|
107
|
+
[this.vector1, this.vector2, this.vector3] = MATRIX_MULT(matrix, this.vectorsAsArray);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { LatticeTypeSchema } from "@mat3ra/esse/lib/js/types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Routines for calculating conventional cell vectors from primitive cell Bravais parameters.
|
|
5
|
+
* Following Setyawan, W., & Curtarolo, S. (2010). doi:10.1016/j.commatsci.2010.05.010
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const unitMatrix = [
|
|
9
|
+
[1, 0, 0],
|
|
10
|
+
[0, 1, 0],
|
|
11
|
+
[0, 0, 1],
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
// (Conventional cellVectors) = (Primitive cellVectors) * (PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIER matrix)
|
|
15
|
+
export const PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIERS = {
|
|
16
|
+
// PRIMITIVE => CONVENTIONAL
|
|
17
|
+
CUB: unitMatrix,
|
|
18
|
+
FCC: [
|
|
19
|
+
[-1, 1, 1],
|
|
20
|
+
[1, -1, 1],
|
|
21
|
+
[1, 1, -1],
|
|
22
|
+
],
|
|
23
|
+
BCC: [
|
|
24
|
+
[0, 1, 1],
|
|
25
|
+
[1, 0, 1],
|
|
26
|
+
[1, 1, 0],
|
|
27
|
+
],
|
|
28
|
+
TET: unitMatrix,
|
|
29
|
+
BCT: [
|
|
30
|
+
[0, 1, 1],
|
|
31
|
+
[1, 0, 1],
|
|
32
|
+
[1, 1, 0],
|
|
33
|
+
],
|
|
34
|
+
ORC: unitMatrix,
|
|
35
|
+
ORCF: [
|
|
36
|
+
[-1, 1, 1],
|
|
37
|
+
[1, -1, 1],
|
|
38
|
+
[1, 1, -1],
|
|
39
|
+
],
|
|
40
|
+
ORCI: [
|
|
41
|
+
[0, 1, 1],
|
|
42
|
+
[1, 0, 1],
|
|
43
|
+
[1, 1, 0],
|
|
44
|
+
],
|
|
45
|
+
ORCC: [
|
|
46
|
+
[1, -1, 0],
|
|
47
|
+
[1, 1, 0],
|
|
48
|
+
[0, 0, 1],
|
|
49
|
+
],
|
|
50
|
+
HEX: unitMatrix,
|
|
51
|
+
RHL: unitMatrix,
|
|
52
|
+
MCL: unitMatrix,
|
|
53
|
+
MCLC: [
|
|
54
|
+
[1, -1, 0],
|
|
55
|
+
[1, 1, 0],
|
|
56
|
+
[0, 0, 1],
|
|
57
|
+
],
|
|
58
|
+
TRI: unitMatrix,
|
|
59
|
+
TRIalt: unitMatrix,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const PRIMITIVE_TO_CONVENTIONAL_CELL_LATTICE_TYPES: {
|
|
63
|
+
[key in LatticeTypeSchema | "TRIalt"]: LatticeTypeSchema;
|
|
64
|
+
} = {
|
|
65
|
+
// PRIMITIVE => CONVENTIONAL
|
|
66
|
+
CUB: "CUB",
|
|
67
|
+
FCC: "CUB",
|
|
68
|
+
BCC: "CUB",
|
|
69
|
+
TET: "TET",
|
|
70
|
+
BCT: "TET",
|
|
71
|
+
ORC: "ORC",
|
|
72
|
+
ORCF: "ORC",
|
|
73
|
+
ORCI: "ORC",
|
|
74
|
+
ORCC: "ORC",
|
|
75
|
+
HEX: "HEX",
|
|
76
|
+
RHL: "RHL",
|
|
77
|
+
MCL: "MCL",
|
|
78
|
+
MCLC: "MCL",
|
|
79
|
+
TRI: "TRI",
|
|
80
|
+
// TODO: Legacy `TRI_alt` type, assert not used and remove
|
|
81
|
+
TRIalt: "TRI",
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export function isConventionalCellSameAsPrimitiveForLatticeType(
|
|
85
|
+
latticeType: LatticeTypeSchema,
|
|
86
|
+
): boolean {
|
|
87
|
+
const multiplier = PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIERS[latticeType || "TRI"];
|
|
88
|
+
return multiplier === unitMatrix;
|
|
89
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/* eslint no-unused-vars: 0 */
|
|
2
|
+
import { LatticeImplicitSchema } from "@mat3ra/esse/lib/js/types";
|
|
3
|
+
|
|
4
|
+
import { VectorsAsArray } from "../lattice/types";
|
|
5
|
+
import math from "../math";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Routines for calculating primitive cell vectors from conventional cell Bravais parameters.
|
|
9
|
+
* Following Setyawan, W., & Curtarolo, S. (2010). doi:10.1016/j.commatsci.2010.05.010
|
|
10
|
+
*/
|
|
11
|
+
const PRIMITIVE_CELLS = {
|
|
12
|
+
CUB: ({ a }: LatticeImplicitSchema): VectorsAsArray => {
|
|
13
|
+
return [
|
|
14
|
+
[a, 0, 0],
|
|
15
|
+
[0, a, 0],
|
|
16
|
+
[0, 0, a],
|
|
17
|
+
];
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
FCC: ({ a }: LatticeImplicitSchema): VectorsAsArray => {
|
|
21
|
+
return [
|
|
22
|
+
[0.0, a / 2, a / 2],
|
|
23
|
+
[a / 2, 0.0, a / 2],
|
|
24
|
+
[a / 2, a / 2, 0.0],
|
|
25
|
+
];
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
BCC: ({ a }: LatticeImplicitSchema): VectorsAsArray => {
|
|
29
|
+
return [
|
|
30
|
+
[-a / 2, a / 2, a / 2],
|
|
31
|
+
[a / 2, -a / 2, a / 2],
|
|
32
|
+
[a / 2, a / 2, -a / 2],
|
|
33
|
+
];
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
TET: ({ a, c }: LatticeImplicitSchema): VectorsAsArray => {
|
|
37
|
+
return [
|
|
38
|
+
[a, 0, 0],
|
|
39
|
+
[0, a, 0],
|
|
40
|
+
[0, 0, c],
|
|
41
|
+
];
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
BCT: ({ a, c }: LatticeImplicitSchema): VectorsAsArray => {
|
|
45
|
+
return [
|
|
46
|
+
[-a / 2, a / 2, c / 2],
|
|
47
|
+
[a / 2, -a / 2, c / 2],
|
|
48
|
+
[a / 2, a / 2, -c / 2],
|
|
49
|
+
];
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
ORC: ({ a, b, c }: LatticeImplicitSchema): VectorsAsArray => {
|
|
53
|
+
return [
|
|
54
|
+
[a, 0, 0],
|
|
55
|
+
[0, b, 0],
|
|
56
|
+
[0, 0, c],
|
|
57
|
+
];
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
ORCF: ({ a, b, c }: LatticeImplicitSchema): VectorsAsArray => {
|
|
61
|
+
return [
|
|
62
|
+
[0, b / 2, c / 2],
|
|
63
|
+
[a / 2, 0, c / 2],
|
|
64
|
+
[a / 2, b / 2, 0],
|
|
65
|
+
];
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
ORCI: ({ a, b, c }: LatticeImplicitSchema): VectorsAsArray => {
|
|
69
|
+
return [
|
|
70
|
+
[-a / 2, b / 2, c / 2],
|
|
71
|
+
[a / 2, -b / 2, c / 2],
|
|
72
|
+
[a / 2, b / 2, -c / 2],
|
|
73
|
+
];
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
ORCC: ({ a, b, c }: LatticeImplicitSchema): VectorsAsArray => {
|
|
77
|
+
return [
|
|
78
|
+
[a / 2, b / 2, 0],
|
|
79
|
+
[-a / 2, b / 2, 0],
|
|
80
|
+
[0, 0, c],
|
|
81
|
+
];
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
HEX: ({ a, c }: LatticeImplicitSchema): VectorsAsArray => {
|
|
85
|
+
return [
|
|
86
|
+
[a / 2, (-a * math.sqrt(3)) / 2, 0],
|
|
87
|
+
[a / 2, (a * math.sqrt(3)) / 2, 0],
|
|
88
|
+
[0, 0, c],
|
|
89
|
+
];
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
RHL: ({ a, alpha }: LatticeImplicitSchema): VectorsAsArray => {
|
|
93
|
+
const cosAlpha = math.cos((alpha / 180) * math.PI);
|
|
94
|
+
const cosHalfAlpha = math.sqrt((1 / 2) * (1 + cosAlpha));
|
|
95
|
+
const sinHalfAlpha = math.sqrt((1 / 2) * (1 - cosAlpha));
|
|
96
|
+
return [
|
|
97
|
+
[a * cosHalfAlpha, -a * sinHalfAlpha, 0.0],
|
|
98
|
+
[a * cosHalfAlpha, a * sinHalfAlpha, 0.0],
|
|
99
|
+
[
|
|
100
|
+
(a * cosAlpha) / cosHalfAlpha,
|
|
101
|
+
0.0,
|
|
102
|
+
a * math.sqrt(1 - (cosAlpha * cosAlpha) / (cosHalfAlpha * cosHalfAlpha)),
|
|
103
|
+
],
|
|
104
|
+
];
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
MCL: ({ a, b, c, alpha }: LatticeImplicitSchema): VectorsAsArray => {
|
|
108
|
+
const cosAlpha = math.cos((alpha / 180) * math.PI);
|
|
109
|
+
return [
|
|
110
|
+
[a, 0, 0],
|
|
111
|
+
[0, b, 0],
|
|
112
|
+
[0, c * cosAlpha, c * math.sqrt(1 - cosAlpha * cosAlpha)],
|
|
113
|
+
];
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
MCLC: ({ a, b, c, alpha }: LatticeImplicitSchema): VectorsAsArray => {
|
|
117
|
+
const cosAlpha = math.cos((alpha / 180) * math.PI);
|
|
118
|
+
return [
|
|
119
|
+
[a / 2, b / 2, 0],
|
|
120
|
+
[-a / 2, b / 2, 0],
|
|
121
|
+
[0, c * cosAlpha, c * math.sqrt(1 - cosAlpha * cosAlpha)],
|
|
122
|
+
];
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
// Algorithm from http://pymatgen.org/_modules/pymatgen/core/lattice.html (from_params)
|
|
126
|
+
TRI: ({ a, b, c, alpha, beta, gamma }: LatticeImplicitSchema): VectorsAsArray => {
|
|
127
|
+
// convert angles to Radians
|
|
128
|
+
// eslint-disable-next-line no-param-reassign
|
|
129
|
+
[alpha, beta, gamma] = [alpha, beta, gamma].map(
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
(x) => math.unit(x, "degree").to("rad").value,
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
const [cosAlpha, cosBeta, cosGamma] = [alpha, beta, gamma].map((x) => math.cos(x));
|
|
135
|
+
const [sinAlpha, sinBeta] = [alpha, beta].map((x) => math.sin(x));
|
|
136
|
+
const gammaStar = math.acos((cosAlpha * cosBeta - cosGamma) / (sinAlpha * sinBeta));
|
|
137
|
+
const cosGammaStar = math.cos(gammaStar);
|
|
138
|
+
const sinGammaStar = math.sin(gammaStar);
|
|
139
|
+
|
|
140
|
+
return [
|
|
141
|
+
[a * sinBeta, 0.0, a * cosBeta],
|
|
142
|
+
[-b * sinAlpha * cosGammaStar, b * sinAlpha * sinGammaStar, b * cosAlpha],
|
|
143
|
+
[0.0, 0.0, c],
|
|
144
|
+
];
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
// alternative implementation
|
|
148
|
+
TRIalt: ({ a, b, c, alpha, beta, gamma }: LatticeImplicitSchema): VectorsAsArray => {
|
|
149
|
+
const cosAlpha = math.cos((alpha / 180) * math.PI);
|
|
150
|
+
const cosBeta = math.cos((beta / 180) * math.PI);
|
|
151
|
+
const cosGamma = math.cos((gamma / 180) * math.PI);
|
|
152
|
+
const sinGamma = math.sqrt(1 - cosGamma * cosGamma);
|
|
153
|
+
return [
|
|
154
|
+
[a, 0.0, 0.0],
|
|
155
|
+
[b * cosGamma, b * sinGamma, 0.0],
|
|
156
|
+
[
|
|
157
|
+
c * cosBeta,
|
|
158
|
+
(c / sinGamma) * (cosAlpha - cosBeta * cosGamma),
|
|
159
|
+
(c / sinGamma) *
|
|
160
|
+
math.sqrt(
|
|
161
|
+
sinGamma * sinGamma -
|
|
162
|
+
cosAlpha * cosAlpha -
|
|
163
|
+
cosBeta * cosBeta +
|
|
164
|
+
2 * cosAlpha * cosBeta * cosGamma,
|
|
165
|
+
),
|
|
166
|
+
],
|
|
167
|
+
];
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Returns lattice vectors for a primitive cell for a lattice.
|
|
173
|
+
* @param lattice - Lattice instance.
|
|
174
|
+
* @param skipRounding - whether to skip rounding the lattice vectors.
|
|
175
|
+
* @return Cell.vectorsAsArray
|
|
176
|
+
*/
|
|
177
|
+
export function primitiveCell(
|
|
178
|
+
lattice: LatticeImplicitSchema,
|
|
179
|
+
skipRounding = false,
|
|
180
|
+
): VectorsAsArray {
|
|
181
|
+
const [vectorA, vectorB, vectorC] = PRIMITIVE_CELLS[lattice.type || "TRI"](lattice);
|
|
182
|
+
// set precision and remove JS floating point artifacts
|
|
183
|
+
if (!skipRounding) {
|
|
184
|
+
[vectorA, vectorB, vectorC].map((vec) =>
|
|
185
|
+
vec.map((c) => math.precise(c)).map(math.roundToZero),
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
return [vectorA, vectorB, vectorC];
|
|
189
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ArrayWithIds } from "../abstract/array_with_ids";
|
|
2
|
+
import { ObjectWithIdAndValue } from "../abstract/scalar_with_id";
|
|
3
|
+
|
|
4
|
+
export interface ConstraintValue extends Array<boolean> {
|
|
5
|
+
0: boolean;
|
|
6
|
+
1: boolean;
|
|
7
|
+
2: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type Constraint = ObjectWithIdAndValue<ConstraintValue>;
|
|
11
|
+
|
|
12
|
+
export class AtomicConstraints {
|
|
13
|
+
name: string;
|
|
14
|
+
|
|
15
|
+
values: ArrayWithIds<ConstraintValue>;
|
|
16
|
+
|
|
17
|
+
static fromArray(array: ConstraintValue[]) {
|
|
18
|
+
return new AtomicConstraints({ values: array });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create atomic constraints.
|
|
23
|
+
* @param {Object} config
|
|
24
|
+
* @param {ArrayWithIds|Array} config.values
|
|
25
|
+
*/
|
|
26
|
+
constructor({ values }: { values?: ConstraintValue[] }) {
|
|
27
|
+
this.name = "atomic_constraints";
|
|
28
|
+
this.values = new ArrayWithIds(values || []);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @example As below:
|
|
33
|
+
[
|
|
34
|
+
{
|
|
35
|
+
"id" : 0,
|
|
36
|
+
"value" : [
|
|
37
|
+
1,
|
|
38
|
+
1,
|
|
39
|
+
1
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
*/
|
|
44
|
+
toJSON() {
|
|
45
|
+
return {
|
|
46
|
+
name: this.name,
|
|
47
|
+
values: this.values.toJSON(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getByIndex(idx: number): ConstraintValue {
|
|
52
|
+
return this.values.getArrayElementByIndex(idx) || [];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get constraints for an atom with index as string.
|
|
57
|
+
* @param idx - atom index.
|
|
58
|
+
* @param mapFn (OPTIONAL) - a function to be applied to each constraint. By default 0 or 1 is returned.
|
|
59
|
+
*/
|
|
60
|
+
getAsStringByIndex(idx: number, mapFn = (val: boolean): string => (val ? "1" : "0")): string {
|
|
61
|
+
return this.getByIndex(idx).map(mapFn).join(" ");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LatticeImplicitSchema,
|
|
3
|
+
LatticeSchema,
|
|
4
|
+
LatticeTypeExtendedSchema,
|
|
5
|
+
} from "@mat3ra/esse/lib/js/types";
|
|
6
|
+
import lodash from "lodash";
|
|
7
|
+
import _ from "underscore";
|
|
8
|
+
|
|
9
|
+
import { Cell } from "../cell/cell";
|
|
10
|
+
import { primitiveCell } from "../cell/primitive_cell";
|
|
11
|
+
import { HASH_TOLERANCE } from "../constants";
|
|
12
|
+
import math from "../math";
|
|
13
|
+
import { FromVectorsProps, LatticeBravais } from "./lattice_bravais";
|
|
14
|
+
import { BravaisConfigProps, LatticeVectors } from "./lattice_vectors";
|
|
15
|
+
import { LATTICE_TYPE_CONFIGS } from "./types";
|
|
16
|
+
import { UnitCell, UnitCellProps } from "./unit_cell";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Scaling factor used to calculate the new lattice size for non-periodic systems.
|
|
20
|
+
* The scaling factor ensures that a non-periodic structure will have have a lattice greater than the structures size.
|
|
21
|
+
*/
|
|
22
|
+
export const nonPeriodicLatticeScalingFactor = 2.0;
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Container class for crystal lattice and associated methods.
|
|
26
|
+
* Follows Bravais convention for lattice types and contains lattice vectors within.
|
|
27
|
+
* Units for lattice vector coordinates are "angstroms", and "degrees" for the corresponding angles.
|
|
28
|
+
*/
|
|
29
|
+
export class Lattice extends LatticeBravais implements LatticeSchema {
|
|
30
|
+
vectors: LatticeVectors;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create a Lattice class from a config object.
|
|
34
|
+
* @param {Object} config - Config object. See LatticeVectors.fromBravais.
|
|
35
|
+
*/
|
|
36
|
+
constructor(config: Partial<LatticeImplicitSchema> = {}) {
|
|
37
|
+
super(config);
|
|
38
|
+
this.vectors = LatticeVectors.fromBravais(config);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create a Lattice class from a list of vectors.
|
|
43
|
+
* @param {Object} config - Config object. See LatticeBravais.fromVectors.
|
|
44
|
+
*/
|
|
45
|
+
static fromVectors(config: FromVectorsProps) {
|
|
46
|
+
return new Lattice(LatticeBravais.fromVectors(config).toJSON());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Serialize class instance to JSON.
|
|
51
|
+
* @example As below:
|
|
52
|
+
{
|
|
53
|
+
"a" : 3.867,
|
|
54
|
+
"b" : 3.867,
|
|
55
|
+
"c" : 3.867,
|
|
56
|
+
"alpha" : 60,
|
|
57
|
+
"beta" : 60,
|
|
58
|
+
"gamma" : 60,
|
|
59
|
+
"units" : {
|
|
60
|
+
"length" : "angstrom",
|
|
61
|
+
"angle" : "degree"
|
|
62
|
+
},
|
|
63
|
+
"type" : "FCC",
|
|
64
|
+
"vectors" : {
|
|
65
|
+
"a" : [
|
|
66
|
+
3.34892,
|
|
67
|
+
0,
|
|
68
|
+
1.9335
|
|
69
|
+
],
|
|
70
|
+
"b" : [
|
|
71
|
+
1.116307,
|
|
72
|
+
3.157392,
|
|
73
|
+
1.9335
|
|
74
|
+
],
|
|
75
|
+
"c" : [
|
|
76
|
+
0,
|
|
77
|
+
0,
|
|
78
|
+
3.867
|
|
79
|
+
],
|
|
80
|
+
"alat" : 1,
|
|
81
|
+
"units" : "angstrom"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
*/
|
|
85
|
+
toJSON(skipRounding = false): LatticeSchema {
|
|
86
|
+
const round = skipRounding ? (x: number) => x : Lattice._roundValue; // round values by default
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
a: round(this.a),
|
|
90
|
+
b: round(this.b),
|
|
91
|
+
c: round(this.c),
|
|
92
|
+
alpha: round(this.alpha),
|
|
93
|
+
beta: round(this.beta),
|
|
94
|
+
gamma: round(this.gamma),
|
|
95
|
+
units: {
|
|
96
|
+
length: this.units.length,
|
|
97
|
+
angle: this.units.angle,
|
|
98
|
+
},
|
|
99
|
+
type: this.type,
|
|
100
|
+
vectors: this.vectors.toJSON(),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
clone(extraContext: BravaisConfigProps) {
|
|
105
|
+
return new (this.constructor as typeof Lattice)({ ...this.toJSON(), ...extraContext });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get lattice vectors as a nested array
|
|
110
|
+
*/
|
|
111
|
+
get vectorArrays() {
|
|
112
|
+
return this.vectors.vectorArrays;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get Cell() {
|
|
116
|
+
return new Cell(this.vectorArrays);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get a short label for the type of the lattice, eg. "MCLC".
|
|
121
|
+
*/
|
|
122
|
+
get typeLabel(): string {
|
|
123
|
+
return lodash.get(
|
|
124
|
+
LATTICE_TYPE_CONFIGS.find((c) => c.code === this.type),
|
|
125
|
+
"label",
|
|
126
|
+
"Unknown",
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get a short label for the extended type of the lattice, eg. "MCLC-5".
|
|
132
|
+
*/
|
|
133
|
+
get typeExtended(): LatticeTypeExtendedSchema {
|
|
134
|
+
const { a, b, c, alpha, beta, gamma, type } = this;
|
|
135
|
+
const cosAlpha = math.cos((alpha / 180) * math.PI);
|
|
136
|
+
|
|
137
|
+
switch (type) {
|
|
138
|
+
case "BCT":
|
|
139
|
+
return c < a ? "BCT-1" : "BCT-2";
|
|
140
|
+
case "ORCF":
|
|
141
|
+
if (1 / (a * a) >= 1 / (b * b) + 1 / (c * c)) {
|
|
142
|
+
return "ORCF-1";
|
|
143
|
+
}
|
|
144
|
+
return "ORCF-2";
|
|
145
|
+
case "RHL":
|
|
146
|
+
return cosAlpha > 0 ? "RHL-1" : "RHL-2";
|
|
147
|
+
case "MCLC":
|
|
148
|
+
if (gamma >= 90) {
|
|
149
|
+
// MCLC-1,2
|
|
150
|
+
return "MCLC-1";
|
|
151
|
+
}
|
|
152
|
+
if ((b / c) * cosAlpha + ((b * b) / (a * a)) * (1 - cosAlpha * cosAlpha) <= 1) {
|
|
153
|
+
// MCLC-3,4
|
|
154
|
+
return "MCLC-3";
|
|
155
|
+
}
|
|
156
|
+
return "MCLC-5";
|
|
157
|
+
case "TRI":
|
|
158
|
+
if (alpha > 90 && beta > 90 && gamma >= 90) {
|
|
159
|
+
// TRI-1a,2a
|
|
160
|
+
return "TRI_1a";
|
|
161
|
+
}
|
|
162
|
+
return "TRI_1b";
|
|
163
|
+
default:
|
|
164
|
+
return type;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Calculate the volume of the lattice cell.
|
|
170
|
+
*/
|
|
171
|
+
get volume(): number {
|
|
172
|
+
return math.abs(math.det(this.vectorArrays));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/*
|
|
176
|
+
* Returns a "default" primitive lattice by type, with lattice parameters scaled by the length of "a",
|
|
177
|
+
* @param latticeConfig {Object} LatticeBravais config (see constructor)
|
|
178
|
+
*/
|
|
179
|
+
static getDefaultPrimitiveLatticeConfigByType(latticeConfig: LatticeImplicitSchema) {
|
|
180
|
+
const f_ = Lattice._roundValue;
|
|
181
|
+
// construct new primitive cell using lattice parameters and skip rounding the vectors
|
|
182
|
+
const pCell = primitiveCell(latticeConfig, true);
|
|
183
|
+
// create new lattice from primitive cell
|
|
184
|
+
const newLattice = { ...Lattice.fromVectorArrays(pCell, latticeConfig.type) };
|
|
185
|
+
// preserve the new type and scale back the lattice parameters
|
|
186
|
+
const k = latticeConfig.a / newLattice.a;
|
|
187
|
+
|
|
188
|
+
return Object.assign(newLattice, {
|
|
189
|
+
a: f_(newLattice.a * k),
|
|
190
|
+
b: f_(newLattice.b * k),
|
|
191
|
+
c: f_(newLattice.c * k),
|
|
192
|
+
alpha: f_(newLattice.alpha),
|
|
193
|
+
beta: f_(newLattice.beta),
|
|
194
|
+
gamma: f_(newLattice.gamma),
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// TODO: remove
|
|
199
|
+
get unitCell() {
|
|
200
|
+
const vectors = [..._.flatten(this.vectorArrays), this.units.length] as UnitCellProps;
|
|
201
|
+
return new UnitCell(vectors);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Returns a string further used for the calculation of an unique hash.
|
|
206
|
+
* @param isScaled - Whether to scale the vectors by the length of the first vector initially.
|
|
207
|
+
*/
|
|
208
|
+
getHashString(isScaled = false): string {
|
|
209
|
+
// lattice vectors must be measured in angstroms
|
|
210
|
+
const scaleK = isScaled ? this.a : 1;
|
|
211
|
+
const scaledLattice = {
|
|
212
|
+
...this,
|
|
213
|
+
a: this.a / scaleK,
|
|
214
|
+
b: this.b / scaleK,
|
|
215
|
+
c: this.c / scaleK,
|
|
216
|
+
};
|
|
217
|
+
// form lattice string
|
|
218
|
+
return `${[
|
|
219
|
+
scaledLattice.a,
|
|
220
|
+
scaledLattice.b,
|
|
221
|
+
scaledLattice.c,
|
|
222
|
+
scaledLattice.alpha,
|
|
223
|
+
scaledLattice.beta,
|
|
224
|
+
scaledLattice.gamma,
|
|
225
|
+
]
|
|
226
|
+
.map((x) => math.round(x, HASH_TOLERANCE))
|
|
227
|
+
.join(";")};`;
|
|
228
|
+
}
|
|
229
|
+
}
|