@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,142 @@
1
+ import { ArrayOf3NumberElementsSchema, LatticeTypeSchema } from "@mat3ra/esse/lib/js/types";
2
+
3
+ export const DEFAULT_LATTICE_UNITS = {
4
+ // by default lattice vectors shall be measured in angstrom, angles - in degrees
5
+ length: {
6
+ angstrom: "angstrom",
7
+ },
8
+ angle: {
9
+ degree: "degree",
10
+ },
11
+ };
12
+
13
+ export enum LatticeTypeExtended {
14
+ BCC = "BCC",
15
+ BCT_1 = "BCT-1",
16
+ BCT_2 = "BCT-2",
17
+ CUB = "CUB",
18
+ FCC = "FCC",
19
+ HEX = "HEX",
20
+ MCL = "MCL",
21
+ MCLC_1 = "MCLC-1",
22
+ MCLC_2 = "MCLC-2",
23
+ MCLC_3 = "MCLC-3",
24
+ MCLC_4 = "MCLC-4",
25
+ MCLC_5 = "MCLC-5",
26
+ ORC = "ORC",
27
+ ORCC = "ORCC",
28
+ ORCF_1 = "ORCF-1",
29
+ ORCF_2 = "ORCF-2",
30
+ ORCF_3 = "ORCF-3",
31
+ ORCI = "ORCI",
32
+ RHL_1 = "RHL-1",
33
+ RHL_2 = "RHL-2",
34
+ TET = "TET",
35
+ TRI_1a = "TRI_1a",
36
+ TRI_2a = "TRI_2a",
37
+ TRI_1b = "TRI_1b",
38
+ }
39
+
40
+ export type Vector = ArrayOf3NumberElementsSchema;
41
+
42
+ export interface VectorsAsArray extends Array<Vector> {
43
+ 0: Vector;
44
+ 1: Vector;
45
+ 2: Vector;
46
+ }
47
+
48
+ interface LatticeTypeConfig {
49
+ label: string;
50
+ code: LatticeTypeSchema;
51
+ editables: string[];
52
+ editablesConventional: string[];
53
+ }
54
+
55
+ export const LATTICE_TYPE_CONFIGS: LatticeTypeConfig[] = [
56
+ {
57
+ label: "Simple Cubic",
58
+ code: "CUB",
59
+ // editables for primitive cell => WARNING: not tested
60
+ editables: ["a"],
61
+ // editables for conventional cell, taken from the publication above
62
+ editablesConventional: ["a"],
63
+ },
64
+ {
65
+ label: "Face-centered Cubic",
66
+ code: "FCC",
67
+ editables: ["a"],
68
+ editablesConventional: ["a"],
69
+ },
70
+ {
71
+ label: "Body-centered Cubic",
72
+ code: "BCC",
73
+ editables: ["a"],
74
+ editablesConventional: ["a"],
75
+ },
76
+ {
77
+ label: "Tetragonal",
78
+ code: "TET",
79
+ editables: ["a", "c"],
80
+ editablesConventional: ["a", "c"],
81
+ },
82
+ {
83
+ label: "Body-centered Tetragonal",
84
+ code: "BCT",
85
+ editables: ["a"],
86
+ editablesConventional: ["a", "c"],
87
+ },
88
+ {
89
+ label: "Orthorombic",
90
+ code: "ORC",
91
+ editables: ["a", "b", "c"],
92
+ editablesConventional: ["a", "b", "c"],
93
+ },
94
+ {
95
+ label: "Orthorombic Face-centered",
96
+ code: "ORCF",
97
+ editables: ["a", "b", "c"],
98
+ editablesConventional: ["a", "b", "c"],
99
+ },
100
+ {
101
+ label: "Orthorombic Body-centered",
102
+ code: "ORCI",
103
+ editables: ["a", "alpha", "gamma"],
104
+ editablesConventional: ["a", "b", "c"],
105
+ },
106
+ {
107
+ label: "Orthorombic Base-centered",
108
+ code: "ORCC",
109
+ editables: ["a", "c", "alpha"],
110
+ editablesConventional: ["a", "b", "c"],
111
+ },
112
+ {
113
+ label: "Hexagonal",
114
+ code: "HEX",
115
+ editables: ["a", "c"],
116
+ editablesConventional: ["a", "c"],
117
+ },
118
+ {
119
+ label: "Rhombohedral",
120
+ code: "RHL",
121
+ editables: ["a", "alpha"],
122
+ editablesConventional: ["a", "alpha"],
123
+ },
124
+ {
125
+ label: "Monoclinic",
126
+ code: "MCL",
127
+ editables: ["a", "b", "c", "alpha"],
128
+ editablesConventional: ["a", "b", "c", "alpha"],
129
+ },
130
+ {
131
+ label: "Monoclinic Base-centered",
132
+ code: "MCLC",
133
+ editables: ["a", "c", "alpha", "gamma"],
134
+ editablesConventional: ["a", "b", "c", "alpha"],
135
+ },
136
+ {
137
+ label: "Triclinic",
138
+ code: "TRI",
139
+ editables: ["a", "b", "c", "alpha", "beta", "gamma"],
140
+ editablesConventional: ["a", "b", "c", "alpha", "beta", "gamma"],
141
+ },
142
+ ];
@@ -0,0 +1,66 @@
1
+ import { Vector } from "./types";
2
+
3
+ export type UnitCellProps = [
4
+ number,
5
+ number,
6
+ number,
7
+ number,
8
+ number,
9
+ number,
10
+ number,
11
+ number,
12
+ number,
13
+ string,
14
+ ];
15
+
16
+ // TODO: refactor and remove the need for UnitCell
17
+ export class UnitCell {
18
+ ax: number;
19
+
20
+ ay: number;
21
+
22
+ az: number;
23
+
24
+ bx: number;
25
+
26
+ by: number;
27
+
28
+ bz: number;
29
+
30
+ cx: number;
31
+
32
+ cy: number;
33
+
34
+ cz: number;
35
+
36
+ units: string;
37
+
38
+ constructor([ax, ay, az, bx, by, bz, cx, cy, cz, units]: UnitCellProps) {
39
+ this.ax = ax;
40
+ this.ay = ay;
41
+ this.az = az;
42
+ this.bx = bx;
43
+ this.by = by;
44
+ this.bz = bz;
45
+ this.cx = cx;
46
+ this.cy = cy;
47
+ this.cz = cz;
48
+ this.units = units;
49
+ }
50
+
51
+ vectorA(): Vector {
52
+ return [this.ax, this.ay, this.az];
53
+ }
54
+
55
+ vectorB(): Vector {
56
+ return [this.bx, this.by, this.bz];
57
+ }
58
+
59
+ vectorC(): Vector {
60
+ return [this.cx, this.cy, this.cz];
61
+ }
62
+
63
+ axes(): [Vector, Vector, Vector] {
64
+ return [this.vectorA(), this.vectorB(), this.vectorC()];
65
+ }
66
+ }
package/src/js/made.js ADDED
@@ -0,0 +1,36 @@
1
+ import { ArrayWithIds } from "./abstract/array_with_ids";
2
+ import { Basis } from "./basis/basis";
3
+ import { ATOMIC_COORD_UNITS, coefficients, tolerance, units } from "./constants";
4
+ import { AtomicConstraints } from "./constraints/constraints";
5
+ import { Lattice, nonPeriodicLatticeScalingFactor } from "./lattice/lattice";
6
+ import { ReciprocalLattice } from "./lattice/reciprocal/lattice_reciprocal";
7
+ import { DEFAULT_LATTICE_UNITS, LATTICE_TYPE_CONFIGS } from "./lattice/types";
8
+ import { defaultMaterialConfig, Material, MaterialMixin } from "./material";
9
+ import MadeMath from "./math";
10
+ import parsers from "./parsers/parsers";
11
+ import tools from "./tools/index";
12
+
13
+ export const Made = {
14
+ coefficients,
15
+ tolerance,
16
+ units,
17
+ ATOMIC_COORD_UNITS,
18
+ math: MadeMath,
19
+
20
+ Material,
21
+ MaterialMixin,
22
+ defaultMaterialConfig,
23
+ Lattice,
24
+ nonPeriodicLatticeScalingFactor,
25
+ ReciprocalLattice,
26
+ Basis,
27
+ AtomicConstraints,
28
+
29
+ parsers,
30
+ tools,
31
+ LATTICE_TYPE_CONFIGS,
32
+ DEFAULT_LATTICE_UNITS,
33
+ primitive: {
34
+ ArrayWithIds,
35
+ },
36
+ };
@@ -0,0 +1,398 @@
1
+ import { HasConsistencyChecksHasMetadataNamedDefaultableInMemoryEntity } from "@exabyte-io/code.js/dist/entity";
2
+ import { AnyObject } from "@exabyte-io/code.js/dist/entity/in_memory";
3
+ import MaterialJSONSchemaObject from "@mat3ra/esse/lib/js/schema/material.json";
4
+ import {
5
+ ConsistencyCheck,
6
+ DerivedPropertiesSchema,
7
+ FileSourceSchema,
8
+ InChIRepresentationSchema,
9
+ MaterialSchema,
10
+ } from "@mat3ra/esse/lib/js/types";
11
+ import CryptoJS from "crypto-js";
12
+
13
+ import { ConstrainedBasis } from "./basis/constrained_basis";
14
+ import {
15
+ isConventionalCellSameAsPrimitiveForLatticeType,
16
+ PRIMITIVE_TO_CONVENTIONAL_CELL_LATTICE_TYPES,
17
+ PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIERS,
18
+ } from "./cell/conventional_cell";
19
+ import { ATOMIC_COORD_UNITS, units } from "./constants";
20
+ import { Constraint } from "./constraints/constraints";
21
+ import { Lattice } from "./lattice/lattice";
22
+ import { BravaisConfigProps } from "./lattice/lattice_vectors";
23
+ import parsers from "./parsers/parsers";
24
+ import { BasisConfig } from "./parsers/xyz";
25
+ // TODO: fix dependency cycle below
26
+ // eslint-disable-next-line import/no-cycle
27
+ import supercellTools from "./tools/supercell";
28
+ import { MaterialJSON } from "./types";
29
+
30
+ export const defaultMaterialConfig = {
31
+ name: "Silicon FCC",
32
+ basis: {
33
+ elements: [
34
+ {
35
+ id: 1,
36
+ value: "Si",
37
+ },
38
+ {
39
+ id: 2,
40
+ value: "Si",
41
+ },
42
+ ],
43
+ coordinates: [
44
+ {
45
+ id: 1,
46
+ value: [0.0, 0.0, 0.0],
47
+ },
48
+ {
49
+ id: 2,
50
+ value: [0.25, 0.25, 0.25],
51
+ },
52
+ ],
53
+ units: ATOMIC_COORD_UNITS.crystal,
54
+ },
55
+ lattice: {
56
+ // Primitive cell for Diamond FCC Silicon at ambient conditions
57
+ type: "FCC",
58
+ a: 3.867,
59
+ b: 3.867,
60
+ c: 3.867,
61
+ alpha: 60,
62
+ beta: 60,
63
+ gamma: 60,
64
+ units: {
65
+ length: units.angstrom,
66
+ angle: units.degree,
67
+ },
68
+ },
69
+ };
70
+
71
+ export interface MaterialSchemaJSON extends MaterialSchema, AnyObject {}
72
+
73
+ type MaterialBaseEntity = InstanceType<
74
+ typeof HasConsistencyChecksHasMetadataNamedDefaultableInMemoryEntity
75
+ >;
76
+
77
+ export type MaterialBaseEntityConstructor<T extends MaterialBaseEntity = MaterialBaseEntity> = new (
78
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
79
+ ...args: any[]
80
+ ) => T;
81
+
82
+ export function MaterialMixin<
83
+ T extends MaterialBaseEntityConstructor = MaterialBaseEntityConstructor,
84
+ >(superclass: T) {
85
+ class MadeMaterial extends superclass {
86
+ declare _json: MaterialSchemaJSON;
87
+
88
+ static readonly jsonSchema = MaterialJSONSchemaObject;
89
+
90
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
+ constructor(...config: any[]) {
92
+ super(...config);
93
+ this.name = super.name || this.formula;
94
+ }
95
+
96
+ toJSON(): MaterialJSON {
97
+ return {
98
+ ...super.toJSON(),
99
+ lattice: this.Lattice.toJSON(),
100
+ basis: this.Basis.toJSON(),
101
+ name: this.name,
102
+ isNonPeriodic: this.isNonPeriodic,
103
+ };
104
+ }
105
+
106
+ static get defaultConfig() {
107
+ return defaultMaterialConfig;
108
+ }
109
+
110
+ get src() {
111
+ return this.prop<FileSourceSchema>("src") as FileSourceSchema;
112
+ }
113
+
114
+ set src(src: FileSourceSchema) {
115
+ this.setProp("src", src);
116
+ }
117
+
118
+ updateFormula() {
119
+ this.setProp("formula", this.Basis.formula);
120
+ this.setProp("unitCellFormula", this.Basis.unitCellFormula);
121
+ }
122
+
123
+ /**
124
+ * Gets Bolean value for whether or not a material is non-periodic vs periodic.
125
+ * False = periodic, True = non-periodic
126
+ */
127
+ get isNonPeriodic(): boolean {
128
+ return this.prop("isNonPeriodic", false);
129
+ }
130
+
131
+ /**
132
+ * @summary Sets the value of isNonPeriodic based on Boolean value passed as an argument.
133
+ */
134
+ set isNonPeriodic(bool: boolean) {
135
+ this.setProp("isNonPeriodic", bool);
136
+ }
137
+
138
+ /**
139
+ * @summary Returns the specific derived property (as specified by name) for a material.
140
+ */
141
+ getDerivedPropertyByName(name: string) {
142
+ return this.getDerivedProperties().find((x) => x.name === name);
143
+ }
144
+
145
+ /**
146
+ * @summary Returns the derived properties array for a material.
147
+ */
148
+ getDerivedProperties(): DerivedPropertiesSchema {
149
+ return this.prop("derivedProperties", []);
150
+ }
151
+
152
+ /**
153
+ * Gets material's formula
154
+ */
155
+ get formula(): string {
156
+ return this.prop("formula") || this.Basis.formula;
157
+ }
158
+
159
+ get unitCellFormula(): string {
160
+ return this.prop("unitCellFormula") || this.Basis.unitCellFormula;
161
+ }
162
+
163
+ /**
164
+ * @param textOrObject Basis text or JSON object.
165
+ * @param format Format (xyz, etc.)
166
+ * @param unitz crystal/cartesian
167
+ */
168
+ setBasis(textOrObject: string | BasisConfig, format?: string, unitz?: string) {
169
+ let basis: BasisConfig | undefined;
170
+ switch (format) {
171
+ case "xyz":
172
+ basis = parsers.xyz.toBasisConfig(textOrObject as string, unitz);
173
+ break;
174
+ default:
175
+ basis = textOrObject as BasisConfig;
176
+ }
177
+ this.setProp("basis", basis);
178
+ this.updateFormula();
179
+ }
180
+
181
+ setBasisConstraints(constraints: Constraint[]) {
182
+ this.setBasis({ ...this.basis, constraints });
183
+ }
184
+
185
+ get basis(): BasisConfig {
186
+ return this.prop<BasisConfig>("basis") as BasisConfig;
187
+ }
188
+
189
+ // returns the instance of {ConstrainedBasis} class
190
+ get Basis() {
191
+ return new ConstrainedBasis({
192
+ ...this.basis,
193
+ cell: this.Lattice.vectorArrays,
194
+ });
195
+ }
196
+
197
+ /**
198
+ * High-level access to unique elements from material instead of basis.
199
+ */
200
+ get uniqueElements() {
201
+ return this.Basis.uniqueElements;
202
+ }
203
+
204
+ get lattice(): BravaisConfigProps | undefined {
205
+ return this.prop("lattice", undefined);
206
+ }
207
+
208
+ set lattice(config: BravaisConfigProps | undefined) {
209
+ this.setProp("lattice", config);
210
+ }
211
+
212
+ get Lattice(): Lattice {
213
+ return new Lattice(this.lattice);
214
+ }
215
+
216
+ /**
217
+ * Returns the inchi string from the derivedProperties for a non-periodic material, or throws an error if the
218
+ * inchi cannot be found.
219
+ * @returns {String}
220
+ */
221
+ getInchiStringForHash(): string {
222
+ const inchi = this.getDerivedPropertyByName("inchi");
223
+ if (inchi) {
224
+ return (inchi as InChIRepresentationSchema).value;
225
+ }
226
+ throw new Error("Hash cannot be created. Missing InChI string in derivedProperties");
227
+ }
228
+
229
+ /**
230
+ * Calculates hash from basis and lattice. Algorithm expects the following:
231
+ * - asserts lattice units to be angstrom
232
+ * - asserts basis units to be crystal
233
+ * - asserts basis coordinates and lattice measurements are rounded to hash precision
234
+ * - forms strings for lattice and basis
235
+ * - creates MD5 hash from basisStr + latticeStr + salt
236
+ * @param salt Salt for hashing, empty string by default.
237
+ * @param isScaled Whether to scale the lattice parameter 'a' to 1.
238
+ */
239
+ calculateHash(salt = "", isScaled = false, bypassNonPeriodicCheck = false): string {
240
+ let message;
241
+ if (!this.isNonPeriodic || bypassNonPeriodicCheck) {
242
+ message =
243
+ this.Basis.hashString + "#" + this.Lattice.getHashString(isScaled) + "#" + salt;
244
+ } else {
245
+ message = this.getInchiStringForHash();
246
+ }
247
+ return CryptoJS.MD5(message).toString();
248
+ }
249
+
250
+ set hash(hash: string) {
251
+ this.setProp("hash", hash);
252
+ }
253
+
254
+ get hash(): string {
255
+ return this.prop("hash") as string;
256
+ }
257
+
258
+ /**
259
+ * Calculates hash from basis and lattice as above + scales lattice properties to make lattice.a = 1
260
+ */
261
+ get scaledHash(): string {
262
+ return this.calculateHash("", true);
263
+ }
264
+
265
+ /**
266
+ * Converts basis to crystal/fractional coordinates.
267
+ */
268
+ toCrystal() {
269
+ const basis = this.Basis;
270
+ basis.toCrystal();
271
+ this.setProp("basis", basis.toJSON());
272
+ }
273
+
274
+ /**
275
+ * Converts current material's basis coordinates to cartesian.
276
+ * No changes if coordinates already cartesian.
277
+ */
278
+ toCartesian() {
279
+ const basis = this.Basis;
280
+ basis.toCartesian();
281
+ this.setProp("basis", basis.toJSON());
282
+ }
283
+
284
+ /**
285
+ * Returns material's basis in XYZ format.
286
+ */
287
+ getBasisAsXyz(fractional = false): string {
288
+ return parsers.xyz.fromMaterial(this.toJSON(), fractional);
289
+ }
290
+
291
+ /**
292
+ * Returns material in Quantum Espresso output format:
293
+ * ```
294
+ * CELL_PARAMETERS (angstroms)
295
+ * -0.543131284 -0.000000000 0.543131284
296
+ * -0.000000000 0.543131284 0.543131284
297
+ * -0.543131284 0.543131284 0.000000000
298
+ *
299
+ * ATOMIC_POSITIONS (crystal)
300
+ * Si 0.000000000 0.000000000 -0.000000000
301
+ * Si 0.250000000 0.250000000 0.250000000
302
+ * ```
303
+ */
304
+ getAsQEFormat(): string {
305
+ return parsers.espresso.toEspressoFormat(this.toJSON());
306
+ }
307
+
308
+ /**
309
+ * Returns material in POSCAR format. Pass `true` to ignore original poscar source and re-serialize.
310
+ */
311
+ getAsPOSCAR(ignoreOriginal = false, omitConstraints = false): string {
312
+ const { src } = this;
313
+ // By default return original source if exists
314
+ if (src && src.extension === "poscar" && !ignoreOriginal) {
315
+ return this.src.text;
316
+ }
317
+ return parsers.poscar.toPoscar(this.toJSON(), omitConstraints);
318
+ }
319
+
320
+ /**
321
+ * Returns a copy of the material with conventional cell constructed instead of primitive.
322
+ */
323
+ getACopyWithConventionalCell(): MadeMaterial {
324
+ const material = this.clone();
325
+
326
+ // if conventional and primitive cells are the same => return a copy.
327
+ if (isConventionalCellSameAsPrimitiveForLatticeType(this.Lattice.type)) return material;
328
+
329
+ const conventionalSupercellMatrix =
330
+ PRIMITIVE_TO_CONVENTIONAL_CELL_MULTIPLIERS[this.Lattice.type];
331
+ const conventionalLatticeType =
332
+ PRIMITIVE_TO_CONVENTIONAL_CELL_LATTICE_TYPES[this.Lattice.type];
333
+ const config = supercellTools.generateConfig(material, conventionalSupercellMatrix);
334
+
335
+ config.lattice.type = conventionalLatticeType;
336
+ config.name = `${material.name} - conventional cell`;
337
+
338
+ // @ts-ignore
339
+ return new this.constructor(config);
340
+ }
341
+
342
+ /**
343
+ * @summary a series of checks for the material and returns an array of results in ConsistencyChecks format.
344
+ * @returns Array of checks results
345
+ */
346
+ getConsistencyChecks(): ConsistencyCheck[] {
347
+ const basisChecks = this.getBasisConsistencyChecks();
348
+
349
+ // any other Material checks can be added here
350
+
351
+ return basisChecks;
352
+ }
353
+
354
+ /**
355
+ * @summary a series of checks for the material's basis and returns an array of results in ConsistencyChecks format.
356
+ * @returns Array of checks results
357
+ */
358
+ getBasisConsistencyChecks(): ConsistencyCheck[] {
359
+ const checks: ConsistencyCheck[] = [];
360
+ const limit = 1000;
361
+ const basis = this.Basis;
362
+
363
+ if (this.Basis.elements.length < limit) {
364
+ const overlappingAtomsGroups = basis.getOverlappingAtoms();
365
+ overlappingAtomsGroups.forEach(({ id1, id2, element1, element2 }) => {
366
+ checks.push(
367
+ {
368
+ key: `basis.coordinates.${id1}`,
369
+ name: "atomsOverlap",
370
+ severity: "warning",
371
+ message: `Atom ${element1} is too close to ${element2} at position ${
372
+ id2 + 1
373
+ }`,
374
+ },
375
+ {
376
+ key: `basis.coordinates.${id2}`,
377
+ name: "atomsOverlap",
378
+ severity: "warning",
379
+ message: `Atom ${element2} is too close to ${element1} at position ${
380
+ id1 + 1
381
+ }`,
382
+ },
383
+ );
384
+ });
385
+ }
386
+
387
+ return checks;
388
+ }
389
+ }
390
+
391
+ return MadeMaterial;
392
+ }
393
+
394
+ export const Material = MaterialMixin(
395
+ HasConsistencyChecksHasMetadataNamedDefaultableInMemoryEntity,
396
+ );
397
+
398
+ export type Material = InstanceType<typeof Material>;
package/src/js/math.js ADDED
@@ -0,0 +1,6 @@
1
+ // TODO: adjust the imports and remove the need for re-exporting
2
+ import { math as codeJSMath } from "@exabyte-io/code.js/dist/math";
3
+
4
+ export default {
5
+ ...codeJSMath,
6
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Extracts meta information from a CIF file
3
+ * @param {String} txt - CIF file text.
4
+ * @return {Object}
5
+ */
6
+ function parseMeta(txt) {
7
+ const REGEX = {
8
+ ICSD_ID: /_database_code_ICSD\s+(\d+)/,
9
+ };
10
+ const meta = {};
11
+ const groups = txt.match(REGEX.ICSD_ID);
12
+
13
+ if (groups) {
14
+ meta.icsdId = Number(groups[1]);
15
+ }
16
+
17
+ return meta;
18
+ }
19
+
20
+ export default {
21
+ parseMeta,
22
+ };
@@ -0,0 +1,7 @@
1
+ export class InvalidLineError extends Error {
2
+ constructor(num, content) {
3
+ super(`Invalid line: ${num}`);
4
+ this.lineNumber = num;
5
+ this.content = content;
6
+ }
7
+ }