@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.
Files changed (176) hide show
  1. package/.babelrc +10 -0
  2. package/.eslintrc.json +11 -0
  3. package/.mocharc.json +5 -0
  4. package/.prettierignore +1 -0
  5. package/.prettierrc +6 -0
  6. package/LICENSE.md +15 -0
  7. package/README.md +167 -0
  8. package/dist/abstract/array_with_ids.d.ts +43 -0
  9. package/dist/abstract/array_with_ids.js +88 -0
  10. package/dist/abstract/scalar_with_id.d.ts +25 -0
  11. package/dist/abstract/scalar_with_id.js +44 -0
  12. package/dist/basis/basis.d.ts +269 -0
  13. package/dist/basis/basis.js +499 -0
  14. package/dist/basis/constrained_basis.d.ts +56 -0
  15. package/dist/basis/constrained_basis.js +90 -0
  16. package/dist/basis/types.d.ts +1 -0
  17. package/dist/basis/types.js +2 -0
  18. package/dist/cell/cell.d.ts +45 -0
  19. package/dist/cell/cell.js +88 -0
  20. package/dist/cell/conventional_cell.d.ts +22 -0
  21. package/dist/cell/conventional_cell.js +83 -0
  22. package/dist/cell/primitive_cell.d.ts +9 -0
  23. package/dist/cell/primitive_cell.js +166 -0
  24. package/dist/constants.d.ts +2 -0
  25. package/dist/constants.js +25 -0
  26. package/dist/constraints/constraints.d.ts +45 -0
  27. package/dist/constraints/constraints.js +49 -0
  28. package/dist/lattice/lattice.d.ts +104 -0
  29. package/dist/lattice/lattice.js +208 -0
  30. package/dist/lattice/lattice_bravais.d.ts +59 -0
  31. package/dist/lattice/lattice_bravais.js +120 -0
  32. package/dist/lattice/lattice_vectors.d.ts +46 -0
  33. package/dist/lattice/lattice_vectors.js +98 -0
  34. package/dist/lattice/reciprocal/lattice_reciprocal.d.ts +75 -0
  35. package/dist/lattice/reciprocal/lattice_reciprocal.js +148 -0
  36. package/dist/lattice/reciprocal/paths.d.ts +24 -0
  37. package/dist/lattice/reciprocal/paths.js +136 -0
  38. package/dist/lattice/reciprocal/symmetry_points.d.ts +8 -0
  39. package/dist/lattice/reciprocal/symmetry_points.js +866 -0
  40. package/dist/lattice/types.d.ts +49 -0
  41. package/dist/lattice/types.js +127 -0
  42. package/dist/lattice/unit_cell.d.ts +30 -0
  43. package/dist/lattice/unit_cell.js +31 -0
  44. package/dist/made.d.ts +40 -0
  45. package/dist/made.js +39 -0
  46. package/dist/material.d.ts +1562 -0
  47. package/dist/material.js +317 -0
  48. package/dist/math.d.ts +395 -0
  49. package/dist/math.js +7 -0
  50. package/dist/parsers/cif.d.ts +10 -0
  51. package/dist/parsers/cif.js +21 -0
  52. package/dist/parsers/errors.d.ts +5 -0
  53. package/dist/parsers/errors.js +11 -0
  54. package/dist/parsers/espresso.d.ts +10 -0
  55. package/dist/parsers/espresso.js +24 -0
  56. package/dist/parsers/native_format_parsers.d.ts +26 -0
  57. package/dist/parsers/native_format_parsers.js +52 -0
  58. package/dist/parsers/parsers.d.ts +13 -0
  59. package/dist/parsers/parsers.js +17 -0
  60. package/dist/parsers/poscar.d.ts +31 -0
  61. package/dist/parsers/poscar.js +180 -0
  62. package/dist/parsers/xyz.d.ts +62 -0
  63. package/dist/parsers/xyz.js +167 -0
  64. package/dist/parsers/xyz_combinatorial_basis.d.ts +64 -0
  65. package/dist/parsers/xyz_combinatorial_basis.js +241 -0
  66. package/dist/tools/basis.d.ts +22 -0
  67. package/dist/tools/basis.js +100 -0
  68. package/dist/tools/cell.d.ts +9 -0
  69. package/dist/tools/cell.js +39 -0
  70. package/dist/tools/index.d.ts +11 -0
  71. package/dist/tools/index.js +15 -0
  72. package/dist/tools/material.d.ts +25 -0
  73. package/dist/tools/material.js +54 -0
  74. package/dist/tools/supercell.d.ts +22 -0
  75. package/dist/tools/supercell.js +62 -0
  76. package/dist/tools/surface.d.ts +10 -0
  77. package/dist/tools/surface.js +147 -0
  78. package/dist/types.d.ts +3 -0
  79. package/dist/types.js +2 -0
  80. package/package.json +89 -0
  81. package/pyproject.toml +77 -0
  82. package/src/js/abstract/array_with_ids.ts +100 -0
  83. package/src/js/abstract/scalar_with_id.ts +53 -0
  84. package/src/js/basis/basis.ts +607 -0
  85. package/src/js/basis/constrained_basis.ts +107 -0
  86. package/src/js/basis/types.ts +1 -0
  87. package/src/js/cell/cell.ts +109 -0
  88. package/src/js/cell/conventional_cell.ts +89 -0
  89. package/src/js/cell/primitive_cell.ts +189 -0
  90. package/src/js/constants.js +4 -0
  91. package/src/js/constraints/constraints.ts +63 -0
  92. package/src/js/lattice/lattice.ts +229 -0
  93. package/src/js/lattice/lattice_bravais.ts +170 -0
  94. package/src/js/lattice/lattice_vectors.ts +126 -0
  95. package/src/js/lattice/reciprocal/lattice_reciprocal.js +155 -0
  96. package/src/js/lattice/reciprocal/paths.js +134 -0
  97. package/src/js/lattice/reciprocal/symmetry_points.ts +886 -0
  98. package/src/js/lattice/types.ts +142 -0
  99. package/src/js/lattice/unit_cell.ts +66 -0
  100. package/src/js/made.js +36 -0
  101. package/src/js/material.ts +398 -0
  102. package/src/js/math.js +6 -0
  103. package/src/js/parsers/cif.js +22 -0
  104. package/src/js/parsers/errors.js +7 -0
  105. package/src/js/parsers/espresso.ts +30 -0
  106. package/src/js/parsers/native_format_parsers.js +51 -0
  107. package/src/js/parsers/parsers.js +13 -0
  108. package/src/js/parsers/poscar.ts +201 -0
  109. package/src/js/parsers/xyz.ts +216 -0
  110. package/src/js/parsers/xyz_combinatorial_basis.js +243 -0
  111. package/src/js/tools/basis.js +116 -0
  112. package/src/js/tools/cell.js +36 -0
  113. package/src/js/tools/index.js +11 -0
  114. package/src/js/tools/material.js +60 -0
  115. package/src/js/tools/supercell.ts +80 -0
  116. package/src/js/tools/surface.js +176 -0
  117. package/src/js/types.ts +4 -0
  118. package/src/py/__init__.py +0 -0
  119. package/src/py/mat3ra/__init__.py +0 -0
  120. package/src/py/mat3ra/made/__init__.py +5 -0
  121. package/tests/.gitattributes +1 -0
  122. package/tests/fixtures/AsGe-basis.json +3 -0
  123. package/tests/fixtures/C2H4-translated.json +3 -0
  124. package/tests/fixtures/C2H4.json +3 -0
  125. package/tests/fixtures/FeLiSi-basis.json +3 -0
  126. package/tests/fixtures/FeO.json +3 -0
  127. package/tests/fixtures/Ge2-basis.json +3 -0
  128. package/tests/fixtures/Graphene.json +3 -0
  129. package/tests/fixtures/Graphene.poscar +3 -0
  130. package/tests/fixtures/H2+H-final.json +3 -0
  131. package/tests/fixtures/H2+H-image.json +3 -0
  132. package/tests/fixtures/H2+H-initial.json +3 -0
  133. package/tests/fixtures/H2O.poscar +3 -0
  134. package/tests/fixtures/LiFeSi-basis.json +3 -0
  135. package/tests/fixtures/Na.json +3 -0
  136. package/tests/fixtures/Na4Cl4-cartesian.json +3 -0
  137. package/tests/fixtures/Na4Cl4.json +3 -0
  138. package/tests/fixtures/Na4Cl4.poscar +3 -0
  139. package/tests/fixtures/Ni-hex.json +3 -0
  140. package/tests/fixtures/Ni-hex.poscar +3 -0
  141. package/tests/fixtures/OSi-basis.json +3 -0
  142. package/tests/fixtures/Si-hex.json +3 -0
  143. package/tests/fixtures/Si-hex.poscar +3 -0
  144. package/tests/fixtures/Si-pwscf.in +3 -0
  145. package/tests/fixtures/Si-slab.json +3 -0
  146. package/tests/fixtures/Si-supercell.json +3 -0
  147. package/tests/fixtures/Si.json +3 -0
  148. package/tests/fixtures/Si2-basis-repeated.json +3 -0
  149. package/tests/fixtures/Si2-basis.json +3 -0
  150. package/tests/fixtures/Zr1H23Zr1H1.json +3 -0
  151. package/tests/fixtures/Zr1H23Zr1H1.poscar +3 -0
  152. package/tests/fixtures/atomic-constraints.json +3 -0
  153. package/tests/js/basis/basis.js +221 -0
  154. package/tests/js/cell/cell.js +21 -0
  155. package/tests/js/cell/primitive_cell.js +17 -0
  156. package/tests/js/constraints/constraints.js +27 -0
  157. package/tests/js/enums.js +40 -0
  158. package/tests/js/lattice/lattice.js +31 -0
  159. package/tests/js/lattice/lattice_bravais.js +17 -0
  160. package/tests/js/lattice/lattice_reciprocal.js +99 -0
  161. package/tests/js/lattice/lattice_vectors.js +10 -0
  162. package/tests/js/material.test.js +11 -0
  163. package/tests/js/parsers/espresso.js +12 -0
  164. package/tests/js/parsers/native_formats.js +30 -0
  165. package/tests/js/parsers/poscar.js +21 -0
  166. package/tests/js/parsers/xyz.js +25 -0
  167. package/tests/js/parsers/xyz_combinatorial_basis.js +153 -0
  168. package/tests/js/setup.js +6 -0
  169. package/tests/js/tools/basis.js +18 -0
  170. package/tests/js/tools/supercell.js +23 -0
  171. package/tests/js/tools/surface.js +12 -0
  172. package/tests/js/utils.js +17 -0
  173. package/tests/py/__init__.py +0 -0
  174. package/tests/py/unit/__init__.py +0 -0
  175. package/tests/py/unit/test_sample.py +10 -0
  176. 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,4 @@
1
+ // TODO: adjust the imports and remove the need for re-exporting
2
+ export * from "@exabyte-io/code.js/dist/constants";
3
+ // eslint-disable-next-line no-restricted-exports
4
+ export { default } from "@exabyte-io/code.js/dist/constants";
@@ -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
+ }