emerge 0.4.7__py3-none-any.whl → 0.4.9__py3-none-any.whl

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.

Potentially problematic release.


This version of emerge might be problematic. Click here for more details.

Files changed (78) hide show
  1. emerge/__init__.py +14 -14
  2. emerge/_emerge/__init__.py +42 -0
  3. emerge/_emerge/bc.py +197 -0
  4. emerge/_emerge/coord.py +119 -0
  5. emerge/_emerge/cs.py +523 -0
  6. emerge/_emerge/dataset.py +36 -0
  7. emerge/_emerge/elements/__init__.py +19 -0
  8. emerge/_emerge/elements/femdata.py +212 -0
  9. emerge/_emerge/elements/index_interp.py +64 -0
  10. emerge/_emerge/elements/legrange2.py +172 -0
  11. emerge/_emerge/elements/ned2_interp.py +645 -0
  12. emerge/_emerge/elements/nedelec2.py +140 -0
  13. emerge/_emerge/elements/nedleg2.py +217 -0
  14. emerge/_emerge/geo/__init__.py +24 -0
  15. emerge/_emerge/geo/horn.py +107 -0
  16. emerge/_emerge/geo/modeler.py +449 -0
  17. emerge/_emerge/geo/operations.py +254 -0
  18. emerge/_emerge/geo/pcb.py +1244 -0
  19. emerge/_emerge/geo/pcb_tools/calculator.py +28 -0
  20. emerge/_emerge/geo/pcb_tools/macro.py +79 -0
  21. emerge/_emerge/geo/pmlbox.py +204 -0
  22. emerge/_emerge/geo/polybased.py +529 -0
  23. emerge/_emerge/geo/shapes.py +427 -0
  24. emerge/_emerge/geo/step.py +77 -0
  25. emerge/_emerge/geo2d.py +86 -0
  26. emerge/_emerge/geometry.py +510 -0
  27. emerge/_emerge/howto.py +214 -0
  28. emerge/_emerge/logsettings.py +5 -0
  29. emerge/_emerge/material.py +118 -0
  30. emerge/_emerge/mesh3d.py +730 -0
  31. emerge/_emerge/mesher.py +339 -0
  32. emerge/_emerge/mth/common_functions.py +33 -0
  33. emerge/_emerge/mth/integrals.py +71 -0
  34. emerge/_emerge/mth/optimized.py +357 -0
  35. emerge/_emerge/periodic.py +263 -0
  36. emerge/_emerge/physics/__init__.py +0 -0
  37. emerge/_emerge/physics/microwave/__init__.py +1 -0
  38. emerge/_emerge/physics/microwave/adaptive_freq.py +279 -0
  39. emerge/_emerge/physics/microwave/assembly/assembler.py +569 -0
  40. emerge/_emerge/physics/microwave/assembly/curlcurl.py +448 -0
  41. emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +426 -0
  42. emerge/_emerge/physics/microwave/assembly/robinbc.py +433 -0
  43. emerge/_emerge/physics/microwave/microwave_3d.py +1150 -0
  44. emerge/_emerge/physics/microwave/microwave_bc.py +915 -0
  45. emerge/_emerge/physics/microwave/microwave_data.py +1148 -0
  46. emerge/_emerge/physics/microwave/periodic.py +82 -0
  47. emerge/_emerge/physics/microwave/port_functions.py +53 -0
  48. emerge/_emerge/physics/microwave/sc.py +175 -0
  49. emerge/_emerge/physics/microwave/simjob.py +147 -0
  50. emerge/_emerge/physics/microwave/sparam.py +138 -0
  51. emerge/_emerge/physics/microwave/touchstone.py +140 -0
  52. emerge/_emerge/plot/__init__.py +0 -0
  53. emerge/_emerge/plot/display.py +394 -0
  54. emerge/_emerge/plot/grapher.py +93 -0
  55. emerge/_emerge/plot/matplotlib/mpldisplay.py +264 -0
  56. emerge/_emerge/plot/pyvista/__init__.py +1 -0
  57. emerge/_emerge/plot/pyvista/display.py +931 -0
  58. emerge/_emerge/plot/pyvista/display_settings.py +24 -0
  59. emerge/_emerge/plot/simple_plots.py +551 -0
  60. emerge/_emerge/plot.py +225 -0
  61. emerge/_emerge/projects/__init__.py +0 -0
  62. emerge/_emerge/projects/_gen_base.txt +32 -0
  63. emerge/_emerge/projects/_load_base.txt +24 -0
  64. emerge/_emerge/projects/generate_project.py +40 -0
  65. emerge/_emerge/selection.py +596 -0
  66. emerge/_emerge/simmodel.py +444 -0
  67. emerge/_emerge/simulation_data.py +411 -0
  68. emerge/_emerge/solver.py +993 -0
  69. emerge/_emerge/system.py +54 -0
  70. emerge/cli.py +19 -0
  71. emerge/lib.py +1 -1
  72. emerge/plot.py +1 -1
  73. {emerge-0.4.7.dist-info → emerge-0.4.9.dist-info}/METADATA +7 -6
  74. emerge-0.4.9.dist-info/RECORD +78 -0
  75. emerge-0.4.9.dist-info/entry_points.txt +2 -0
  76. emerge-0.4.7.dist-info/RECORD +0 -9
  77. emerge-0.4.7.dist-info/entry_points.txt +0 -2
  78. {emerge-0.4.7.dist-info → emerge-0.4.9.dist-info}/WHEEL +0 -0
