@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,499 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Basis = void 0;
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
const periodic_table_js_1 = require("@exabyte-io/periodic-table.js");
|
|
9
|
+
const underscore_1 = __importDefault(require("underscore"));
|
|
10
|
+
const underscore_string_1 = __importDefault(require("underscore.string"));
|
|
11
|
+
const array_with_ids_1 = require("../abstract/array_with_ids");
|
|
12
|
+
const constants_1 = require("../constants");
|
|
13
|
+
const lattice_1 = require("../lattice/lattice");
|
|
14
|
+
const math_1 = __importDefault(require("../math"));
|
|
15
|
+
/**
|
|
16
|
+
* A class representing a crystal basis.
|
|
17
|
+
*/
|
|
18
|
+
class Basis {
|
|
19
|
+
constructor({ elements = ["Si"], coordinates = [[0, 0, 0]], units, cell = Basis.defaultCell, // by default, assume a cubic unary cell
|
|
20
|
+
isEmpty = false, // whether to generate an empty Basis
|
|
21
|
+
labels = [], }) {
|
|
22
|
+
const _elements = isEmpty ? [] : elements;
|
|
23
|
+
const _coordinates = isEmpty ? [] : coordinates;
|
|
24
|
+
const _units = units || Basis.unitsOptionsDefaultValue;
|
|
25
|
+
if (!units) {
|
|
26
|
+
console.warn("Basis.constructor: units are not provided => set to crystal");
|
|
27
|
+
}
|
|
28
|
+
// assert that elements and coordinates have ids if not already passed in config + store Array helper classes
|
|
29
|
+
this._elements = new array_with_ids_1.ArrayWithIds(_elements);
|
|
30
|
+
this._coordinates = new array_with_ids_1.ArrayWithIds(_coordinates);
|
|
31
|
+
this.units = _units;
|
|
32
|
+
this.cell = cell;
|
|
33
|
+
if (!underscore_1.default.isEmpty(labels)) {
|
|
34
|
+
this.labels = labels;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
static get unitsOptionsConfig() {
|
|
38
|
+
return constants_1.ATOMIC_COORD_UNITS;
|
|
39
|
+
}
|
|
40
|
+
static get unitsOptionsDefaultValue() {
|
|
41
|
+
return constants_1.ATOMIC_COORD_UNITS.crystal;
|
|
42
|
+
}
|
|
43
|
+
static get defaultCell() {
|
|
44
|
+
return new lattice_1.Lattice().vectorArrays;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Serialize class instance to JSON.
|
|
48
|
+
* @example As below:
|
|
49
|
+
{
|
|
50
|
+
"elements" : [
|
|
51
|
+
{
|
|
52
|
+
"id" : 0,
|
|
53
|
+
"value" : "Si"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"id" : 1,
|
|
57
|
+
"value" : "Si"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"coordinates" : [
|
|
61
|
+
{
|
|
62
|
+
"id" : 0,
|
|
63
|
+
"value" : [
|
|
64
|
+
0,
|
|
65
|
+
0,
|
|
66
|
+
0
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id" : 1,
|
|
71
|
+
"value" : [
|
|
72
|
+
0.25,
|
|
73
|
+
0.25,
|
|
74
|
+
0.25
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
"units" : "crystal",
|
|
79
|
+
"cell" : [
|
|
80
|
+
[
|
|
81
|
+
1,
|
|
82
|
+
0,
|
|
83
|
+
6.12323399573677e-17
|
|
84
|
+
],
|
|
85
|
+
[
|
|
86
|
+
1.60812264967664e-16,
|
|
87
|
+
1,
|
|
88
|
+
6.12323399573677e-17
|
|
89
|
+
],
|
|
90
|
+
[
|
|
91
|
+
0,
|
|
92
|
+
0,
|
|
93
|
+
1
|
|
94
|
+
]
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
*/
|
|
98
|
+
toJSON() {
|
|
99
|
+
const json = {
|
|
100
|
+
elements: this.elements,
|
|
101
|
+
coordinates: this.coordinates,
|
|
102
|
+
units: this.units,
|
|
103
|
+
cell: this.cell,
|
|
104
|
+
};
|
|
105
|
+
if (!underscore_1.default.isEmpty(this.labels)) {
|
|
106
|
+
return JSON.parse(JSON.stringify({
|
|
107
|
+
...json,
|
|
108
|
+
labels: this.labels,
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
return JSON.parse(JSON.stringify(json));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Create an identical copy of the class instance.
|
|
115
|
+
* @param extraContext - Extra context to be passed to the new class instance on creation.
|
|
116
|
+
*/
|
|
117
|
+
clone(extraContext) {
|
|
118
|
+
return new this.constructor({
|
|
119
|
+
...this.toJSON(),
|
|
120
|
+
...extraContext,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
getElementByIndex(idx) {
|
|
124
|
+
return this._elements.getArrayElementByIndex(idx);
|
|
125
|
+
}
|
|
126
|
+
getCoordinateByIndex(idx) {
|
|
127
|
+
return this._coordinates.getArrayElementByIndex(idx);
|
|
128
|
+
}
|
|
129
|
+
get elementsArray() {
|
|
130
|
+
return this._elements.array;
|
|
131
|
+
}
|
|
132
|
+
get elements() {
|
|
133
|
+
return this._elements.toJSON();
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Set basis elements to passed array.
|
|
137
|
+
* @param elementsArray - New elements array.
|
|
138
|
+
*/
|
|
139
|
+
set elements(elementsArray) {
|
|
140
|
+
this._elements = new array_with_ids_1.ArrayWithIds(elementsArray);
|
|
141
|
+
}
|
|
142
|
+
getElementsAsObject() {
|
|
143
|
+
return this._elements.toJSON();
|
|
144
|
+
}
|
|
145
|
+
get coordinates() {
|
|
146
|
+
return this._coordinates.toJSON();
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Set basis elements to passed array.
|
|
150
|
+
* @param {Array|ArrayWithIds} coordinatesNestedArray - New coordinates array.
|
|
151
|
+
*/
|
|
152
|
+
set coordinates(coordinatesNestedArray) {
|
|
153
|
+
this._coordinates = new array_with_ids_1.ArrayWithIds(coordinatesNestedArray);
|
|
154
|
+
}
|
|
155
|
+
get coordinatesAsArray() {
|
|
156
|
+
return this._coordinates.array;
|
|
157
|
+
}
|
|
158
|
+
get isInCrystalUnits() {
|
|
159
|
+
return this.units === constants_1.ATOMIC_COORD_UNITS.crystal;
|
|
160
|
+
}
|
|
161
|
+
get isInCartesianUnits() {
|
|
162
|
+
return this.units === constants_1.ATOMIC_COORD_UNITS.cartesian;
|
|
163
|
+
}
|
|
164
|
+
toCartesian() {
|
|
165
|
+
const unitCell = this.cell;
|
|
166
|
+
if (this.units === constants_1.ATOMIC_COORD_UNITS.cartesian)
|
|
167
|
+
return;
|
|
168
|
+
this._coordinates.mapArrayInPlace((point) => math_1.default.multiply(point, unitCell));
|
|
169
|
+
this.units = constants_1.ATOMIC_COORD_UNITS.cartesian;
|
|
170
|
+
}
|
|
171
|
+
toCrystal() {
|
|
172
|
+
const unitCell = this.cell;
|
|
173
|
+
if (this.units === constants_1.ATOMIC_COORD_UNITS.crystal)
|
|
174
|
+
return;
|
|
175
|
+
this._coordinates.mapArrayInPlace((point) => math_1.default.multiply(point, math_1.default.inv(unitCell)));
|
|
176
|
+
this.units = constants_1.ATOMIC_COORD_UNITS.crystal;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Asserts that all coordinates are in standardRepresentation (as explained below).
|
|
180
|
+
*/
|
|
181
|
+
toStandardRepresentation() {
|
|
182
|
+
this.toCrystal();
|
|
183
|
+
this._coordinates.mapArrayInPlace((point) => point.map((x) => math_1.default.mod(x)));
|
|
184
|
+
}
|
|
185
|
+
/** A representation where all coordinates are within 0 and 1 in crystal units */
|
|
186
|
+
get standardRepresentation() {
|
|
187
|
+
const originalUnits = this.units;
|
|
188
|
+
this.toStandardRepresentation();
|
|
189
|
+
const result = this.toJSON();
|
|
190
|
+
// preserve the original state
|
|
191
|
+
if (originalUnits !== constants_1.ATOMIC_COORD_UNITS.crystal)
|
|
192
|
+
this.toCartesian();
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Add atom with a chemical element at coordinate.
|
|
197
|
+
*/
|
|
198
|
+
addAtom({ element = "Si", coordinate = [0.5, 0.5, 0.5] }) {
|
|
199
|
+
this._elements.addElement(element);
|
|
200
|
+
this._coordinates.addElement(coordinate);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Remove atom with a chemical element at coordinate either by passing the (element AND coordinate) OR id.
|
|
204
|
+
*/
|
|
205
|
+
removeAtom({ element, coordinate, id }) {
|
|
206
|
+
if (element && coordinate.length > 0) {
|
|
207
|
+
this._elements.removeElement(element, id);
|
|
208
|
+
this._coordinates.removeElement(coordinate, id);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Unique names (symbols) of the chemical elements basis. E.g. `['Si', 'Li']`
|
|
213
|
+
*/
|
|
214
|
+
get uniqueElements() {
|
|
215
|
+
return underscore_1.default.unique(this._elements.array);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Returns unique chemical elements with their count sorted by electronegativity.
|
|
219
|
+
* `{ "Fe": 4.0, "O": 8.0, "Li": 2.0}`.
|
|
220
|
+
*/
|
|
221
|
+
get uniqueElementCountsSortedByElectronegativity() {
|
|
222
|
+
return underscore_1.default.chain(this.elements)
|
|
223
|
+
.sortBy("value")
|
|
224
|
+
.sortBy((x) => (0, periodic_table_js_1.getElectronegativity)(x.value))
|
|
225
|
+
.countBy((element) => element.value)
|
|
226
|
+
.value();
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Returns chemical elements with their count wrt their original order in the basis.
|
|
230
|
+
* Note: entries for the same element separated by another element are considered separately.
|
|
231
|
+
* [{"count":1, "value":"Zr"}, {"count":23, "value":"H"}, {"count":11, "value":"Zr"}, {"count":1, "value":"H"}]
|
|
232
|
+
*/
|
|
233
|
+
get elementCounts() {
|
|
234
|
+
const elementCounts = [];
|
|
235
|
+
this.getElementsAsObject().forEach((element, index) => {
|
|
236
|
+
const previousElement = this.getElementsAsObject()[index - 1];
|
|
237
|
+
if (previousElement && previousElement.value === element.value) {
|
|
238
|
+
const previousElementCount = elementCounts[elementCounts.length - 1];
|
|
239
|
+
previousElementCount.count += 1;
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
elementCounts.push({
|
|
243
|
+
count: 1,
|
|
244
|
+
value: element.value,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
return elementCounts;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Reduced formula in IUPAC format. E.g., Na2SO4
|
|
252
|
+
*/
|
|
253
|
+
get formula() {
|
|
254
|
+
const counts = this.uniqueElementCountsSortedByElectronegativity;
|
|
255
|
+
const countsValues = underscore_1.default.values(counts);
|
|
256
|
+
const gcd = countsValues.length > 1 ? math_1.default.gcd(...countsValues) : countsValues[0];
|
|
257
|
+
return underscore_1.default.pairs(counts)
|
|
258
|
+
.map((x) => x[0] + (x[1] / gcd === 1 ? "" : x[1] / gcd))
|
|
259
|
+
.reduce((mem, item) => {
|
|
260
|
+
return mem + item;
|
|
261
|
+
}, "");
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Returns the unit cell formula as object `{ "Fe": 4.0, "O": 8.0, "Li": 2.0}`
|
|
265
|
+
*/
|
|
266
|
+
get unitCellFormula() {
|
|
267
|
+
const counts = this.uniqueElementCountsSortedByElectronegativity;
|
|
268
|
+
return underscore_1.default.pairs(counts)
|
|
269
|
+
.map((x) => x[0] + (x[1] === 1 ? "" : x[1]))
|
|
270
|
+
.reduce((mem, item) => {
|
|
271
|
+
return mem + item;
|
|
272
|
+
}, "");
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Returns a nested array with elements and their corresponding coordinates
|
|
276
|
+
* @example Output: [ ["Si", [0,0,0]], ["Si", [0.5,0.5,0.5]] ]
|
|
277
|
+
*/
|
|
278
|
+
get elementsAndCoordinatesArray() {
|
|
279
|
+
return this._elements.array.map((element, idx) => {
|
|
280
|
+
const coordinates = this.getCoordinateByIndex(idx);
|
|
281
|
+
const atomicLabel = this.atomicLabelsArray[idx];
|
|
282
|
+
return [element, coordinates, atomicLabel];
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* @summary Concatenates elements and sorts them in alphanumeric order.
|
|
287
|
+
* E.g.,
|
|
288
|
+
* ```
|
|
289
|
+
* elements: [{id: 0, value: 'Si'}, {id: 1, value: 'Si'}]
|
|
290
|
+
* coordinates: [{id: 0, value: [1,0,0]}, {id: 1, value: [0, 1, 0]}]
|
|
291
|
+
*
|
|
292
|
+
* result: "Si 0,1,0;Si 1,0,0"
|
|
293
|
+
* ```
|
|
294
|
+
* This guarantees the independence from the order in the elements array.
|
|
295
|
+
*/
|
|
296
|
+
getAsSortedString() {
|
|
297
|
+
// make a copy to prevent modifying class values
|
|
298
|
+
const clsInstance = new Basis(this.toJSON());
|
|
299
|
+
clsInstance.toStandardRepresentation();
|
|
300
|
+
const standardRep = clsInstance.elementsAndCoordinatesArray.map((entry) => {
|
|
301
|
+
const element = entry[0];
|
|
302
|
+
const coordinate = entry[1];
|
|
303
|
+
const atomicLabel = entry[2];
|
|
304
|
+
const toleratedCoordinates = coordinate.map((x) => math_1.default.round(x, constants_1.HASH_TOLERANCE));
|
|
305
|
+
return `${element}${atomicLabel} ${toleratedCoordinates.join()}`;
|
|
306
|
+
});
|
|
307
|
+
return `${standardRep.sort().join(";")};`;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Returns a string for hash calculation (in crystal units)
|
|
311
|
+
*/
|
|
312
|
+
get hashString() {
|
|
313
|
+
const originallyInCartesianUnits = this.isInCartesianUnits;
|
|
314
|
+
this.toCrystal();
|
|
315
|
+
const hashString = this.getAsSortedString();
|
|
316
|
+
// preserve the original state
|
|
317
|
+
if (originallyInCartesianUnits)
|
|
318
|
+
this.toCartesian();
|
|
319
|
+
return hashString;
|
|
320
|
+
}
|
|
321
|
+
/* Returns array of atomic labels E.g., ["1", "2", "", ""] */
|
|
322
|
+
get atomicLabelsArray() {
|
|
323
|
+
var _a;
|
|
324
|
+
const labelsArray = [];
|
|
325
|
+
for (let i = 0; i < this.elements.length; i++) {
|
|
326
|
+
const labelObj = (_a = this.labels) === null || _a === void 0 ? void 0 : _a.find((item) => item.id === i);
|
|
327
|
+
const atomicLabel = labelObj ? labelObj.value.toString() : "";
|
|
328
|
+
labelsArray.push(atomicLabel);
|
|
329
|
+
}
|
|
330
|
+
return labelsArray;
|
|
331
|
+
}
|
|
332
|
+
/* Returns array of elements with labels E.g., ["Fe1", "Fe2", "O", "O"] */
|
|
333
|
+
get elementsWithLabelsArray() {
|
|
334
|
+
const elements = this.elementsArray;
|
|
335
|
+
const labels = this.atomicLabelsArray;
|
|
336
|
+
const elementsWithLabels = [];
|
|
337
|
+
elements.forEach((symbol, idx) => elementsWithLabels.push(symbol + labels[idx]));
|
|
338
|
+
return elementsWithLabels;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Returns an array of strings with chemical elements and their atomic positions.
|
|
342
|
+
* E.g., ``` ['Si 0 0 0', 'Li 0.5 0.5 0.5']```
|
|
343
|
+
*/
|
|
344
|
+
get atomicPositions() {
|
|
345
|
+
return this.elementsAndCoordinatesArray.map((entry, idx) => {
|
|
346
|
+
const element = entry[0];
|
|
347
|
+
const coordinate = entry[1];
|
|
348
|
+
const atomicLabel = this.atomicLabelsArray[idx];
|
|
349
|
+
return `${element}${atomicLabel} ${coordinate
|
|
350
|
+
.map((x) => underscore_string_1.default.sprintf("%14.9f", x).trim())
|
|
351
|
+
.join(" ")}`;
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* @summary Returns number of atoms in material
|
|
356
|
+
*/
|
|
357
|
+
get nAtoms() {
|
|
358
|
+
return this._elements.array.length;
|
|
359
|
+
}
|
|
360
|
+
// helpers
|
|
361
|
+
/**
|
|
362
|
+
* @summary Returns true if bases are equal, otherwise - false.
|
|
363
|
+
* @param anotherBasisClsInstance {Basis} Another Basis.
|
|
364
|
+
*/
|
|
365
|
+
isEqualTo(anotherBasisClsInstance) {
|
|
366
|
+
return this.hashString === anotherBasisClsInstance.hashString;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* @summary Returns true if basis cells are equal, otherwise - false.
|
|
370
|
+
* @param anotherBasisClsInstance {Basis} Another Basis.
|
|
371
|
+
*/
|
|
372
|
+
hasEquivalentCellTo(anotherBasisClsInstance) {
|
|
373
|
+
// this.cell {Array} - Cell Vectors 1, eg. [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]
|
|
374
|
+
// prettier-ignore
|
|
375
|
+
return !this.cell
|
|
376
|
+
.map((vector, idx) => {
|
|
377
|
+
return math_1.default.vEqualWithTolerance(vector, anotherBasisClsInstance.cell[idx]);
|
|
378
|
+
})
|
|
379
|
+
.some((x) => !x);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* @summary function returns the minimum basis lattice size for a structure.
|
|
383
|
+
* The lattice size is based on the atomic radius of an element if the basis contains a single atom.
|
|
384
|
+
* The lattice size is based on the maximum pairwise distance across a structure if the basis contains > 2 atoms.
|
|
385
|
+
*/
|
|
386
|
+
getMinimumLatticeSize(latticeScalingFactor = lattice_1.nonPeriodicLatticeScalingFactor) {
|
|
387
|
+
let latticeSizeAdditiveContribution = 0;
|
|
388
|
+
if (this._elements.array.length === 1) {
|
|
389
|
+
const elementSymbol = this._elements.getArrayElementByIndex(0);
|
|
390
|
+
latticeSizeAdditiveContribution = (0, periodic_table_js_1.getElementAtomicRadius)(elementSymbol);
|
|
391
|
+
}
|
|
392
|
+
const moleculeLatticeSize = this.maxPairwiseDistance * latticeScalingFactor;
|
|
393
|
+
const latticeSize = latticeSizeAdditiveContribution + moleculeLatticeSize;
|
|
394
|
+
return math_1.default.precise(latticeSize, 4);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* @summary function returns an array of overlapping atoms within specified tolerance.
|
|
398
|
+
*/
|
|
399
|
+
getOverlappingAtoms() {
|
|
400
|
+
// to simplify calculations, convert to cartesian coordinates
|
|
401
|
+
this.toCartesian();
|
|
402
|
+
const { coordinates, elements } = this;
|
|
403
|
+
const overlaps = [];
|
|
404
|
+
// temporary value for overlap approximation, where atoms most certainly can't be located
|
|
405
|
+
const overlapCoefficient = 0.75;
|
|
406
|
+
coordinates.forEach((entry1, i) => {
|
|
407
|
+
for (let j = i + 1; j < coordinates.length; j++) {
|
|
408
|
+
const entry2 = coordinates[j];
|
|
409
|
+
const el1 = elements[i].value;
|
|
410
|
+
const el2 = elements[j].value;
|
|
411
|
+
const tolerance = overlapCoefficient *
|
|
412
|
+
((0, periodic_table_js_1.getElementAtomicRadius)(el1) + (0, periodic_table_js_1.getElementAtomicRadius)(el2)); // in angstroms
|
|
413
|
+
// @ts-ignore
|
|
414
|
+
const distance = math_1.default.vDist(entry1.value, entry2.value);
|
|
415
|
+
if (distance < tolerance) {
|
|
416
|
+
overlaps.push({
|
|
417
|
+
id1: i,
|
|
418
|
+
id2: j,
|
|
419
|
+
element1: el1,
|
|
420
|
+
element2: el2,
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
this.toCrystal();
|
|
426
|
+
return overlaps;
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* @summary function returns the max distance between pairs of basis coordinates by
|
|
430
|
+
* calculating the distance between pairs of basis coordinates.
|
|
431
|
+
* basis coordinates = [[x1, y1, z1], [x2, y2, z2], ... [xn, yn, zn]]
|
|
432
|
+
* n = last set of coordinates
|
|
433
|
+
* n-1 = second to last set of coordinates
|
|
434
|
+
*
|
|
435
|
+
* Iterate through pairs without redundancy.
|
|
436
|
+
* pair 0,1 pair 0,2 pair 0,3 ... pair 0,n
|
|
437
|
+
* - pair 1,2 pair 1,3 ... pair 1,n
|
|
438
|
+
* - - - pair 2,3 ... pair 2,n
|
|
439
|
+
* - - - ... ...
|
|
440
|
+
* - - - ... ... pair n-1, n
|
|
441
|
+
*
|
|
442
|
+
*/
|
|
443
|
+
get maxPairwiseDistance() {
|
|
444
|
+
const originalUnits = this.units;
|
|
445
|
+
this.toCartesian();
|
|
446
|
+
let maxDistance = 0;
|
|
447
|
+
if (this._elements.array.length >= 2) {
|
|
448
|
+
for (let i = 0; i < this._elements.array.length; i++) {
|
|
449
|
+
for (let j = i + 1; j < this._elements.array.length; j++) {
|
|
450
|
+
const distance = math_1.default.vDist(this._coordinates.getArrayElementByIndex(i), this._coordinates.getArrayElementByIndex(j));
|
|
451
|
+
// @ts-ignore
|
|
452
|
+
if (distance > maxDistance) {
|
|
453
|
+
// @ts-ignore
|
|
454
|
+
maxDistance = distance;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
if (originalUnits !== constants_1.ATOMIC_COORD_UNITS.cartesian)
|
|
460
|
+
this.toCrystal();
|
|
461
|
+
return math_1.default.precise(maxDistance, 4);
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* @summary Function takes basis coordinates and transposes them so that the values for each dimension of the
|
|
465
|
+
* the basis are in their own nested array.
|
|
466
|
+
* Then the center point for each dimension of the coordinates is calculated.
|
|
467
|
+
*
|
|
468
|
+
* initial basisCoordinates
|
|
469
|
+
* [[x1, y1, z1],
|
|
470
|
+
* [x2, y2, z2],
|
|
471
|
+
* [.., .., ..],
|
|
472
|
+
* [xn, yn, zn]]
|
|
473
|
+
*
|
|
474
|
+
* transposed basisCoordinates
|
|
475
|
+
* [[x1, x2, ...xn],
|
|
476
|
+
* [y1, y2, ...yn],
|
|
477
|
+
* [z1, z2, ...zn]]
|
|
478
|
+
*
|
|
479
|
+
* Returns an array = [xCenter, yCenter, zCenter]
|
|
480
|
+
*/
|
|
481
|
+
get centerOfCoordinatesPoint() {
|
|
482
|
+
const transposedBasisCoordinates = math_1.default.transpose(this._coordinates.array);
|
|
483
|
+
const centerOfCoordinatesVectors = [];
|
|
484
|
+
for (let i = 0; i < 3; i++) {
|
|
485
|
+
const center = // @ts-ignore
|
|
486
|
+
transposedBasisCoordinates[i].reduce((a, b) => a + b) / this._elements.array.length;
|
|
487
|
+
centerOfCoordinatesVectors.push(math_1.default.precise(center, 4));
|
|
488
|
+
}
|
|
489
|
+
return centerOfCoordinatesVectors;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* @summary Function translates coordinates by the vector passed as an argument.
|
|
493
|
+
*/
|
|
494
|
+
translateByVector(translationVector) {
|
|
495
|
+
// @ts-ignore
|
|
496
|
+
this._coordinates.mapArrayInPlace((x) => math_1.default.add(x, translationVector));
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
exports.Basis = Basis;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ArrayWithIds } from "../abstract/array_with_ids";
|
|
2
|
+
import { ObjectWithIdAndValue } from "../abstract/scalar_with_id";
|
|
3
|
+
import { AtomicConstraints, Constraint, ConstraintValue } from "../constraints/constraints";
|
|
4
|
+
import { Basis, BasisProps, BasisSchema } from "./basis";
|
|
5
|
+
import { Coordinate } from "./types";
|
|
6
|
+
export interface ConstrainedBasisProps extends BasisProps {
|
|
7
|
+
constraints: Constraint[];
|
|
8
|
+
}
|
|
9
|
+
export interface ConstrainedBasisJSON extends BasisSchema {
|
|
10
|
+
constraints: ObjectWithIdAndValue<ConstraintValue>[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* @summary Extension of the Basis class able to deal with atomic constraints.
|
|
14
|
+
* @extends Basis
|
|
15
|
+
*/
|
|
16
|
+
export declare class ConstrainedBasis extends Basis {
|
|
17
|
+
_constraints: ArrayWithIds<ConstraintValue>;
|
|
18
|
+
/**
|
|
19
|
+
* Create a an array with ids.
|
|
20
|
+
* @param {Object} config
|
|
21
|
+
* @param {ArrayWithIds|Array} config.constraints - atomic constraints.
|
|
22
|
+
*/
|
|
23
|
+
constructor(config: ConstrainedBasisProps);
|
|
24
|
+
get constraints(): ConstraintValue[];
|
|
25
|
+
set constraints(newConstraints: ConstraintValue[]);
|
|
26
|
+
getConstraintAsArray(): ArrayWithIds<ConstraintValue>;
|
|
27
|
+
get AtomicConstraints(): AtomicConstraints;
|
|
28
|
+
/**
|
|
29
|
+
* Serialize class instance to JSON.
|
|
30
|
+
* @example As below:
|
|
31
|
+
{
|
|
32
|
+
...Basis.toJSON(),
|
|
33
|
+
"constraints": [
|
|
34
|
+
{
|
|
35
|
+
"id" : 0,
|
|
36
|
+
"value" : [
|
|
37
|
+
1,
|
|
38
|
+
1,
|
|
39
|
+
1
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
*/
|
|
45
|
+
toJSON(): ConstrainedBasisJSON;
|
|
46
|
+
getConstraintByIndex(idx: number): ConstraintValue;
|
|
47
|
+
/**
|
|
48
|
+
* Helper function returning a nested array with [element, coordinates, constraints] as elements
|
|
49
|
+
*/
|
|
50
|
+
get elementsCoordinatesConstraintsArray(): [string, Coordinate, ConstraintValue, string][];
|
|
51
|
+
/**
|
|
52
|
+
* Returns an array with atomic positions (with constraints) per atom stored as strings.
|
|
53
|
+
* E.g., ``` ['Si 0 0 0 0 1 0', 'Li 0.5 0.5 0.5 1 0 1']```
|
|
54
|
+
*/
|
|
55
|
+
get atomicPositionsWithConstraints(): string[];
|
|
56
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ConstrainedBasis = void 0;
|
|
7
|
+
const underscore_string_1 = __importDefault(require("underscore.string"));
|
|
8
|
+
const array_with_ids_1 = require("../abstract/array_with_ids");
|
|
9
|
+
const constraints_1 = require("../constraints/constraints");
|
|
10
|
+
const basis_1 = require("./basis");
|
|
11
|
+
/**
|
|
12
|
+
* @summary Extension of the Basis class able to deal with atomic constraints.
|
|
13
|
+
* @extends Basis
|
|
14
|
+
*/
|
|
15
|
+
class ConstrainedBasis extends basis_1.Basis {
|
|
16
|
+
/**
|
|
17
|
+
* Create a an array with ids.
|
|
18
|
+
* @param {Object} config
|
|
19
|
+
* @param {ArrayWithIds|Array} config.constraints - atomic constraints.
|
|
20
|
+
*/
|
|
21
|
+
constructor(config) {
|
|
22
|
+
super(config);
|
|
23
|
+
this._constraints = new array_with_ids_1.ArrayWithIds(config.constraints); // `constraints` is an Array with ids
|
|
24
|
+
}
|
|
25
|
+
get constraints() {
|
|
26
|
+
return this._constraints.array;
|
|
27
|
+
}
|
|
28
|
+
set constraints(newConstraints) {
|
|
29
|
+
this._constraints = new array_with_ids_1.ArrayWithIds(newConstraints);
|
|
30
|
+
}
|
|
31
|
+
getConstraintAsArray() {
|
|
32
|
+
return this._constraints;
|
|
33
|
+
}
|
|
34
|
+
get AtomicConstraints() {
|
|
35
|
+
return constraints_1.AtomicConstraints.fromArray(this.constraints);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Serialize class instance to JSON.
|
|
39
|
+
* @example As below:
|
|
40
|
+
{
|
|
41
|
+
...Basis.toJSON(),
|
|
42
|
+
"constraints": [
|
|
43
|
+
{
|
|
44
|
+
"id" : 0,
|
|
45
|
+
"value" : [
|
|
46
|
+
1,
|
|
47
|
+
1,
|
|
48
|
+
1
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
*/
|
|
54
|
+
toJSON() {
|
|
55
|
+
return {
|
|
56
|
+
...super.toJSON(),
|
|
57
|
+
constraints: this._constraints.toJSON(),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
getConstraintByIndex(idx) {
|
|
61
|
+
return this._constraints.getArrayElementByIndex(idx) || [];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Helper function returning a nested array with [element, coordinates, constraints] as elements
|
|
65
|
+
*/
|
|
66
|
+
get elementsCoordinatesConstraintsArray() {
|
|
67
|
+
return this._elements.array.map((element, idx) => {
|
|
68
|
+
const coordinates = this.getCoordinateByIndex(idx);
|
|
69
|
+
const constraints = this.getConstraintByIndex(idx);
|
|
70
|
+
const atomicLabel = this.atomicLabelsArray[idx];
|
|
71
|
+
return [element, coordinates, constraints, atomicLabel];
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Returns an array with atomic positions (with constraints) per atom stored as strings.
|
|
76
|
+
* E.g., ``` ['Si 0 0 0 0 1 0', 'Li 0.5 0.5 0.5 1 0 1']```
|
|
77
|
+
*/
|
|
78
|
+
get atomicPositionsWithConstraints() {
|
|
79
|
+
return this.elementsCoordinatesConstraintsArray.map((entry) => {
|
|
80
|
+
const element = entry[0] + entry[3]; // element with label, Fe1
|
|
81
|
+
const coordinate = entry[1];
|
|
82
|
+
const constraint = entry[2];
|
|
83
|
+
return (underscore_string_1.default.sprintf("%-4s", element) +
|
|
84
|
+
coordinate.map((x) => underscore_string_1.default.sprintf("%14.9f", x).trim()).join(" ") +
|
|
85
|
+
" " +
|
|
86
|
+
constraint.map((x) => (x ? 1 : 0)).join(" "));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.ConstrainedBasis = ConstrainedBasis;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Coordinate = [number, number, number];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Coordinate } from "../basis/types";
|
|
2
|
+
import { Vector, VectorsAsArray } from "../lattice/types";
|
|
3
|
+
type Point = Coordinate | math.Matrix | math.MathType;
|
|
4
|
+
export declare class Cell {
|
|
5
|
+
tolerance: number;
|
|
6
|
+
vector1: Vector;
|
|
7
|
+
vector2: Vector;
|
|
8
|
+
vector3: Vector;
|
|
9
|
+
/**
|
|
10
|
+
* Create a cell.
|
|
11
|
+
* @param nestedArray {Number[][]} is an array of cell vectors in cartesian Angstrom units.
|
|
12
|
+
*/
|
|
13
|
+
constructor(nestedArray: VectorsAsArray);
|
|
14
|
+
/**
|
|
15
|
+
* Get cell vectors as (a nested) array.
|
|
16
|
+
* @example [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
|
|
17
|
+
*/
|
|
18
|
+
get vectorsAsArray(): VectorsAsArray;
|
|
19
|
+
clone(): Cell;
|
|
20
|
+
cloneAndScaleByMatrix(matrix: number[][]): Cell;
|
|
21
|
+
/**
|
|
22
|
+
* Convert a point (in crystal coordinates) to cartesian.
|
|
23
|
+
*/
|
|
24
|
+
convertPointToCartesian(point: Point): import("mathjs").MathType;
|
|
25
|
+
/**
|
|
26
|
+
* Convert a point (in cartesian coordinates) to crystal (fractional).
|
|
27
|
+
*/
|
|
28
|
+
convertPointToFractional(point: Point): Coordinate;
|
|
29
|
+
/**
|
|
30
|
+
* Check whether a point is inside the cell.
|
|
31
|
+
* @param point - the point to conduct the check for.
|
|
32
|
+
* @param tolerance - numerical tolerance.
|
|
33
|
+
*/
|
|
34
|
+
isPointInsideCell(point: Point, tolerance?: number): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Returns the index of the cell vector, most collinear with the testVector.
|
|
37
|
+
* @param testVector
|
|
38
|
+
*/
|
|
39
|
+
getMostCollinearVectorIndex(testVector: Vector): number;
|
|
40
|
+
/**
|
|
41
|
+
* Scale this cell by right-multiplying it to a matrix (nested array)
|
|
42
|
+
*/
|
|
43
|
+
scaleByMatrix(matrix: number[][]): void;
|
|
44
|
+
}
|
|
45
|
+
export {};
|