-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathboundary.js
130 lines (117 loc) · 5.01 KB
/
boundary.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import { Made } from "@mat3ra/made";
import * as THREE from "three";
import { BOUNDARY_CONDITIONS } from "../enums";
export const BoundaryMixin = (superclass) =>
class extends superclass {
/**
* boundaryConditions.type {String}: type of the boundary.
* boundaryConditions.offset {Number} boundary offset (esm_w).
*/
constructor(config) {
super(config);
this.boundaryConditions = config.boundaryConditions || {};
}
/**
* Boundaries are drawn only if type is "bc1", "bc2", or "bc3".
* bc1 : Immerse the slab between two semi-infinite vacuum regions;
* bc2 : Immerse the slab between two semi-infinite metallic electrodes, with optional fixed field applied between them.
* bc3 : Immerse the slab between one semi-infinite vacuum region (left) and one semi-infinite metallic electrode (right).
*/
get areNonPeriodicBoundariesPresent() {
return BOUNDARY_CONDITIONS.filter((e) => e.isNonPeriodic)
.map((e) => e.type)
.includes(this.boundaryConditions.type);
}
/**
* Returns a plane-like mesh object with given corner vertices in counterclockwise order.
* @param color {Number} mesh object color.
* @param coordinates1 {Array} first point.
* @param coordinates2 {Array} second point.
* @param coordinates3 {Array} third point.
* @param coordinates4 {Array} fourth point.
* @param zOffset {Number} offset to add to the z coordinate of points forming the object.
*/
// eslint-disable-next-line class-methods-use-this
getBoundaryMeshObject(
color,
coordinates1,
coordinates2,
coordinates3,
coordinates4,
zOffset = 0,
) {
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array(
[coordinates1, coordinates2, coordinates3, coordinates3, coordinates4, coordinates1]
.map(([x, y, z]) => [x, y, z + zOffset])
.flat(),
);
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const material = new THREE.MeshBasicMaterial({
color,
opacity: 0.5,
transparent: true,
side: THREE.DoubleSide,
});
return new THREE.Mesh(geometry, material);
}
/**
* Returns the z offset to add to the boundary planes. Note that the c axis of the cell and z axis of coordinate system
* are always aligned by convention, hence this.cVectorLength / 2.
*/
get boundaryMeshObjectZOffset() {
return this.boundaryConditions.offset + this.cVectorLength / 2;
}
/**
* Draw boundaries with +/- [L_z/2 + this.boundaryConditions.offset] z coordinates.
*/
drawBoundaries() {
if (this.areNonPeriodicBoundariesPresent) {
const vertices = this.getCellVertices(this.cell);
const colors =
this.settings.boundaryConditionTypeColors[this.boundaryConditions.type];
const boundaryMeshObjectVertices = [
vertices[0],
vertices[1],
vertices[3],
vertices[2],
];
const plane1 = this.getBoundaryMeshObject(
colors[0],
...boundaryMeshObjectVertices,
this.boundaryMeshObjectZOffset,
);
const plane2 = this.getBoundaryMeshObject(
colors[1],
...boundaryMeshObjectVertices,
-this.boundaryMeshObjectZOffset,
);
this.repeatObject3DAtRepetitionCoordinates(plane1);
this.repeatObject3DAtRepetitionCoordinates(plane2);
}
}
/**
* Returns a basis with elements inside boundary conditions.
*/
get basisWithElementsInsideNonPeriodicBoundaries() {
const newBasis = this.basis.clone();
newBasis.elements = [];
newBasis.coordinates = [];
const basisCloneInCrystalCoordinates = this.basis.clone();
newBasis.toCrystal();
basisCloneInCrystalCoordinates.toCrystal();
basisCloneInCrystalCoordinates.elements.forEach((element, index) => {
const coord = basisCloneInCrystalCoordinates.getCoordinateValueByIndex(index);
newBasis.addAtom({
element,
coordinate: [
coord[0],
coord[1],
Made.math.abs(coord[2]) <= 0.5 ? coord[2] : coord[2] - 1,
],
});
});
if (this.basis.isInCartesianUnits) newBasis.toCartesian();
return newBasis;
}
};