@@ -0,0 +1,212 @@
1
+ # EMerge is an open source Python based FEM EM simulation module.
2
+ # Copyright (C) 2025 Robert Fennis.
3
+
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, see
16
+ # <https://www.gnu.org/licenses/>.
17
+
18
+ from __future__ import annotations
19
+ from ..mesh3d import Mesh3D
20
+ import numpy as np
21
+ from typing import Callable
22
+ from scipy.sparse import coo_matrix, csr_matrix
23
+
24
+ from ..mth.optimized import matmul
25
+
26
+ class FEMBasis:
27
+
28
+ def __init__(self, mesh: Mesh3D):
29
+ self.mesh: Mesh3D = mesh
30
+ self.n_edges: int = self.mesh.n_edges
31
+ self.n_tris: int = self.mesh.n_tris
32
+ self.n_tets: int = self.mesh.n_tets
33
+
34
+ self.n_tet_dofs: int = None
35
+ self.n_tri_dofs: int = None
36
+
37
+ self.n_field: int = 2*self.n_edges + 2*self.n_tris
38
+
39
+ self.tet_to_field: np.ndarray = None
40
+
41
+ self.edge_to_field: np.ndarray = None
42
+
43
+ self.tri_to_field: np.ndarray = None
44
+
45
+ self._rows: np.ndarray = None
46
+ self._cols: np.ndarray = None
47
+
48
+
49
+ def interpolate_Ef(self, field: np.ndarray, basis: np.ndarray = None, origin: np.ndarray = None, tetids: np.ndarray = None) -> Callable:
50
+ '''Generates the Interpolation function as a function object for a given coordiante basis and origin.'''
51
+ if basis is None:
52
+ basis = np.eye(3)
53
+
54
+ if origin is None:
55
+ origin = np.zeros(3)
56
+
57
+ ibasis = np.linalg.pinv(basis)
58
+ def func(xs: np.ndarray, ys: np.ndarray, zs: np.ndarray) -> np.ndarray:
59
+ xyz = np.array([xs, ys, zs]) + origin[:, np.newaxis]
60
+ xyzg = matmul(basis, xyz)
61
+ return matmul(ibasis, np.array(self.interpolate(field, xyzg[0,:], xyzg[1,:], xyzg[2,:], tetids)))
62
+ return func
63
+
64
+ def interpolate(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs: np.ndarray, tetids: np.ndarray = None) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
65
+ pass
66
+
67
+ def interpolate_curl(self, field: np.ndarray, xs: np.ndarray, ys: np.ndarray, zs: np.ndarray, constants: np.ndarray, tetids: np.ndarray = None) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
68
+ """
69
+ Interpolates the curl of the field at the given points.
70
+ """
71
+ pass
72
+
73
+ def empty_tet_matrix(self) -> np.ndarray:
74
+ nnz = self.n_tets*self.n_tet_dofs**2
75
+ matrix = np.empty((nnz,), dtype=np.complex128)
76
+ return matrix
77
+
78
+ def empty_tri_matrix(self) -> np.ndarray:
79
+ nnz = self.n_tris*self.n_tri_dofs**2
80
+ matrix = np.zeros((nnz,), dtype=np.complex128)
81
+ return matrix
82
+
83
+ def empty_tet_rowcol(self) -> tuple[np.ndarray, np.ndarray]:
84
+ N = self.n_tet_dofs
85
+ N2 = N**2
86
+ nnz = self.n_tets*N2
87
+ rows = np.empty(nnz, dtype=np.int64)
88
+ cols = np.empty(nnz, dtype=np.int64)
89
+
90
+ for itet in range(self.n_tets):
91
+ p = itet*N2
92
+
93
+ indices = self.tet_to_field[:, itet]
94
+ for ii in range(self.n_tet_dofs):
95
+ rows[p+N*ii:p+N*(ii+1)] = indices[ii]
96
+ cols[p+ii:p+N2:N] = indices[ii]
97
+ self._rows = rows
98
+ self._cols = cols
99
+ return rows, cols
100
+
101
+ def empty_tri_rowcol(self) -> tuple[np.ndarray, np.ndarray]:
102
+ N = self.n_tri_dofs
103
+ N2 = N**2
104
+ nnz = self.n_tris*N2
105
+ rows = np.empty(nnz, dtype=np.int64)
106
+ cols = np.empty(nnz, dtype=np.int64)
107
+
108
+ for itri in range(self.n_tris):
109
+ p = itri*N2
110
+ indices = self.tri_to_field[:, itri]
111
+ for ii in range(N):
112
+ rows[p+N*ii:p+N*(ii+1)] = indices[ii]
113
+ cols[p+ii:p+N2:N] = indices[ii]
114
+
115
+ self._rows = rows
116
+ self._cols = cols
117
+ return rows, cols
118
+
119
+ def tetslice(self, itet: int) -> slice:
120
+ N = self.n_tet_dofs**2
121
+ return slice(itet*N,(itet+1)*N)
122
+
123
+ def trislice(self, itri: int) -> slice:
124
+ N = self.n_tri_dofs**2
125
+ return slice(itri*N,(itri+1)*N)
126
+
127
+ def generate_csr(self, data: np.ndarray) -> csr_matrix:
128
+ ids = np.argwhere(data!=0)[:,0]
129
+ return csr_matrix((data[ids], (self._rows[ids], self._cols[ids])), shape=(self.n_field, self.n_field))
130
+ ### QUANTITIES
131
+
132
+ def tet_to_edge_lengths(self, itet: int) -> np.ndarray:
133
+ """
134
+ Returns the edge lengths of the tetrahedron itet.
135
+ """
136
+ return self.mesh.edge_lengths[self.mesh.tet_to_edge[:,itet]]
137
+
138
+ def tri_to_edge_lengths(self, itri: int) -> np.ndarray:
139
+ """
140
+ Returns the edge lengths of the triangle itri.
141
+ """
142
+ return self.mesh.edge_lengths[self.mesh.tri_to_edge[:,itri]]
143
+ ####### INDEX MAPPINGS
144
+
145
+ def local_tet_to_triid(self, itet: int) -> np.ndarray:
146
+ raise NotImplementedError("local_tet_to_triid not implemented")
147
+
148
+ def local_tet_to_edgeid(self, itet: int) -> np.ndarray:
149
+ raise NotImplementedError("local_tet_to_edgeid not implemented")
150
+
151
+ def interpolate_index(self, xs: np.ndarray,
152
+ ys: np.ndarray,
153
+ zs: np.ndarray,
154
+ tetids: np.ndarray = None) -> np.ndarray:
155
+ raise NotImplementedError()
156
+
157
+ def map_edge_to_field(self, edge_ids: np.ndarray) -> np.ndarray:
158
+ """
159
+ Returns the field ids for the edges.
160
+ """
161
+ return edge_ids
162
+
163
+ # ##### CUTS
164
+
165
+ @property
166
+ def bounds(self) -> tuple[tuple[float, float], tuple[float, float],tuple[float, float]]:
167
+ xmin = np.min(self.mesh.nodes[0,:])
168
+ xmax = np.max(self.mesh.nodes[0,:])
169
+ ymin = np.min(self.mesh.nodes[1,:])
170
+ ymax = np.max(self.mesh.nodes[1,:])
171
+ zmin = np.min(self.mesh.nodes[2,:])
172
+ zmax = np.max(self.mesh.nodes[2,:])
173
+ return (xmin, xmax), (ymin, ymax), (zmin, zmax)
174
+
175
+ # @staticmethod
176
+ # def tet_stiff_mass_submatrix(tet_vertices: np.ndarray,
177
+ # edge_lengths: np.ndarray,
178
+ # local_edge_map: np.ndarray,
179
+ # local_tri_map: np.ndarray,
180
+ # C_stiffness: float,
181
+ # C_mass: float) -> tuple[np.ndarray, np.ndarray]:
182
+ # pass
183
+
184
+ # @staticmethod
185
+ # def tri_stiff_mass_submatrix(tri_vertices: np.ndarray,
186
+ # edge_lengths: np.ndarray,
187
+ # local_edge_map: np.ndarray,
188
+ # C_stiffness: float,
189
+ # C_mass: float) -> tuple[np.ndarray, np.ndarray]:
190
+ # pass
191
+
192
+ # @staticmethod
193
+ # def tri_stiff_vec_matrix(lcs_vertices: np.ndarray,
194
+ # edge_lengths: np.ndarray,
195
+ # gamma: complex,
196
+ # lcs_Uinc: np.ndarray,
197
+ # DPTs: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
198
+ # pass
199
+
200
+ # @staticmethod
201
+ # def tri_stiff_matrix(lcs_vertices: np.ndarray,
202
+ # edge_lengths: np.ndarray,
203
+ # gamma: complex) -> tuple[np.ndarray, np.ndarray]:
204
+ # pass
205
+
206
+
207
+ # @staticmethod
208
+ # def tri_surf_integral(lcs_vertices: np.ndarray,
209
+ # edge_lengths: np.ndarray,
210
+ # lcs_Uinc: np.ndarray,
211
+ # DPTs: np.ndarray) -> complex:
212
+ # pass
@@ -0,0 +1,64 @@
1
+ # EMerge is an open source Python based FEM EM simulation module.
2
+ # Copyright (C) 2025 Robert Fennis.
3
+
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, see
16
+ # <https://www.gnu.org/licenses/>.
17
+ from numba import njit, f8, c16, i8, types
18
+ import numpy as np
19
+
20
+
21
+ @njit(i8[:](f8[:,:], i8[:,:], f8[:,:], i8[:]), cache=True, nogil=True)
22
+ def index_interp(coords: np.ndarray,
23
+ tets: np.ndarray,
24
+ nodes: np.ndarray,
25
+ tetids: np.ndarray):
26
+ ''' Nedelec 2 tetrahedral interpolation of the analytic curl'''
27
+ # Solution has shape (nEdges, nsols)
28
+ nNodes = coords.shape[1]
29
+
30
+ prop = np.zeros((nNodes, ), dtype=np.int64)
31
+
32
+
33
+ for i_iter in range(tetids.shape[0]):
34
+ itet = tetids[i_iter]
35
+
36
+ iv1, iv2, iv3, iv4 = tets[:, itet]
37
+
38
+ v1 = nodes[:,iv1]
39
+ v2 = nodes[:,iv2]
40
+ v3 = nodes[:,iv3]
41
+ v4 = nodes[:,iv4]
42
+
43
+ bv1 = v2 - v1
44
+ bv2 = v3 - v1
45
+ bv3 = v4 - v1
46
+
47
+ blocal = np.zeros((3,3))
48
+ blocal[:,0] = bv1
49
+ blocal[:,1] = bv2
50
+ blocal[:,2] = bv3
51
+ basis = np.linalg.pinv(blocal)
52
+
53
+ coords_offset = coords - v1[:,np.newaxis]
54
+ coords_local = (basis @ (coords_offset))
55
+
56
+
57
+ inside = ((coords_local[0,:] + coords_local[1,:] + coords_local[2,:]) <= 1.00000001) & (coords_local[0,:] >= -1e-6) & (coords_local[1,:] >= -1e-6) & (coords_local[2,:] >= -1e-6)
58
+
59
+ if inside.sum() == 0:
60
+ continue
61
+
62
+ prop[inside] = itet
63
+
64
+ return prop
@@ -0,0 +1,172 @@
1
+ # # EMerge is an open source Python based FEM EM simulation module.
2
+ # # Copyright (C) 2025 Robert Fennis.
3
+
4
+ # # This program is free software; you can redistribute it and/or
5
+ # # modify it under the terms of the GNU General Public License
6
+ # # as published by the Free Software Foundation; either version 2
7
+ # # of the License, or (at your option) any later version.
8
+
9
+ # # This program is distributed in the hope that it will be useful,
10
+ # # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # # GNU General Public License for more details.
13
+
14
+ # # You should have received a copy of the GNU General Public License
15
+ # # along with this program; if not, see
16
+ # # <https://www.gnu.org/licenses/>.
17
+
18
+ # from __future__ import annotations
19
+ # import numpy as np
20
+ # from ..mesh3d import Mesh3D
21
+ # from ..dataset_old import Dataset, Axis
22
+ # from .femdata import FEMBasis
23
+ # from ..mth.tet import leg2_tet_interp, leg2_tet_grad_interp, leg2_tet_stiff
24
+ # from ..mth.tri import leg2_tri_stiff
25
+ # from ..mth.optimized import local_mapping
26
+ # from typing import Callable
27
+
28
+ # ############### Nedelec2 Class
29
+
30
+ # class Legrange2(FEMBasis):
31
+
32
+
33
+ # def __init__(self, mesh: Mesh3D):
34
+ # super().__init__(mesh)
35
+
36
+ # self.nedges: int = self.mesh.n_edges
37
+ # self.ntris: int = self.mesh.n_tris
38
+ # self.ntets: int = self.mesh.n_tets
39
+
40
+ # self.nfield: int = 2*self.nedges + 2*self.ntris
41
+
42
+ # self.axes: list[Axis] = []
43
+ # self.fieldata: Dataset = None
44
+
45
+ # ######## MESH Derived
46
+
47
+ # nedges = self.mesh.n_edges
48
+ # ntris = self.mesh.n_tris
49
+
50
+ # self.tet_to_field: np.ndarray = np.zeros((10, self.mesh.tets.shape[1]), dtype=int)
51
+ # self.tet_to_field[:4,:] = self.mesh.tets
52
+ # self.tet_to_field[4:10,:] = self.mesh.tet_to_edge + self.mesh.n_nodes
53
+
54
+ # self.edge_to_field: np.ndarray = np.arange(nedges) + self.mesh.n_nodes
55
+
56
+ # self.tri_to_field: np.ndarray = np.zeros((6,ntris), dtype=int)
57
+
58
+ # self.tri_to_field[:3,:] = self.mesh.tris
59
+ # self.tri_to_field[3:6,:] = self.mesh.tri_to_edge + self.mesh.n_nodes
60
+
61
+ # ##
62
+ # self._field: np.ndarray = None
63
+
64
+ # def __call__(self, **kwargs) -> Legrange2:
65
+ # self._field = self.fielddata(**kwargs)
66
+ # return self
67
+
68
+ # def interpolate(self, field, xs: np.ndarray, ys: np.ndarray, zs:np.ndarray, tet_ids: np.ndarray = None) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
69
+ # if tet_ids is None:
70
+ # tet_ids = np.arange(self.mesh.n_tets)
71
+ # return leg2_tet_interp(np.array([xs, ys,zs]), field, self.mesh.tets, self.mesh.tris, self.mesh.edges, self.mesh.nodes, self.tet_to_field, self.mesh.tet_to_edge, self.mesh.tet_to_tri, tet_ids)
72
+
73
+ # def interpolate_grad(self, field, xs: np.ndarray, ys: np.ndarray, zs:np.ndarray, tet_ids: np.ndarray = None) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
74
+ # if tet_ids is None:
75
+ # tet_ids = np.arange(self.mesh.tet_ids)
76
+ # return leg2_tet_grad_interp(np.array([xs, ys,zs]), field, self.mesh.tets, self.mesh.tris, self.mesh.edges, self.mesh.nodes, self.tet_to_field, self.mesh.tet_to_edge, self.mesh.tet_to_tri, tet_ids)
77
+
78
+ # def fieldf(self, field: np.ndarray, basis: np.ndarray = None, origin: np.ndarray = None) -> Callable:
79
+ # if basis is None:
80
+ # basis = np.eye(3)
81
+
82
+ # if origin is None:
83
+ # origin = np.zeros(3)
84
+
85
+ # ibasis = np.linalg.pinv(basis)
86
+ # def func(xs: np.ndarray, ys: np.ndarray, zs: np.ndarray) -> np.ndarray:
87
+ # xyz = np.array([xs, ys, zs]) + origin[:, np.newaxis]
88
+ # xyzg = basis @ xyz
89
+ # return ibasis @ np.array(self.interpolate(field, xyzg[0,:], xyzg[1,:], xyzg[2,:]))
90
+ # return func
91
+
92
+
93
+ # ###### Vertex getter
94
+
95
+ # def field_to_vertices(self, ifield: np.ndarray):
96
+ # return_ids = ifield[ifield < self.mesh.n_nodes]
97
+ # return return_ids
98
+
99
+ # def field_to_edges(self, ifield: np.ndarray):
100
+ # return_ids = ifield[ifield >= self.mesh.n_nodes] - self.mesh.n_nodes
101
+ # return return_ids
102
+ # ###### INDEX MAPPINGS
103
+
104
+ # def local_tet_to_triid(self, itet: int) -> np.ndarray:
105
+ # tri_ids = self.tet_to_field[6:10, itet] - self.n_edges
106
+ # global_tri_map = self.mesh.tris[:, tri_ids]
107
+ # return local_mapping(self.mesh.tets[:, itet], global_tri_map)
108
+
109
+ # def local_tet_to_edgeid(self, itet: int) -> np.ndarray:
110
+ # global_edge_map = self.mesh.edges[:, self.tet_to_field[:6,itet]]
111
+ # return local_mapping(self.mesh.tets[:, itet], global_edge_map)
112
+
113
+ # def local_tri_to_edgeid(self, itri: int) -> np.ndarray:
114
+ # global_edge_map = self.mesh.edges[:, self.tri_to_field[:3,itri]]
115
+ # return local_mapping(self.mesh.tris[:, itri], global_edge_map)
116
+
117
+ # def map_edge_to_field(self, edge_ids: np.ndarray) -> np.ndarray:
118
+ # """
119
+ # Returns the field ids for the edges.
120
+ # """
121
+ # # Concatinate the edges with the edges + ntris + nedges
122
+ # edge_ids = np.array(edge_ids)
123
+ # return np.concatenate((edge_ids, edge_ids + self.ntris + self.nedges))
124
+
125
+ # ########
126
+ # @staticmethod
127
+ # def tet_stiff_mass_submatrix(tet_vertices: np.ndarray,
128
+ # edge_lengths: np.ndarray,
129
+ # local_edge_map: np.ndarray,
130
+ # local_tri_map: np.ndarray,
131
+ # C_stiffness: float,
132
+ # C_mass: float) -> tuple[np.ndarray, np.ndarray]:
133
+ # raise NotImplementedError("tet_stiff_mass_submatrix is not implemented for Legrange2")
134
+
135
+ # @staticmethod
136
+ # def tet_stiff_submatrix(tet_vertices: np.ndarray,
137
+ # edge_lengths: np.ndarray,
138
+ # local_edge_map: np.ndarray,
139
+ # local_tri_map: np.ndarray,
140
+ # C_stiffness: float) -> tuple[np.ndarray, np.ndarray]:
141
+ # raise leg2_tet_stiff(tet_vertices, edge_lengths, local_edge_map, local_tri_map, C_stiffness)
142
+
143
+
144
+ # @staticmethod
145
+ # def tri_stiff_mass_submatrix(tri_vertices: np.ndarray,
146
+ # edge_lengths: np.ndarray,
147
+ # local_edge_map: np.ndarray,
148
+ # C_stiffness: float,
149
+ # C_mass: float) -> tuple[np.ndarray, np.ndarray]:
150
+ # raise NotImplementedError("tri stiff mass is not implemented for Legrange2")
151
+
152
+ # @staticmethod
153
+ # def tri_stiff_submatrix(tri_vertices: np.ndarray,
154
+ # local_edge_map: np.ndarray,
155
+ # C_stiffness: float) -> np.ndarray:
156
+ # return leg2_tri_stiff(tri_vertices, local_edge_map, C_stiffness)
157
+
158
+
159
+ # @staticmethod
160
+ # def tri_stiff_vec_matrix(lcs_vertices: np.ndarray,
161
+ # edge_lengths: np.ndarray,
162
+ # gamma: complex,
163
+ # lcs_Uinc: np.ndarray,
164
+ # DPTs: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
165
+ # raise NotImplementedError("tri stiff mass is not implemented for Legrange2")
166
+
167
+ # @staticmethod
168
+ # def tri_surf_integral(lcs_vertices: np.ndarray,
169
+ # edge_lengths: np.ndarray,
170
+ # lcs_Uinc: np.ndarray,
171
+ # DPTs: np.ndarray) -> complex:
172
+ # raise NotImplementedError("tri stiff mass is not implemented for Legrange2")