emerge 0.5.2__py3-none-any.whl → 0.5.4__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 (35) hide show
  1. emerge/__init__.py +2 -2
  2. emerge/_emerge/__init__.py +1 -26
  3. emerge/_emerge/_cache_check.py +46 -0
  4. emerge/_emerge/bc.py +3 -12
  5. emerge/_emerge/const.py +5 -0
  6. emerge/_emerge/elements/nedleg2.py +2 -2
  7. emerge/_emerge/geo/pcb.py +110 -13
  8. emerge/_emerge/geo/pcb_tools/calculator.py +2 -2
  9. emerge/_emerge/geometry.py +1 -1
  10. emerge/_emerge/logsettings.py +29 -13
  11. emerge/_emerge/material.py +4 -0
  12. emerge/_emerge/mesh3d.py +9 -9
  13. emerge/_emerge/mth/integrals.py +1 -1
  14. emerge/_emerge/mth/pairing.py +1 -2
  15. emerge/_emerge/periodic.py +1 -1
  16. emerge/_emerge/physics/microwave/adaptive_freq.py +1 -5
  17. emerge/_emerge/physics/microwave/assembly/assembler.py +62 -39
  18. emerge/_emerge/physics/microwave/assembly/curlcurl.py +1 -8
  19. emerge/_emerge/physics/microwave/microwave_3d.py +33 -26
  20. emerge/_emerge/physics/microwave/microwave_bc.py +97 -27
  21. emerge/_emerge/physics/microwave/microwave_data.py +3 -5
  22. emerge/_emerge/physics/microwave/sc.py +26 -26
  23. emerge/_emerge/physics/microwave/simjob.py +8 -3
  24. emerge/_emerge/selection.py +1 -1
  25. emerge/_emerge/simmodel.py +12 -9
  26. emerge/_emerge/simulation_data.py +5 -1
  27. emerge/_emerge/solve_interfaces/cudss_interface.py +238 -0
  28. emerge/_emerge/solver.py +285 -107
  29. emerge/cli.py +1 -1
  30. emerge/lib.py +54 -40
  31. {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/METADATA +15 -8
  32. {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/RECORD +35 -32
  33. {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/licenses/LICENSE +39 -0
  34. {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/WHEEL +0 -0
  35. {emerge-0.5.2.dist-info → emerge-0.5.4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,238 @@
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
+ import cupy as cp # ty: ignore
19
+ import nvmath.bindings.cudss as cudss # ty: ignore
20
+ from nvmath import CudaDataType # ty: ignore
21
+
22
+ from scipy.sparse import csr_matrix
23
+ import numpy as np
24
+
25
+ from loguru import logger
26
+
27
+
28
+ ############################################################
29
+ # CONSTANTS #
30
+ ############################################################
31
+
32
+ ALG_NEST_DISS_METIS = cudss.AlgType.ALG_DEFAULT
33
+ ALG_COLAMD = cudss.AlgType.ALG_1
34
+ ALG_COLAMD_BLOCK_TRI = cudss.AlgType.ALG_2
35
+ ALG_AMD = cudss.AlgType.ALG_3
36
+
37
+ FLOAT64 = CudaDataType.CUDA_R_64F
38
+ FLOAT32 = CudaDataType.CUDA_R_32F
39
+ COMPLEX128 = CudaDataType.CUDA_C_64F
40
+ COMPLEX64 = CudaDataType.CUDA_C_32F
41
+ INT64 = CudaDataType.CUDA_R_64I
42
+ INT32 = CudaDataType.CUDA_R_32I
43
+
44
+ INDEX_BASE = cudss.IndexBase.ZERO
45
+
46
+ def _c_pointer(arry) -> int:
47
+ return int(arry.data.ptr)
48
+
49
+ ############################################################
50
+ # INTERFACE #
51
+ ############################################################
52
+
53
+ class CuDSSInterface:
54
+ def __init__(self):
55
+ self.A_cu = None
56
+ self.b_cu = None
57
+ self.x_cu = None
58
+ self.A_cobj = None
59
+ self.b_cobj = None
60
+ self.x_cobj = None
61
+ self.A_pattern = None
62
+
63
+ self._handle = cudss.create()
64
+ self._config = cudss.config_create()
65
+ self._data = cudss.data_create(self._handle)
66
+
67
+ self.MTYPE = cudss.MatrixType.SYMMETRIC
68
+ self.MVIEW = cudss.MatrixViewType.FULL
69
+ self.RALG = cudss.AlgType.ALG_DEFAULT
70
+ self.VTYPE = CudaDataType.CUDA_R_64F
71
+
72
+ self._INDPTR = None
73
+ self._ROW_START: int | None = None
74
+ self._ROW_END: int | None = None
75
+ self._IND = None
76
+ self._VAL = None
77
+ self._NNZ: int | None = None
78
+ self._COMP: bool = True
79
+ self._PRES: int = 2
80
+ self._COL_IDS = None
81
+
82
+ self._initialized = False
83
+
84
+ param = cudss.ConfigParam.REORDERING_ALG
85
+ dtype = cudss.get_config_param_dtype(int(param))
86
+ reorder_alg = np.array(self.RALG, dtype=dtype)
87
+
88
+ cudss.config_set(
89
+ self._config,
90
+ int(param),
91
+ reorder_alg.ctypes.data,
92
+ reorder_alg.nbytes
93
+ )
94
+
95
+ def set_algorithm(self, alg_type: cudss.AlgType):
96
+ self.RALG = alg_type
97
+
98
+ def init_type(self):
99
+ if self._PRES == 1:
100
+ if self._COMP:
101
+ self.c_dtype = cp.complex64
102
+ self.VTYPE = COMPLEX64
103
+ else:
104
+ self.c_dtype = cp.float32
105
+ self.VTYPE = FLOAT32
106
+ else:
107
+ if self._COMP:
108
+ self.c_dtype = cp.complex128
109
+ self.VTYPE = COMPLEX128
110
+ else:
111
+ self.c_dtype = cp.float64
112
+ self.VTYPE = FLOAT64
113
+
114
+ def submit_matrix(self, A: csr_matrix):
115
+ self.N = A.shape[0]
116
+
117
+ if np.iscomplexobj(A):
118
+ self._COMP = True
119
+ else:
120
+ self._COMP = False
121
+
122
+ self.init_type()
123
+
124
+ self.A_cu = cp.sparse.csr_matrix(A).astype(self.c_dtype)
125
+
126
+ self._INDPTR = cp.ascontiguousarray(self.A_cu.indptr.astype(cp.int32))
127
+ self._IND = cp.ascontiguousarray(self.A_cu.indices.astype(cp.int32))
128
+ self._VAL = cp.ascontiguousarray(self.A_cu.data)
129
+ self._NNZ = int(self._VAL.size)
130
+ self._ROW_START = self._INDPTR[:-1]
131
+ self._ROW_END = self._INDPTR[1:]
132
+ self._COL_IDS = self.A_cu.indices.astype(cp.int32)
133
+
134
+ def submit_vector(self, b: np.ndarray):
135
+ self.b_cu = cp.array(b).astype(self.c_dtype)
136
+
137
+ def create_solvec(self):
138
+ self.x_cu = cp.empty_like(self.b_cu)
139
+
140
+ def _update_dss_data(self):
141
+ cudss.matrix_set_values(self.A_cobj, _c_pointer(self._VAL))
142
+
143
+
144
+ self.b_cobj = cudss.matrix_create_dn(self.N, 1, self.N, _c_pointer(self.b_cu),
145
+ int(self.VTYPE), int(cudss.Layout.COL_MAJOR))
146
+ self.x_cobj = cudss.matrix_create_dn(self.N, 1, self.N, _c_pointer(self.x_cu),
147
+ int(self.VTYPE), int(cudss.Layout.COL_MAJOR))
148
+
149
+ def _create_dss_data(self):
150
+ self.A_cobj = cudss.matrix_create_csr(
151
+ self.N,self.N,self._NNZ,
152
+ _c_pointer(self._ROW_START),
153
+ _c_pointer(self._ROW_END),
154
+ _c_pointer(self._COL_IDS),
155
+ _c_pointer(self._VAL),
156
+ int(INT32),
157
+ int(self.VTYPE),
158
+ int(self.MTYPE),
159
+ int(self.MVIEW),
160
+ int(INDEX_BASE),
161
+ )
162
+
163
+ self.b_cobj = cudss.matrix_create_dn(self.N, 1, self.N, _c_pointer(self.b_cu),
164
+ int(self.VTYPE), int(cudss.Layout.COL_MAJOR))
165
+ self.x_cobj = cudss.matrix_create_dn(self.N, 1, self.N, _c_pointer(self.x_cu),
166
+ int(self.VTYPE), int(cudss.Layout.COL_MAJOR))
167
+
168
+ def from_symbolic(self, A: csr_matrix, b: np.ndarray) -> np.ndarray:
169
+ """Solves Ax=b starting from the symbolic factorization
170
+
171
+ Args:
172
+ A (csr_matrix): The input sparse matrix
173
+ b (np.ndarray): The solution vector b
174
+
175
+ Returns:
176
+ np.ndarray: The solved vector
177
+ """
178
+ self.submit_matrix(A)
179
+ self.submit_vector(b)
180
+ self.create_solvec()
181
+ self._create_dss_data()
182
+ self._symbolic()
183
+ self._numeric(False)
184
+ return self._solve()
185
+
186
+ def from_numeric(self, A: csr_matrix, b: np.ndarray) -> np.ndarray:
187
+ """Solves Ax=b starting from the Numeric factorization
188
+
189
+ Args:
190
+ A (csr_matrix): The input sparse matrix
191
+ b (np.ndarray): The solution vector b
192
+
193
+ Returns:
194
+ np.ndarray: The solved vector
195
+ """
196
+ self.submit_matrix(A)
197
+ self.submit_vector(b)
198
+ self.create_solvec()
199
+ self._update_dss_data()
200
+ self._numeric(True)
201
+ return self._solve()
202
+
203
+ def from_solve(self, b: np.ndarray) -> np.ndarray:
204
+ """Solves Ax=b only with a new b vector.
205
+
206
+ Args:
207
+ A (csr_matrix): The input sparse matrix
208
+ b (np.ndarray): The solution vector b
209
+
210
+ Returns:
211
+ np.ndarray: The solved vector
212
+ """
213
+ self.submit_vector(b)
214
+ self.create_solvec()
215
+ return self._solve()
216
+
217
+ def _symbolic(self):
218
+ logger.trace('Executing symbolic factorization')
219
+ cudss.execute(self._handle, cudss.Phase.ANALYSIS, self._config, self._data,
220
+ self.A_cobj, self.x_cobj, self.b_cobj)
221
+
222
+ def _numeric(self, refactorize: bool = False):
223
+ if refactorize:
224
+ logger.trace('Refactoring matrix')
225
+ phase = cudss.Phase.REFACTORIZATION
226
+ else:
227
+ phase = cudss.Phase.FACTORIZATION
228
+ logger.trace('Executing numerical factorization')
229
+ cudss.execute(self._handle, phase, self._config, self._data,
230
+ self.A_cobj, self.x_cobj, self.b_cobj)
231
+
232
+ def _solve(self) -> np.ndarray:
233
+ logger.trace('Solving matrix problem')
234
+ cudss.execute(self._handle, cudss.Phase.SOLVE, self._config, self._data,
235
+ self.A_cobj, self.x_cobj, self.b_cobj)
236
+ cp.cuda.runtime.deviceSynchronize()
237
+ x_host = cp.asnumpy(self.x_cu).ravel()
238
+ return x_host