emerge 0.4.6__py3-none-any.whl → 0.4.8__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.
- emerge/__init__.py +54 -0
- emerge/__main__.py +5 -0
- emerge/_emerge/__init__.py +42 -0
- emerge/_emerge/bc.py +197 -0
- emerge/_emerge/coord.py +119 -0
- emerge/_emerge/cs.py +523 -0
- emerge/_emerge/dataset.py +36 -0
- emerge/_emerge/elements/__init__.py +19 -0
- emerge/_emerge/elements/femdata.py +212 -0
- emerge/_emerge/elements/index_interp.py +64 -0
- emerge/_emerge/elements/legrange2.py +172 -0
- emerge/_emerge/elements/ned2_interp.py +645 -0
- emerge/_emerge/elements/nedelec2.py +140 -0
- emerge/_emerge/elements/nedleg2.py +217 -0
- emerge/_emerge/geo/__init__.py +24 -0
- emerge/_emerge/geo/horn.py +107 -0
- emerge/_emerge/geo/modeler.py +449 -0
- emerge/_emerge/geo/operations.py +254 -0
- emerge/_emerge/geo/pcb.py +1244 -0
- emerge/_emerge/geo/pcb_tools/calculator.py +28 -0
- emerge/_emerge/geo/pcb_tools/macro.py +79 -0
- emerge/_emerge/geo/pmlbox.py +204 -0
- emerge/_emerge/geo/polybased.py +529 -0
- emerge/_emerge/geo/shapes.py +427 -0
- emerge/_emerge/geo/step.py +77 -0
- emerge/_emerge/geo2d.py +86 -0
- emerge/_emerge/geometry.py +510 -0
- emerge/_emerge/howto.py +214 -0
- emerge/_emerge/logsettings.py +5 -0
- emerge/_emerge/material.py +118 -0
- emerge/_emerge/mesh3d.py +730 -0
- emerge/_emerge/mesher.py +339 -0
- emerge/_emerge/mth/common_functions.py +33 -0
- emerge/_emerge/mth/integrals.py +71 -0
- emerge/_emerge/mth/optimized.py +357 -0
- emerge/_emerge/periodic.py +263 -0
- emerge/_emerge/physics/__init__.py +0 -0
- emerge/_emerge/physics/microwave/__init__.py +1 -0
- emerge/_emerge/physics/microwave/adaptive_freq.py +279 -0
- emerge/_emerge/physics/microwave/assembly/assembler.py +569 -0
- emerge/_emerge/physics/microwave/assembly/curlcurl.py +448 -0
- emerge/_emerge/physics/microwave/assembly/generalized_eigen.py +426 -0
- emerge/_emerge/physics/microwave/assembly/robinbc.py +433 -0
- emerge/_emerge/physics/microwave/microwave_3d.py +1150 -0
- emerge/_emerge/physics/microwave/microwave_bc.py +915 -0
- emerge/_emerge/physics/microwave/microwave_data.py +1148 -0
- emerge/_emerge/physics/microwave/periodic.py +82 -0
- emerge/_emerge/physics/microwave/port_functions.py +53 -0
- emerge/_emerge/physics/microwave/sc.py +175 -0
- emerge/_emerge/physics/microwave/simjob.py +147 -0
- emerge/_emerge/physics/microwave/sparam.py +138 -0
- emerge/_emerge/physics/microwave/touchstone.py +140 -0
- emerge/_emerge/plot/__init__.py +0 -0
- emerge/_emerge/plot/display.py +394 -0
- emerge/_emerge/plot/grapher.py +93 -0
- emerge/_emerge/plot/matplotlib/mpldisplay.py +264 -0
- emerge/_emerge/plot/pyvista/__init__.py +1 -0
- emerge/_emerge/plot/pyvista/display.py +931 -0
- emerge/_emerge/plot/pyvista/display_settings.py +24 -0
- emerge/_emerge/plot/simple_plots.py +551 -0
- emerge/_emerge/plot.py +225 -0
- emerge/_emerge/projects/__init__.py +0 -0
- emerge/_emerge/projects/_gen_base.txt +32 -0
- emerge/_emerge/projects/_load_base.txt +24 -0
- emerge/_emerge/projects/generate_project.py +40 -0
- emerge/_emerge/selection.py +596 -0
- emerge/_emerge/simmodel.py +444 -0
- emerge/_emerge/simulation_data.py +411 -0
- emerge/_emerge/solver.py +993 -0
- emerge/_emerge/system.py +54 -0
- emerge/cli.py +19 -0
- emerge/lib.py +57 -0
- emerge/plot.py +1 -0
- emerge/pyvista.py +1 -0
- {emerge-0.4.6.dist-info → emerge-0.4.8.dist-info}/METADATA +1 -1
- emerge-0.4.8.dist-info/RECORD +78 -0
- emerge-0.4.8.dist-info/entry_points.txt +2 -0
- emerge-0.4.6.dist-info/RECORD +0 -4
- emerge-0.4.6.dist-info/entry_points.txt +0 -2
- {emerge-0.4.6.dist-info → emerge-0.4.8.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,433 @@
|
|
|
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
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
from numba import njit, f8, c16, i8, types, prange
|
|
21
|
+
from ....elements import Nedelec2
|
|
22
|
+
from typing import Callable
|
|
23
|
+
from loguru import logger
|
|
24
|
+
|
|
25
|
+
_FACTORIALS = np.array([1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880], dtype=np.int64)
|
|
26
|
+
|
|
27
|
+
@njit(cache=True, fastmath=True, nogil=True)
|
|
28
|
+
def optim_matmul(B: np.ndarray, data: np.ndarray):
|
|
29
|
+
dnew = np.zeros_like(data)
|
|
30
|
+
dnew[0,:] = B[0,0]*data[0,:] + B[0,1]*data[1,:] + B[0,2]*data[2,:]
|
|
31
|
+
dnew[1,:] = B[1,0]*data[0,:] + B[1,1]*data[1,:] + B[1,2]*data[2,:]
|
|
32
|
+
dnew[2,:] = B[2,0]*data[0,:] + B[2,1]*data[1,:] + B[2,2]*data[2,:]
|
|
33
|
+
return dnew
|
|
34
|
+
|
|
35
|
+
@njit(f8(i8, i8, i8, i8), cache=True, fastmath=True, nogil=True)
|
|
36
|
+
def area_coeff(a, b, c, d):
|
|
37
|
+
klmn = np.array([0,0,0,0,0,0,0])
|
|
38
|
+
klmn[a] += 1
|
|
39
|
+
klmn[b] += 1
|
|
40
|
+
klmn[c] += 1
|
|
41
|
+
klmn[d] += 1
|
|
42
|
+
output = 2*(_FACTORIALS[klmn[1]]*_FACTORIALS[klmn[2]]*_FACTORIALS[klmn[3]]
|
|
43
|
+
*_FACTORIALS[klmn[4]]*_FACTORIALS[klmn[5]]*_FACTORIALS[klmn[6]])/_FACTORIALS[(np.sum(klmn[1:])+2)]
|
|
44
|
+
return output
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
NFILL = 5
|
|
48
|
+
AREA_COEFF_CACHE_BASE = np.zeros((NFILL,NFILL,NFILL,NFILL), dtype=np.float64)
|
|
49
|
+
for I in range(NFILL):
|
|
50
|
+
for J in range(NFILL):
|
|
51
|
+
for K in range(NFILL):
|
|
52
|
+
for L in range(NFILL):
|
|
53
|
+
AREA_COEFF_CACHE_BASE[I,J,K,L] = area_coeff(I,J,K,L)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@njit(f8(f8[:], f8[:]), cache=True, fastmath=True, nogil=True)
|
|
58
|
+
def dot(a: np.ndarray, b: np.ndarray):
|
|
59
|
+
return a[0]*b[0] + a[1]*b[1]
|
|
60
|
+
|
|
61
|
+
@njit(f8[:](f8[:], f8[:]), cache=True, fastmath=True, nogil=True)
|
|
62
|
+
def cross(a: np.ndarray, b: np.ndarray):
|
|
63
|
+
crossv = np.empty((3,), dtype=np.float64)
|
|
64
|
+
crossv[0] = a[1]*b[2] - a[2]*b[1]
|
|
65
|
+
crossv[1] = a[2]*b[0] - a[0]*b[2]
|
|
66
|
+
crossv[2] = a[0]*b[1] - a[1]*b[0]
|
|
67
|
+
return crossv
|
|
68
|
+
|
|
69
|
+
@njit(types.Tuple((f8[:],f8[:]))(f8[:,:], i8[:,:], f8[:,:], i8[:]), cache=True, nogil=True)
|
|
70
|
+
def generate_points(vertices_local, tris, DPTs, surf_triangle_indices):
|
|
71
|
+
NS = surf_triangle_indices.shape[0]
|
|
72
|
+
xall = np.zeros((DPTs.shape[1], NS))
|
|
73
|
+
yall = np.zeros((DPTs.shape[1], NS))
|
|
74
|
+
|
|
75
|
+
for i in range(NS):
|
|
76
|
+
itri = surf_triangle_indices[i]
|
|
77
|
+
vertex_ids = tris[:, itri]
|
|
78
|
+
|
|
79
|
+
x1, x2, x3 = vertices_local[0, vertex_ids]
|
|
80
|
+
y1, y2, y3 = vertices_local[1, vertex_ids]
|
|
81
|
+
|
|
82
|
+
xall[:,i] = x1*DPTs[1,:] + x2*DPTs[2,:] + x3*DPTs[3,:]
|
|
83
|
+
yall[:,i] = y1*DPTs[1,:] + y2*DPTs[2,:] + y3*DPTs[3,:]
|
|
84
|
+
|
|
85
|
+
xflat = xall.flatten()
|
|
86
|
+
yflat = yall.flatten()
|
|
87
|
+
return xflat, yflat
|
|
88
|
+
|
|
89
|
+
@njit(f8[:,:](f8[:], f8[:], f8[:]), cache=True, nogil=True, fastmath=True)
|
|
90
|
+
def compute_distances(xs: np.ndarray, ys: np.ndarray, zs: np.ndarray) -> np.ndarray:
|
|
91
|
+
N = xs.shape[0]
|
|
92
|
+
Ds = np.empty((N,N), dtype=np.float64)
|
|
93
|
+
for i in range(N):
|
|
94
|
+
for j in range(i,N):
|
|
95
|
+
Ds[i,j] = np.sqrt((xs[i]-xs[j])**2 + (ys[i]-ys[j])**2 + (zs[i]-zs[j])**2)
|
|
96
|
+
Ds[j,i] = Ds[i,j]
|
|
97
|
+
return Ds
|
|
98
|
+
|
|
99
|
+
@njit(types.Tuple((c16[:,:],c16[:]))(f8[:,:], c16, c16[:,:], f8[:,:]), cache=True, nogil=True, parallel=False)
|
|
100
|
+
def ned2_tri_stiff_force(lcs_vertices, gamma, lcs_Uinc, DPTs):
|
|
101
|
+
''' Nedelec-2 Triangle Stiffness matrix and forcing vector (For Boundary Condition of the Third Kind)
|
|
102
|
+
|
|
103
|
+
'''
|
|
104
|
+
local_edge_map = np.array([[0,1,0],[1,2,2]])
|
|
105
|
+
Bmat = np.zeros((8,8), dtype=np.complex128)
|
|
106
|
+
bvec = np.zeros((8,), dtype=np.complex128)
|
|
107
|
+
|
|
108
|
+
xs = lcs_vertices[0,:]
|
|
109
|
+
ys = lcs_vertices[1,:]
|
|
110
|
+
|
|
111
|
+
x1, x2, x3 = xs
|
|
112
|
+
y1, y2, y3 = ys
|
|
113
|
+
|
|
114
|
+
a1 = x2*y3-y2*x3
|
|
115
|
+
a2 = x3*y1-y3*x1
|
|
116
|
+
a3 = x1*y2-y1*x2
|
|
117
|
+
b1 = y2-y3
|
|
118
|
+
b2 = y3-y1
|
|
119
|
+
b3 = y1-y2
|
|
120
|
+
c1 = x3-x2
|
|
121
|
+
c2 = x1-x3
|
|
122
|
+
c3 = x2-x1
|
|
123
|
+
|
|
124
|
+
As = np.array([a1, a2, a3])
|
|
125
|
+
Bs = np.array([b1, b2, b3])
|
|
126
|
+
Cs = np.array([c1, c2, c3])
|
|
127
|
+
|
|
128
|
+
Ds = compute_distances(xs, ys, np.zeros_like(xs))
|
|
129
|
+
|
|
130
|
+
GL1 = np.array([b1, c1])
|
|
131
|
+
GL2 = np.array([b2, c2])
|
|
132
|
+
GL3 = np.array([b3, c3])
|
|
133
|
+
|
|
134
|
+
GLs = (GL1, GL2, GL3)
|
|
135
|
+
|
|
136
|
+
Area = 0.5 * np.abs((x1 - x3) * (y2 - y1) - (x1 - x2) * (y3 - y1))
|
|
137
|
+
signA = -np.sign((x1 - x3) * (y2 - y1) - (x1 - x2) * (y3 - y1))
|
|
138
|
+
|
|
139
|
+
letters = [1,2,3,4,5,6]
|
|
140
|
+
|
|
141
|
+
tA, tB, tC = letters[0], letters[1], letters[2]
|
|
142
|
+
GtA, GtB, GtC = GLs[0], GLs[1], GLs[2]
|
|
143
|
+
|
|
144
|
+
Lt1, Lt2 = Ds[2, 0], Ds[1, 0]
|
|
145
|
+
|
|
146
|
+
Ux = lcs_Uinc[0,:]
|
|
147
|
+
Uy = lcs_Uinc[1,:]
|
|
148
|
+
|
|
149
|
+
x = x1*DPTs[1,:] + x2*DPTs[2,:] + x3*DPTs[3,:]
|
|
150
|
+
y = y1*DPTs[1,:] + y2*DPTs[2,:] + y3*DPTs[3,:]
|
|
151
|
+
|
|
152
|
+
Ws = DPTs[0,:]
|
|
153
|
+
|
|
154
|
+
COEFF = gamma/(2*Area)**2
|
|
155
|
+
AREA_COEFF = AREA_COEFF_CACHE_BASE * Area
|
|
156
|
+
for ei in range(3):
|
|
157
|
+
ei1, ei2 = local_edge_map[:, ei]
|
|
158
|
+
Li = Ds[ei1, ei2]
|
|
159
|
+
|
|
160
|
+
A = letters[ei1]
|
|
161
|
+
B = letters[ei2]
|
|
162
|
+
|
|
163
|
+
GA = GLs[ei1]
|
|
164
|
+
GB = GLs[ei2]
|
|
165
|
+
|
|
166
|
+
for ej in range(3):
|
|
167
|
+
ej1, ej2 = local_edge_map[:, ej]
|
|
168
|
+
Lj = Ds[ej1, ej2]
|
|
169
|
+
|
|
170
|
+
C = letters[ej1]
|
|
171
|
+
D = letters[ej2]
|
|
172
|
+
|
|
173
|
+
GC = GLs[ej1]
|
|
174
|
+
GD = GLs[ej2]
|
|
175
|
+
|
|
176
|
+
DAC = dot(GA,GC)
|
|
177
|
+
DAD = dot(GA,GD)
|
|
178
|
+
DBC = dot(GB,GC)
|
|
179
|
+
DBD = dot(GB,GD)
|
|
180
|
+
LL = Li*Lj
|
|
181
|
+
|
|
182
|
+
Bmat[ei,ej] += LL*(AREA_COEFF[A,B,C,D]*DAC-AREA_COEFF[A,B,C,C]*DAD-AREA_COEFF[A,A,C,D]*DBC+AREA_COEFF[A,A,C,C]*DBD)
|
|
183
|
+
Bmat[ei,ej+4] += LL*(AREA_COEFF[A,B,D,D]*DAC-AREA_COEFF[A,B,C,D]*DAD-AREA_COEFF[A,A,D,D]*DBC+AREA_COEFF[A,A,C,D]*DBD)
|
|
184
|
+
Bmat[ei+4,ej] += LL*(AREA_COEFF[B,B,C,D]*DAC-AREA_COEFF[B,B,C,C]*DAD-AREA_COEFF[A,B,C,D]*DBC+AREA_COEFF[A,B,C,C]*DBD)
|
|
185
|
+
Bmat[ei+4,ej+4] += LL*(AREA_COEFF[B,B,D,D]*DAC-AREA_COEFF[B,B,C,D]*DAD-AREA_COEFF[A,B,D,D]*DBC+AREA_COEFF[A,B,C,D]*DBD)
|
|
186
|
+
|
|
187
|
+
FA = dot(GA,GtC)
|
|
188
|
+
FB = dot(GA,GtA)
|
|
189
|
+
FC = dot(GB,GtC)
|
|
190
|
+
FD = dot(GB,GtA)
|
|
191
|
+
FE = dot(GA,GtB)
|
|
192
|
+
FF = dot(GB,GtB)
|
|
193
|
+
|
|
194
|
+
Bmat[ei,3] += Li*Lt1*(AREA_COEFF[A,B,tA,tB]*FA-AREA_COEFF[A,B,tB,tC]*FB-AREA_COEFF[A,A,tA,tB]*FC+AREA_COEFF[A,A,tB,tC]*FD)
|
|
195
|
+
Bmat[ei,7] += Li*Lt2*(AREA_COEFF[A,B,tB,tC]*FB-AREA_COEFF[A,B,tC,tA]*FE-AREA_COEFF[A,A,tB,tC]*FD+AREA_COEFF[A,A,tC,tA]*FF)
|
|
196
|
+
Bmat[3,ei] += Lt1*Li*(AREA_COEFF[tA,tB,A,B]*FA-AREA_COEFF[tA,tB,A,A]*FC-AREA_COEFF[tB,tC,A,B]*FB+AREA_COEFF[tB,tC,A,A]*FD)
|
|
197
|
+
Bmat[7,ei] += Lt2*Li*(AREA_COEFF[tB,tC,A,B]*FB-AREA_COEFF[tB,tC,A,A]*FD-AREA_COEFF[tC,tA,A,B]*FE+AREA_COEFF[tC,tA,A,A]*FF)
|
|
198
|
+
Bmat[ei+4,3] += Li*Lt1*(AREA_COEFF[B,B,tA,tB]*FA-AREA_COEFF[B,B,tB,tC]*FB-AREA_COEFF[A,B,tA,tB]*FC+AREA_COEFF[A,B,tB,tC]*FD)
|
|
199
|
+
Bmat[ei+4,7] += Li*Lt2*(AREA_COEFF[B,B,tB,tC]*FB-AREA_COEFF[B,B,tC,tA]*FE-AREA_COEFF[A,B,tB,tC]*FD+AREA_COEFF[A,B,tC,tA]*FF)
|
|
200
|
+
Bmat[3,ei+4] += Lt1*Li*(AREA_COEFF[tA,tB,B,B]*FA-AREA_COEFF[tA,tB,A,B]*FC-AREA_COEFF[tB,tC,B,B]*FB+AREA_COEFF[tB,tC,A,B]*FD)
|
|
201
|
+
Bmat[7,ei+4] += Lt2*Li*(AREA_COEFF[tB,tC,B,B]*FB-AREA_COEFF[tB,tC,A,B]*FD-AREA_COEFF[tC,tA,B,B]*FE+AREA_COEFF[tC,tA,A,B]*FF)
|
|
202
|
+
|
|
203
|
+
A1, A2 = As[ei1], As[ei2]
|
|
204
|
+
B1, B2 = Bs[ei1], Bs[ei2]
|
|
205
|
+
C1, C2 = Cs[ei1], Cs[ei2]
|
|
206
|
+
|
|
207
|
+
Q = A2 + B2*x + C2*y
|
|
208
|
+
Z = A1 + B1*x + C1*y
|
|
209
|
+
A4 = (4*Area**2)
|
|
210
|
+
Q2 = Q/A4
|
|
211
|
+
Z2 = Z/A4
|
|
212
|
+
Ar2 = 1/(2*Area)
|
|
213
|
+
|
|
214
|
+
Ee1x = (B1*Q2 - B2*Z2)*(Z)*Ar2
|
|
215
|
+
Ee1y = (C1*Q2 - C2*Z2)*(Z)*Ar2
|
|
216
|
+
Ee2x = (B1*Q2 - B2*Z2)*(Q)*Ar2
|
|
217
|
+
Ee2y = (C1*Q2 - C2*Z2)*(Q)*Ar2
|
|
218
|
+
|
|
219
|
+
bvec[ei] += signA*Area*Li*np.sum(Ws*(Ee1x*Ux + Ee1y*Uy))
|
|
220
|
+
bvec[ei+4] += signA*Area*Li*np.sum(Ws*(Ee2x*Ux + Ee2y*Uy))
|
|
221
|
+
|
|
222
|
+
H1 = dot(GtA,GtC)
|
|
223
|
+
H2 = dot(GtA,GtA)
|
|
224
|
+
H3 = dot(GtA,GtB)
|
|
225
|
+
|
|
226
|
+
Bmat[3,3] += Lt1*Lt1*(AREA_COEFF[tA,tB,tA,tB]*dot(GtC,GtC)-AREA_COEFF[tA,tB,tB,tC]*H1-AREA_COEFF[tB,tC,tA,tB]*H1+AREA_COEFF[tB,tC,tB,tC]*H2)
|
|
227
|
+
Bmat[3,7] += Lt1*Lt2*(AREA_COEFF[tA,tB,tB,tC]*H1-AREA_COEFF[tA,tB,tC,tA]*dot(GtB,GtC)-AREA_COEFF[tB,tC,tB,tC]*H2+AREA_COEFF[tB,tC,tC,tA]*H3)
|
|
228
|
+
Bmat[7,3] += Lt2*Lt1*(AREA_COEFF[tB,tC,tA,tB]*H1-AREA_COEFF[tB,tC,tB,tC]*H2-AREA_COEFF[tC,tA,tA,tB]*dot(GtB,GtC)+AREA_COEFF[tC,tA,tB,tC]*H3)
|
|
229
|
+
Bmat[7,7] += Lt2*Lt2*(AREA_COEFF[tB,tC,tB,tC]*H2-AREA_COEFF[tB,tC,tC,tA]*H3-AREA_COEFF[tC,tA,tB,tC]*H3+AREA_COEFF[tC,tA,tC,tA]*dot(GtB,GtB))
|
|
230
|
+
|
|
231
|
+
A1, A2, A3 = As
|
|
232
|
+
B1, B2, B3 = Bs
|
|
233
|
+
C1, C2, C3 = Cs
|
|
234
|
+
|
|
235
|
+
Q = A2 + B2*x + C2*y
|
|
236
|
+
Z = A1 + B1*x + C1*y
|
|
237
|
+
FA = (8*Area**3)
|
|
238
|
+
W = (A3 + B3*x + C3*y)/FA
|
|
239
|
+
W2 = Q*W
|
|
240
|
+
|
|
241
|
+
Ef1x = Lt1*(-B1*W2 + B3*(Z)*(Q)/FA)
|
|
242
|
+
Ef1y = Lt1*(-C1*W2 + C3*(Z)*(Q)/FA)
|
|
243
|
+
Ef2x = Lt2*(B1*W2 - B2*(Z)*W)
|
|
244
|
+
Ef2y = Lt2*(C1*W2 - C2*(Z)*W)
|
|
245
|
+
|
|
246
|
+
bvec[3] += signA*Area*np.sum(Ws*(Ef1x*Ux + Ef1y*Uy))
|
|
247
|
+
bvec[7] += signA*Area*np.sum(Ws*(Ef2x*Ux + Ef2y*Uy))
|
|
248
|
+
Bmat = Bmat * COEFF
|
|
249
|
+
return Bmat, bvec
|
|
250
|
+
|
|
251
|
+
@njit(types.Tuple((c16[:], c16[:]))(f8[:,:], i8[:,:], c16[:], c16[:], i8[:], c16, c16[:,:,:], f8[:,:], i8[:,:]), cache=True, nogil=True, parallel=False)
|
|
252
|
+
def compute_bc_entries_excited(vertices_local, tris, Bmat, Bvec, surf_triangle_indices, gamma, Ulocal_all, DPTs, tri_to_field):
|
|
253
|
+
N = 64
|
|
254
|
+
Niter = surf_triangle_indices.shape[0]
|
|
255
|
+
for i in prange(Niter):
|
|
256
|
+
itri = surf_triangle_indices[i]
|
|
257
|
+
|
|
258
|
+
vertex_ids = tris[:, itri]
|
|
259
|
+
|
|
260
|
+
Ulocal = Ulocal_all[:,:, i]
|
|
261
|
+
|
|
262
|
+
Bsub, bvec = ned2_tri_stiff_force(vertices_local[:,vertex_ids], gamma, Ulocal, DPTs)
|
|
263
|
+
|
|
264
|
+
indices = tri_to_field[:, itri]
|
|
265
|
+
|
|
266
|
+
Bmat[itri*N:(itri+1)*N] += Bsub.ravel()
|
|
267
|
+
Bvec[indices] += bvec
|
|
268
|
+
return Bmat, Bvec
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@njit(c16[:,:](f8[:,:], f8[:], c16), cache=True, nogil=True, parallel=False)
|
|
272
|
+
def ned2_tri_stiff(vertices, edge_lengths, gamma):
|
|
273
|
+
''' Nedelec-2 Triangle Stiffness matrix and forcing vector (For Boundary Condition of the Third Kind)
|
|
274
|
+
|
|
275
|
+
'''
|
|
276
|
+
local_edge_map = np.array([[0,1,0],[1,2,2]])
|
|
277
|
+
Bmat = np.zeros((8,8), dtype=np.complex128)
|
|
278
|
+
|
|
279
|
+
xs = vertices[0,:]
|
|
280
|
+
ys = vertices[1,:]
|
|
281
|
+
zs = vertices[2,:]
|
|
282
|
+
|
|
283
|
+
ax1 = np.array([xs[1]-xs[0], ys[1]-ys[0], zs[1]-zs[0]])
|
|
284
|
+
ax2 = np.array([xs[2]-xs[0], ys[2]-ys[0], zs[2]-zs[0]])
|
|
285
|
+
ax1 = ax1/np.linalg.norm(ax1)
|
|
286
|
+
ax2 = ax2/np.linalg.norm(ax2)
|
|
287
|
+
|
|
288
|
+
axn = cross(ax1, ax2)
|
|
289
|
+
ax2 = -cross(axn, ax1)
|
|
290
|
+
basis = np.zeros((3,3), dtype=np.float64)
|
|
291
|
+
basis[:,0] = ax1
|
|
292
|
+
basis[:,1] = ax2
|
|
293
|
+
basis[:,2] = axn
|
|
294
|
+
basis = np.linalg.pinv(basis)
|
|
295
|
+
lcs_vertices = basis @ np.ascontiguousarray(vertices)
|
|
296
|
+
|
|
297
|
+
xs = lcs_vertices[0,:]
|
|
298
|
+
ys = lcs_vertices[1,:]
|
|
299
|
+
|
|
300
|
+
x1, x2, x3 = xs
|
|
301
|
+
y1, y2, y3 = ys
|
|
302
|
+
|
|
303
|
+
b1 = y2-y3
|
|
304
|
+
b2 = y3-y1
|
|
305
|
+
b3 = y1-y2
|
|
306
|
+
c1 = x3-x2
|
|
307
|
+
c2 = x1-x3
|
|
308
|
+
c3 = x2-x1
|
|
309
|
+
|
|
310
|
+
Ds = compute_distances(xs, ys, np.zeros_like(xs))
|
|
311
|
+
|
|
312
|
+
GL1 = np.array([b1, c1])
|
|
313
|
+
GL2 = np.array([b2, c2])
|
|
314
|
+
GL3 = np.array([b3, c3])
|
|
315
|
+
|
|
316
|
+
GLs = (GL1, GL2, GL3)
|
|
317
|
+
|
|
318
|
+
Area = 0.5 * np.abs((x1 - x3) * (y2 - y1) - (x1 - x2) * (y3 - y1))
|
|
319
|
+
|
|
320
|
+
letters = [1,2,3,4,5,6]
|
|
321
|
+
|
|
322
|
+
tA, tB, tC = letters[0], letters[1], letters[2]
|
|
323
|
+
GtA, GtB, GtC = GLs[0], GLs[1], GLs[2]
|
|
324
|
+
|
|
325
|
+
Lt1, Lt2 = Ds[2, 0], Ds[1, 0]
|
|
326
|
+
|
|
327
|
+
COEFF = gamma/(2*Area)**2
|
|
328
|
+
AREA_COEFF = AREA_COEFF_CACHE_BASE * Area
|
|
329
|
+
for ei in range(3):
|
|
330
|
+
ei1, ei2 = local_edge_map[:, ei]
|
|
331
|
+
Li = edge_lengths[ei]
|
|
332
|
+
|
|
333
|
+
A = letters[ei1]
|
|
334
|
+
B = letters[ei2]
|
|
335
|
+
|
|
336
|
+
GA = GLs[ei1]
|
|
337
|
+
GB = GLs[ei2]
|
|
338
|
+
|
|
339
|
+
for ej in range(3):
|
|
340
|
+
ej1, ej2 = local_edge_map[:, ej]
|
|
341
|
+
Lj = edge_lengths[ej]
|
|
342
|
+
|
|
343
|
+
C = letters[ej1]
|
|
344
|
+
D = letters[ej2]
|
|
345
|
+
|
|
346
|
+
GC = GLs[ej1]
|
|
347
|
+
GD = GLs[ej2]
|
|
348
|
+
DAC = dot(GA,GC)
|
|
349
|
+
DAD = dot(GA,GD)
|
|
350
|
+
DBC = dot(GB,GC)
|
|
351
|
+
DBD = dot(GB,GD)
|
|
352
|
+
LL = Li*Lj
|
|
353
|
+
|
|
354
|
+
Bmat[ei,ej] += LL*COEFF*(AREA_COEFF[A,B,C,D]*DAC-AREA_COEFF[A,B,C,C]*DAD-AREA_COEFF[A,A,C,D]*DBC+AREA_COEFF[A,A,C,C]*DBD)
|
|
355
|
+
Bmat[ei,ej+4] += LL*COEFF*(AREA_COEFF[A,B,D,D]*DAC-AREA_COEFF[A,B,C,D]*DAD-AREA_COEFF[A,A,D,D]*DBC+AREA_COEFF[A,A,C,D]*DBD)
|
|
356
|
+
Bmat[ei+4,ej] += LL*COEFF*(AREA_COEFF[B,B,C,D]*DAC-AREA_COEFF[B,B,C,C]*DAD-AREA_COEFF[A,B,C,D]*DBC+AREA_COEFF[A,B,C,C]*DBD)
|
|
357
|
+
Bmat[ei+4,ej+4] += LL*COEFF*(AREA_COEFF[B,B,D,D]*DAC-AREA_COEFF[B,B,C,D]*DAD-AREA_COEFF[A,B,D,D]*DBC+AREA_COEFF[A,B,C,D]*DBD)
|
|
358
|
+
|
|
359
|
+
FA = dot(GA,GtC)
|
|
360
|
+
FB = dot(GA,GtA)
|
|
361
|
+
FC = dot(GB,GtC)
|
|
362
|
+
FD = dot(GB,GtA)
|
|
363
|
+
FE = dot(GA,GtB)
|
|
364
|
+
FF = dot(GB,GtB)
|
|
365
|
+
|
|
366
|
+
Bmat[ei,3] += Li*Lt1*COEFF*(AREA_COEFF[A,B,tA,tB]*FA-AREA_COEFF[A,B,tB,tC]*FB-AREA_COEFF[A,A,tA,tB]*FC+AREA_COEFF[A,A,tB,tC]*FD)
|
|
367
|
+
Bmat[ei,7] += Li*Lt2*COEFF*(AREA_COEFF[A,B,tB,tC]*FB-AREA_COEFF[A,B,tC,tA]*FE-AREA_COEFF[A,A,tB,tC]*FD+AREA_COEFF[A,A,tC,tA]*FF)
|
|
368
|
+
Bmat[3,ei] += Lt1*Li*COEFF*(AREA_COEFF[tA,tB,A,B]*FA-AREA_COEFF[tA,tB,A,A]*FC-AREA_COEFF[tB,tC,A,B]*FB+AREA_COEFF[tB,tC,A,A]*FD)
|
|
369
|
+
Bmat[7,ei] += Lt2*Li*COEFF*(AREA_COEFF[tB,tC,A,B]*FB-AREA_COEFF[tB,tC,A,A]*FD-AREA_COEFF[tC,tA,A,B]*FE+AREA_COEFF[tC,tA,A,A]*FF)
|
|
370
|
+
Bmat[ei+4,3] += Li*Lt1*COEFF*(AREA_COEFF[B,B,tA,tB]*FA-AREA_COEFF[B,B,tB,tC]*FB-AREA_COEFF[A,B,tA,tB]*FC+AREA_COEFF[A,B,tB,tC]*FD)
|
|
371
|
+
Bmat[ei+4,7] += Li*Lt2*COEFF*(AREA_COEFF[B,B,tB,tC]*FB-AREA_COEFF[B,B,tC,tA]*FE-AREA_COEFF[A,B,tB,tC]*FD+AREA_COEFF[A,B,tC,tA]*FF)
|
|
372
|
+
Bmat[3,ei+4] += Lt1*Li*COEFF*(AREA_COEFF[tA,tB,B,B]*FA-AREA_COEFF[tA,tB,A,B]*FC-AREA_COEFF[tB,tC,B,B]*FB+AREA_COEFF[tB,tC,A,B]*FD)
|
|
373
|
+
Bmat[7,ei+4] += Lt2*Li*COEFF*(AREA_COEFF[tB,tC,B,B]*FB-AREA_COEFF[tB,tC,A,B]*FD-AREA_COEFF[tC,tA,B,B]*FE+AREA_COEFF[tC,tA,A,B]*FF)
|
|
374
|
+
|
|
375
|
+
H1 = dot(GtA,GtC)
|
|
376
|
+
H2 = dot(GtA,GtA)
|
|
377
|
+
H3 = dot(GtA,GtB)
|
|
378
|
+
|
|
379
|
+
Bmat[3,3] += Lt1*Lt1*(AREA_COEFF[tA,tB,tA,tB]*dot(GtC,GtC)-AREA_COEFF[tA,tB,tB,tC]*H1-AREA_COEFF[tB,tC,tA,tB]*H1+AREA_COEFF[tB,tC,tB,tC]*H2)
|
|
380
|
+
Bmat[3,7] += Lt1*Lt2*(AREA_COEFF[tA,tB,tB,tC]*H1-AREA_COEFF[tA,tB,tC,tA]*dot(GtB,GtC)-AREA_COEFF[tB,tC,tB,tC]*H2+AREA_COEFF[tB,tC,tC,tA]*H3)
|
|
381
|
+
Bmat[7,3] += Lt2*Lt1*(AREA_COEFF[tB,tC,tA,tB]*H1-AREA_COEFF[tB,tC,tB,tC]*H2-AREA_COEFF[tC,tA,tA,tB]*dot(GtB,GtC)+AREA_COEFF[tC,tA,tB,tC]*H3)
|
|
382
|
+
Bmat[7,7] += Lt2*Lt2*(AREA_COEFF[tB,tC,tB,tC]*H2-AREA_COEFF[tB,tC,tC,tA]*H3-AREA_COEFF[tC,tA,tB,tC]*H3+AREA_COEFF[tC,tA,tC,tA]*dot(GtB,GtB))
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
return Bmat
|
|
386
|
+
|
|
387
|
+
@njit(c16[:](f8[:,:], i8[:,:], c16[:], f8[:,:], i8[:], c16), cache=True, nogil=True, parallel=False)
|
|
388
|
+
def compute_bc_entries(vertices, tris, Bmat, all_edge_lengths, surf_triangle_indices, gamma):
|
|
389
|
+
N = 64
|
|
390
|
+
Niter = surf_triangle_indices.shape[0]
|
|
391
|
+
for i in prange(Niter):
|
|
392
|
+
itri = surf_triangle_indices[i]
|
|
393
|
+
|
|
394
|
+
vertex_ids = tris[:, itri]
|
|
395
|
+
|
|
396
|
+
edge_lengths = all_edge_lengths[:,itri]
|
|
397
|
+
|
|
398
|
+
Bsub = ned2_tri_stiff(vertices[:,vertex_ids], edge_lengths, gamma)
|
|
399
|
+
|
|
400
|
+
Bmat[itri*N:(itri+1)*N] = Bmat[itri*N:(itri+1)*N] + Bsub.ravel()
|
|
401
|
+
return Bmat
|
|
402
|
+
|
|
403
|
+
def assemble_robin_bc_excited(field: Nedelec2,
|
|
404
|
+
Bmat: np.ndarray,
|
|
405
|
+
surf_triangle_indices: np.ndarray,
|
|
406
|
+
Ufunc: Callable,
|
|
407
|
+
gamma: np.ndarray,
|
|
408
|
+
local_basis: np.ndarray,
|
|
409
|
+
origin: np.ndarray,
|
|
410
|
+
DPTs: np.ndarray):
|
|
411
|
+
|
|
412
|
+
Bvec = np.zeros((field.n_field,), dtype=np.complex128)
|
|
413
|
+
|
|
414
|
+
vertices_local = optim_matmul(local_basis, field.mesh.nodes - origin[:,np.newaxis])
|
|
415
|
+
|
|
416
|
+
xflat, yflat = generate_points(vertices_local, field.mesh.tris, DPTs, surf_triangle_indices)
|
|
417
|
+
|
|
418
|
+
Ulocal = Ufunc(xflat, yflat)
|
|
419
|
+
|
|
420
|
+
Ulocal_all = Ulocal.reshape((3, DPTs.shape[1], surf_triangle_indices.shape[0]))
|
|
421
|
+
|
|
422
|
+
Bmat, Bvec = compute_bc_entries_excited(vertices_local, field.mesh.tris, Bmat, Bvec, surf_triangle_indices, gamma, Ulocal_all, DPTs, field.tri_to_field)
|
|
423
|
+
return Bmat, Bvec
|
|
424
|
+
|
|
425
|
+
def assemble_robin_bc(field: Nedelec2,
|
|
426
|
+
Bmat: np.ndarray,
|
|
427
|
+
surf_triangle_indices: np.ndarray,
|
|
428
|
+
gamma: np.ndarray):
|
|
429
|
+
vertices = field.mesh.nodes
|
|
430
|
+
all_edge_lengths = field.mesh.edge_lengths[field.mesh.tri_to_edge]
|
|
431
|
+
Bmat = compute_bc_entries(vertices, field.mesh.tris, Bmat, all_edge_lengths, surf_triangle_indices, gamma)
|
|
432
|
+
|
|
433
|
+
return Bmat
|