setupEM 0.6.1__tar.gz → 0.6.4__tar.gz
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.
- {setupem-0.6.1 → setupem-0.6.4}/PKG-INFO +16 -3
- {setupem-0.6.1 → setupem-0.6.4}/README.md +10 -0
- setupem-0.6.1/src/setupEM.egg-info/PKG-INFO → setupem-0.6.4/README_pypi.md +13 -21
- {setupem-0.6.1 → setupem-0.6.4}/pyproject.toml +2 -1
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/__init__.py +1 -1
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/palace_results.py +7 -2
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/setupEM.py +88 -16
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/setupThermal.py +36 -6
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/setup_common.py +591 -291
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/stackupEditor.py +112 -14
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/thermal_results.py +16 -0
- setupem-0.6.1/README_pypi.md → setupem-0.6.4/src/setupEM.egg-info/PKG-INFO +34 -1
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM.egg-info/requires.txt +2 -1
- {setupem-0.6.1 → setupem-0.6.4}/LICENSE +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/setup.cfg +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/__main__.py +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/data/SG13G2_100um.xml +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/data/SG13G2_200um.xml +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/data/SG13G2_200um_with_parameters.xml +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/data/SG13G2_nosub.xml +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/momentum_import.py +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/result_viewer.py +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM/stackup_writer.py +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM.egg-info/SOURCES.txt +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM.egg-info/dependency_links.txt +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM.egg-info/entry_points.txt +0 -0
- {setupem-0.6.1 → setupem-0.6.4}/src/setupEM.egg-info/top_level.txt +0 -0
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: setupEM
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.4
|
|
4
4
|
Summary: Python tool for configuration of gds2palace workflow with GUI.
|
|
5
5
|
Author-email: Volker Muehlhaus <volker@muehlhaus.com>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
7
7
|
Requires-Python: >=3.9
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
License-File: LICENSE
|
|
10
|
-
Requires-Dist: gds2palace>=0.4.
|
|
10
|
+
Requires-Dist: gds2palace>=0.4.3
|
|
11
11
|
Requires-Dist: PySide6
|
|
12
|
+
Requires-Dist: shiboken6
|
|
12
13
|
Requires-Dist: scipy
|
|
13
14
|
Requires-Dist: requests
|
|
14
15
|
Requires-Dist: scikit-rf
|
|
@@ -28,6 +29,7 @@ setupEM includes two built-in tools for working with simulation results directly
|
|
|
28
29
|
- **Model Fit** (Create Model tab > Model Fit...) launches [snp2le](https://github.com/iic-jku/snp2le), an external open-source tool that extracts a lumped-element SPICE/Spectre netlist from S-parameter results - offering to install it via pip if it isn't already present. See section "[Model Fit](#model-fit)".
|
|
29
30
|
|
|
30
31
|
- A graphical **Stackup XML Editor** (Tools > Edit Stackup XML...), including Variables, Reference-relative positioning, Derived Layers, and Thermal Tables
|
|
32
|
+
- The stackup preview graphics are **interactive**: click a shape for its properties, and selection syncs both ways with the Stackup Editor's tables
|
|
31
33
|
- Input Files tab can now **override stackup Variables** (e.g. `total_thickness`) directly, without hand-editing the XML or the generated model
|
|
32
34
|
- **setupThermal**, a companion app for Elmer thermal simulation, alongside setupEM
|
|
33
35
|
|
|
@@ -43,6 +45,11 @@ The setupEM package now includes setupThermal also, which is the equivalent of s
|
|
|
43
45
|
|
|
44
46
|
An overview of the SetupEM user interface is given below in chapter "Using setupEM"
|
|
45
47
|
|
|
48
|
+
Two more external tools are used by parts of the workflow, and are not installed automatically:
|
|
49
|
+
|
|
50
|
+
- [ParaView](https://www.paraview.org/) — to view field-dump output (Palace/Elmer EM) and Elmer thermal result files via the "View fields/results in Paraview" buttons.
|
|
51
|
+
- An MPI implementation — only needed for multi-process Elmer runs (the Elmer solver settings' multithreading option). Use OpenMPI or MPICH on Linux/macOS; on Windows, install [Microsoft MPI](https://learn.microsoft.com/en-us/message-passing-interface/microsoft-mpi) (setupEM checks for this and shows a download link if it's missing).
|
|
52
|
+
|
|
46
53
|
|
|
47
54
|
## Installing the AWS Palace FEM solver engine
|
|
48
55
|
**setupEM** creates and runs simulation models for the AWS Palace FEM solver engine. The underlying solver **AWS Palace** can be installed in multiple ways. For a smooth interaction with the gds2palace workflow, it is recommended to create some scripts that help running the model and convert the Palace results to SnP Touchstone files.
|
|
@@ -102,10 +109,14 @@ sudo apt install libxcb-cursor0 libxcb-xinerama0 libxcb-xkb1 libxcb-icccm4 libxc
|
|
|
102
109
|
The setupEM module also installs these dependencies:
|
|
103
110
|
- gds2palace
|
|
104
111
|
- PySide6
|
|
112
|
+
- shiboken6
|
|
105
113
|
- scipy
|
|
106
114
|
- requests
|
|
107
115
|
- scikit-rf
|
|
108
116
|
- matplotlib
|
|
117
|
+
- numpy
|
|
118
|
+
- gdspy
|
|
119
|
+
- meshio
|
|
109
120
|
|
|
110
121
|
---
|
|
111
122
|
|
|
@@ -322,13 +333,15 @@ This project is licensed under the GNU General Public License v3.0 or later (GPL
|
|
|
322
333
|
|
|
323
334
|
**Note:** the `setupEM` PyPI package itself requires:
|
|
324
335
|
|
|
325
|
-
- gds2palace>=0.4.
|
|
336
|
+
- gds2palace>=0.4.3
|
|
326
337
|
- PySide6
|
|
338
|
+
- shiboken6
|
|
327
339
|
- scipy
|
|
328
340
|
- requests
|
|
329
341
|
- scikit-rf
|
|
330
342
|
- matplotlib
|
|
331
343
|
- numpy
|
|
332
344
|
- gdspy
|
|
345
|
+
- meshio
|
|
333
346
|
|
|
334
347
|
(Other Python modules mentioned above are only needed to run standalone helper scripts in this repository, not to use the installed package.)
|
|
@@ -8,6 +8,7 @@ setupEM includes two built-in tools for working with simulation results directly
|
|
|
8
8
|
- **Model Fit** (Create Model tab > Model Fit...) launches [snp2le](https://github.com/iic-jku/snp2le), an external open-source tool that extracts a lumped-element SPICE/Spectre netlist from S-parameter results - offering to install it via pip if it isn't already present. See section "[Model Fit](#model-fit)".
|
|
9
9
|
|
|
10
10
|
- A graphical **Stackup XML Editor** (Tools > Edit Stackup XML...), including Variables, Reference-relative positioning, Derived Layers, and Thermal Tables
|
|
11
|
+
- The stackup preview graphics are **interactive**: click a shape for its properties, and selection syncs both ways with the Stackup Editor's tables
|
|
11
12
|
- Input Files tab can now **override stackup Variables** (e.g. `total_thickness`) directly, without hand-editing the XML or the generated model
|
|
12
13
|
- **setupThermal**, a companion app for Elmer thermal simulation, alongside setupEM
|
|
13
14
|
|
|
@@ -23,6 +24,11 @@ The setupEM package now includes setupThermal also, which is the equivalent of s
|
|
|
23
24
|
|
|
24
25
|
An overview of the SetupEM user interface is given below in chapter "Using setupEM"
|
|
25
26
|
|
|
27
|
+
Two more external tools are used by parts of the workflow, and are not installed automatically:
|
|
28
|
+
|
|
29
|
+
- [ParaView](https://www.paraview.org/) — to view field-dump output (Palace/Elmer EM) and Elmer thermal result files via the "View fields/results in Paraview" buttons.
|
|
30
|
+
- An MPI implementation — only needed for multi-process Elmer runs (the Elmer solver settings' multithreading option). Use OpenMPI or MPICH on Linux/macOS; on Windows, install [Microsoft MPI](https://learn.microsoft.com/en-us/message-passing-interface/microsoft-mpi) (setupEM checks for this and shows a download link if it's missing).
|
|
31
|
+
|
|
26
32
|
|
|
27
33
|
## Installing the AWS Palace FEM solver engine
|
|
28
34
|
**setupEM** creates and runs simulation models for the AWS Palace FEM solver engine. The underlying solver **AWS Palace** can be installed in multiple ways. For a smooth interaction with the gds2palace workflow, it is recommended to create some scripts that help running the model and convert the Palace results to SnP Touchstone files.
|
|
@@ -82,10 +88,14 @@ sudo apt install libxcb-cursor0 libxcb-xinerama0 libxcb-xkb1 libxcb-icccm4 libxc
|
|
|
82
88
|
The setupEM module also installs these dependencies:
|
|
83
89
|
- gds2palace
|
|
84
90
|
- PySide6
|
|
91
|
+
- shiboken6
|
|
85
92
|
- scipy
|
|
86
93
|
- requests
|
|
87
94
|
- scikit-rf
|
|
88
95
|
- matplotlib
|
|
96
|
+
- numpy
|
|
97
|
+
- gdspy
|
|
98
|
+
- meshio
|
|
89
99
|
|
|
90
100
|
---
|
|
91
101
|
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: setupEM
|
|
3
|
-
Version: 0.6.1
|
|
4
|
-
Summary: Python tool for configuration of gds2palace workflow with GUI.
|
|
5
|
-
Author-email: Volker Muehlhaus <volker@muehlhaus.com>
|
|
6
|
-
License-Expression: GPL-3.0-or-later
|
|
7
|
-
Requires-Python: >=3.9
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
License-File: LICENSE
|
|
10
|
-
Requires-Dist: gds2palace>=0.4.0
|
|
11
|
-
Requires-Dist: PySide6
|
|
12
|
-
Requires-Dist: scipy
|
|
13
|
-
Requires-Dist: requests
|
|
14
|
-
Requires-Dist: scikit-rf
|
|
15
|
-
Requires-Dist: matplotlib
|
|
16
|
-
Requires-Dist: numpy
|
|
17
|
-
Requires-Dist: gdspy
|
|
18
|
-
Requires-Dist: meshio
|
|
19
|
-
Dynamic: license-file
|
|
20
|
-
|
|
21
1
|
# Python GUI for gds2palace
|
|
22
2
|
|
|
23
3
|
## What's New
|
|
@@ -28,6 +8,7 @@ setupEM includes two built-in tools for working with simulation results directly
|
|
|
28
8
|
- **Model Fit** (Create Model tab > Model Fit...) launches [snp2le](https://github.com/iic-jku/snp2le), an external open-source tool that extracts a lumped-element SPICE/Spectre netlist from S-parameter results - offering to install it via pip if it isn't already present. See section "[Model Fit](#model-fit)".
|
|
29
9
|
|
|
30
10
|
- A graphical **Stackup XML Editor** (Tools > Edit Stackup XML...), including Variables, Reference-relative positioning, Derived Layers, and Thermal Tables
|
|
11
|
+
- The stackup preview graphics are **interactive**: click a shape for its properties, and selection syncs both ways with the Stackup Editor's tables
|
|
31
12
|
- Input Files tab can now **override stackup Variables** (e.g. `total_thickness`) directly, without hand-editing the XML or the generated model
|
|
32
13
|
- **setupThermal**, a companion app for Elmer thermal simulation, alongside setupEM
|
|
33
14
|
|
|
@@ -43,6 +24,11 @@ The setupEM package now includes setupThermal also, which is the equivalent of s
|
|
|
43
24
|
|
|
44
25
|
An overview of the SetupEM user interface is given below in chapter "Using setupEM"
|
|
45
26
|
|
|
27
|
+
Two more external tools are used by parts of the workflow, and are not installed automatically:
|
|
28
|
+
|
|
29
|
+
- [ParaView](https://www.paraview.org/) — to view field-dump output (Palace/Elmer EM) and Elmer thermal result files via the "View fields/results in Paraview" buttons.
|
|
30
|
+
- An MPI implementation — only needed for multi-process Elmer runs (the Elmer solver settings' multithreading option). Use OpenMPI or MPICH on Linux/macOS; on Windows, install [Microsoft MPI](https://learn.microsoft.com/en-us/message-passing-interface/microsoft-mpi) (setupEM checks for this and shows a download link if it's missing).
|
|
31
|
+
|
|
46
32
|
|
|
47
33
|
## Installing the AWS Palace FEM solver engine
|
|
48
34
|
**setupEM** creates and runs simulation models for the AWS Palace FEM solver engine. The underlying solver **AWS Palace** can be installed in multiple ways. For a smooth interaction with the gds2palace workflow, it is recommended to create some scripts that help running the model and convert the Palace results to SnP Touchstone files.
|
|
@@ -102,10 +88,14 @@ sudo apt install libxcb-cursor0 libxcb-xinerama0 libxcb-xkb1 libxcb-icccm4 libxc
|
|
|
102
88
|
The setupEM module also installs these dependencies:
|
|
103
89
|
- gds2palace
|
|
104
90
|
- PySide6
|
|
91
|
+
- shiboken6
|
|
105
92
|
- scipy
|
|
106
93
|
- requests
|
|
107
94
|
- scikit-rf
|
|
108
95
|
- matplotlib
|
|
96
|
+
- numpy
|
|
97
|
+
- gdspy
|
|
98
|
+
- meshio
|
|
109
99
|
|
|
110
100
|
---
|
|
111
101
|
|
|
@@ -322,13 +312,15 @@ This project is licensed under the GNU General Public License v3.0 or later (GPL
|
|
|
322
312
|
|
|
323
313
|
**Note:** the `setupEM` PyPI package itself requires:
|
|
324
314
|
|
|
325
|
-
- gds2palace>=0.4.
|
|
315
|
+
- gds2palace>=0.4.3
|
|
326
316
|
- PySide6
|
|
317
|
+
- shiboken6
|
|
327
318
|
- scipy
|
|
328
319
|
- requests
|
|
329
320
|
- scikit-rf
|
|
330
321
|
- matplotlib
|
|
331
322
|
- numpy
|
|
332
323
|
- gdspy
|
|
324
|
+
- meshio
|
|
333
325
|
|
|
334
326
|
(Other Python modules mentioned above are only needed to run standalone helper scripts in this repository, not to use the installed package.)
|
|
@@ -53,8 +53,10 @@ def find_paraview_files(run_path, model_basename):
|
|
|
53
53
|
recursively. Palace's own field-dump feature (triggered by fdump/SaveStep) writes
|
|
54
54
|
its category/excitation folder structure without gds2palace's control - confirmed
|
|
55
55
|
(on two Palace versions) to only keep the last-solved excitation's Cycle files, so
|
|
56
|
-
no fixed filename or count can be assumed here.
|
|
57
|
-
|
|
56
|
+
no fixed filename or count can be assumed here. Prefers .pvd, then falls back to
|
|
57
|
+
.pvtu (the multi-partition index - ties per-partition pieces back into one dataset),
|
|
58
|
+
then loose .vtu if neither exists yet. Empty list if the output directory doesn't
|
|
59
|
+
exist / has nothing yet.
|
|
58
60
|
"""
|
|
59
61
|
output_dir = find_output_dir(run_path, model_basename)
|
|
60
62
|
if not os.path.isdir(output_dir):
|
|
@@ -62,6 +64,9 @@ def find_paraview_files(run_path, model_basename):
|
|
|
62
64
|
pvd_files = sorted(glob.glob(os.path.join(output_dir, '**', '*.pvd'), recursive=True))
|
|
63
65
|
if pvd_files:
|
|
64
66
|
return pvd_files
|
|
67
|
+
pvtu_files = sorted(glob.glob(os.path.join(output_dir, '**', '*.pvtu'), recursive=True))
|
|
68
|
+
if pvtu_files:
|
|
69
|
+
return pvtu_files
|
|
65
70
|
return sorted(glob.glob(os.path.join(output_dir, '**', '*.vtu'), recursive=True))
|
|
66
71
|
|
|
67
72
|
|
|
@@ -165,10 +165,21 @@ class FrequenciesTab(QWidget):
|
|
|
165
165
|
self.dump_layout = QHBoxLayout()
|
|
166
166
|
|
|
167
167
|
self.fdump_layout = QVBoxLayout()
|
|
168
|
-
self.
|
|
168
|
+
self.fdump_label = QLabel("fdump [GHz], values separated by comma")
|
|
169
|
+
self.fdump_layout.addWidget(self.fdump_label)
|
|
169
170
|
self.fdump_edit = QLineEdit("")
|
|
170
171
|
self.fdump_edit.setStyleSheet(EDIT_STYLE_OPTIONAL)
|
|
171
172
|
self.fdump_layout.addWidget(self.fdump_edit)
|
|
173
|
+
|
|
174
|
+
# Elmer has no per-sample SaveStep like Palace - any fdump value turns on
|
|
175
|
+
# field-dump output at every solved frequency (sweep + fpoint together), so a
|
|
176
|
+
# per-frequency list is misleading there. Elmer mode shows this checkbox instead
|
|
177
|
+
# of fdump_edit; only one of the two is ever visible, toggled in setPalaceMode()/
|
|
178
|
+
# setElmerMode(). Both widgets always exist so mode switches are just a visibility
|
|
179
|
+
# flip, no rebuilding.
|
|
180
|
+
self.fdump_enabled_checkbox = QCheckBox("Enable field dump at all frequencies")
|
|
181
|
+
self.fdump_layout.addWidget(self.fdump_enabled_checkbox)
|
|
182
|
+
|
|
172
183
|
self.dump_layout.addLayout(self.fdump_layout)
|
|
173
184
|
self.dump_group.setLayout(self.dump_layout)
|
|
174
185
|
|
|
@@ -184,7 +195,9 @@ class FrequenciesTab(QWidget):
|
|
|
184
195
|
def save_values(self):
|
|
185
196
|
# fstart/fstop may be left empty only if fpoint or fdump supplies at least
|
|
186
197
|
# one frequency instead (gds2palace treats fstart/fstop as fully optional)
|
|
187
|
-
|
|
198
|
+
fdump_given = (self.fdump_enabled_checkbox.isChecked() if self.MainWindow.ElmerMode
|
|
199
|
+
else self.fdump_edit.text() != "")
|
|
200
|
+
discrete_freqs_given = (self.fpoint_edit.text() != "" or fdump_given)
|
|
188
201
|
|
|
189
202
|
fstart = None
|
|
190
203
|
if self.start_edit.text() == "":
|
|
@@ -239,18 +252,35 @@ class FrequenciesTab(QWidget):
|
|
|
239
252
|
else:
|
|
240
253
|
saved_values.pop("fpoint",None) # delete key
|
|
241
254
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
saved_values
|
|
255
|
+
if self.MainWindow.ElmerMode:
|
|
256
|
+
saved_values["fdump_enabled"] = self.fdump_enabled_checkbox.isChecked()
|
|
257
|
+
# don't touch saved_values["fdump"] here - it's Palace-only data (a real
|
|
258
|
+
# frequency list) and must survive a round-trip through Elmer mode untouched
|
|
259
|
+
have_sweep = ("fstart" in saved_values and "fstop" in saved_values)
|
|
260
|
+
have_fpoint = bool(saved_values.get("fpoint"))
|
|
261
|
+
if self.fdump_enabled_checkbox.isChecked() and not have_sweep and not have_fpoint:
|
|
262
|
+
QMessageBox.warning(self, "Error",
|
|
263
|
+
"Field dump needs at least one frequency: set fstart/fstop or fpoint first.")
|
|
264
|
+
self.fdump_enabled_checkbox.setChecked(False)
|
|
265
|
+
saved_values["fdump_enabled"] = False
|
|
266
|
+
return False
|
|
245
267
|
else:
|
|
246
|
-
|
|
268
|
+
text = self.fdump_edit.text()
|
|
269
|
+
if text != "":
|
|
270
|
+
saved_values ["fdump"] = ast.literal_eval('['+text+']')
|
|
271
|
+
else:
|
|
272
|
+
saved_values.pop("fdump",None)
|
|
273
|
+
# don't touch saved_values["fdump_enabled"] here either, same reasoning
|
|
247
274
|
# "View fields in Paraview" is only relevant once fdump is set
|
|
248
275
|
self.MainWindow.create_model_tab._update_paraview_button_visibility()
|
|
249
276
|
|
|
250
277
|
# if fstart == fstop == fdump or fstart == fstop == fstep, then remove fstart, fstop
|
|
251
278
|
if fstart is not None and fstop is not None and fstart == fstop:
|
|
252
279
|
discrete_list1 = saved_values.get("fpoint", [])
|
|
253
|
-
|
|
280
|
+
# fdump no longer holds real per-frequency data in Elmer mode, and collapsing
|
|
281
|
+
# the sweep away here would remove the very fstop value the field-dump
|
|
282
|
+
# checkbox's generated code depends on (see ModelEditorTab.create_model_text)
|
|
283
|
+
discrete_list2 = [] if self.MainWindow.ElmerMode else saved_values.get("fdump", [])
|
|
254
284
|
if fstart in discrete_list1 or fstart in discrete_list2:
|
|
255
285
|
saved_values.pop("fstart", None)
|
|
256
286
|
saved_values.pop("fstop", None)
|
|
@@ -265,7 +295,9 @@ class FrequenciesTab(QWidget):
|
|
|
265
295
|
def load_values(self):
|
|
266
296
|
# if fstart/fstop were intentionally omitted in favor of fpoint/fdump, keep the
|
|
267
297
|
# fields blank on reload instead of repopulating the "0"/"50" sweep defaults
|
|
268
|
-
|
|
298
|
+
fdump_given = saved_values.get("fdump_enabled", False) if self.MainWindow.ElmerMode \
|
|
299
|
+
else ("fdump" in saved_values)
|
|
300
|
+
discrete_freqs_given = ("fpoint" in saved_values) or fdump_given
|
|
269
301
|
fstart_default = "" if discrete_freqs_given else "0"
|
|
270
302
|
fstop_default = "" if discrete_freqs_given else "50"
|
|
271
303
|
self.start_edit.setText(str(saved_values.get("fstart",fstart_default)))
|
|
@@ -277,6 +309,7 @@ class FrequenciesTab(QWidget):
|
|
|
277
309
|
|
|
278
310
|
float_list = saved_values.get("fdump","")
|
|
279
311
|
self.fdump_edit.setText(','.join(map(str, float_list)))
|
|
312
|
+
self.fdump_enabled_checkbox.setChecked(bool(saved_values.get("fdump_enabled", False)))
|
|
280
313
|
|
|
281
314
|
|
|
282
315
|
class PortsTab(QWidget):
|
|
@@ -1386,7 +1419,11 @@ class CreateModelTab(CreateModelTabBase):
|
|
|
1386
1419
|
self.log_area.appendPlainText("\n" + summary + "\n")
|
|
1387
1420
|
|
|
1388
1421
|
def _update_paraview_button_visibility(self):
|
|
1389
|
-
self.
|
|
1422
|
+
if self.MainWindow.ElmerMode:
|
|
1423
|
+
visible = bool(saved_values.get('fdump_enabled'))
|
|
1424
|
+
else:
|
|
1425
|
+
visible = bool(saved_values.get('fdump'))
|
|
1426
|
+
self.paraview_btn.setVisible(visible)
|
|
1390
1427
|
|
|
1391
1428
|
def load_values(self):
|
|
1392
1429
|
super().load_values()
|
|
@@ -1409,7 +1446,7 @@ class CreateModelTab(CreateModelTabBase):
|
|
|
1409
1446
|
# found for thermal_results.vtu). Check run_path too, defensively.
|
|
1410
1447
|
search_dirs = [os.path.join(run_path, "mesh"), run_path]
|
|
1411
1448
|
file_paths = []
|
|
1412
|
-
for pattern in ("fields*.pvd", "fields*.vtu"):
|
|
1449
|
+
for pattern in ("fields*.pvd", "fields*.pvtu", "fields*.vtu"):
|
|
1413
1450
|
for d in search_dirs:
|
|
1414
1451
|
file_paths = sorted(glob.glob(os.path.join(d, pattern)))
|
|
1415
1452
|
if file_paths:
|
|
@@ -1418,7 +1455,7 @@ class CreateModelTab(CreateModelTabBase):
|
|
|
1418
1455
|
break
|
|
1419
1456
|
not_found = (
|
|
1420
1457
|
f"⚠️ No Elmer field-dump output found under {run_path}\n"
|
|
1421
|
-
"(
|
|
1458
|
+
"(enable field dump before running the simulation)\n"
|
|
1422
1459
|
)
|
|
1423
1460
|
self._open_in_paraview(file_paths, not_found)
|
|
1424
1461
|
|
|
@@ -1731,13 +1768,22 @@ class ModelEditorTab(QWidget):
|
|
|
1731
1768
|
special_keylist = ['simulation_ports','materials_list','dielectrics_list','metals_list',
|
|
1732
1769
|
'layernumbers','allpolygons']
|
|
1733
1770
|
# List of keys that we don't write to Python model code editor
|
|
1734
|
-
|
|
1771
|
+
# fdump_enabled is a GUI-only toggle (Elmer mode), never a real gds2palace setting
|
|
1772
|
+
ignore_list = ['model_basename','sim_path','fdump_enabled']
|
|
1735
1773
|
|
|
1736
1774
|
|
|
1737
1775
|
# Keywords that are excluded in Palace mode
|
|
1738
1776
|
if self.MainWindow.PalaceMode:
|
|
1739
1777
|
ignore_list.append('iterative')
|
|
1740
1778
|
|
|
1779
|
+
if self.MainWindow.ElmerMode:
|
|
1780
|
+
# Elmer mode shows a plain on/off checkbox (fdump_enabled) instead of Palace's
|
|
1781
|
+
# per-frequency fdump list - suppress the generic per-key emission of fdump
|
|
1782
|
+
# here so a stale Palace-mode list saved earlier in the same session doesn't
|
|
1783
|
+
# leak into an Elmer-mode script; the synthesized settings['fdump'] line
|
|
1784
|
+
# (below, after special_keylist) is emitted instead when the checkbox is on.
|
|
1785
|
+
ignore_list.append('fdump')
|
|
1786
|
+
|
|
1741
1787
|
if forExport:
|
|
1742
1788
|
# these commands are only used within this GUI application to control gmsh
|
|
1743
1789
|
ignore_list.extend(['preview_only','no_preview'])
|
|
@@ -1747,6 +1793,23 @@ class ModelEditorTab(QWidget):
|
|
|
1747
1793
|
if not key in ignore_list:
|
|
1748
1794
|
add_key(key)
|
|
1749
1795
|
|
|
1796
|
+
if self.MainWindow.ElmerMode and bool(saved_values.get('fdump_enabled')):
|
|
1797
|
+
# Elmer has no per-frequency SaveStep like Palace - it dumps fields at every
|
|
1798
|
+
# solved frequency once any fdump value is set, so reuse an already-solved
|
|
1799
|
+
# frequency here rather than asking the user to pick one. This is harmless
|
|
1800
|
+
# (adds no extra solve) as long as util_elmer.write_elmer_frequencies()
|
|
1801
|
+
# dedupes the combined frequency list, which it does.
|
|
1802
|
+
# Known limitation: this line's RHS references "settings", so
|
|
1803
|
+
# parse_assignments() (setup_common.py) skips it entirely on Import -
|
|
1804
|
+
# re-importing an exported Elmer+fdump script loses fdump_enabled (loads
|
|
1805
|
+
# unchecked). Not fixed here since it's a silent no-op, not a crash.
|
|
1806
|
+
add_text("\n# 'Enable field dump' checkbox: Elmer dumps fields at every solved")
|
|
1807
|
+
add_text("# frequency once fdump is non-empty, so reuse an already-solved one")
|
|
1808
|
+
if 'fstop' in saved_values:
|
|
1809
|
+
add_text("settings['fdump'] = [settings['fstop']]")
|
|
1810
|
+
elif saved_values.get('fpoint'):
|
|
1811
|
+
add_text("settings['fdump'] = [settings['fpoint'][0]]")
|
|
1812
|
+
|
|
1750
1813
|
|
|
1751
1814
|
add_text("\n# ===================== port definitions =======================")
|
|
1752
1815
|
add_text("simulation_ports = simulation_setup.all_simulation_ports()")
|
|
@@ -1951,6 +2014,10 @@ class MainWindow(MainWindowBase):
|
|
|
1951
2014
|
self.ElmerMode = False
|
|
1952
2015
|
self.setWindowTitle(APP_NAME + ' Palace')
|
|
1953
2016
|
self.frequencies_tab.dump_group.setVisible(True)
|
|
2017
|
+
self.frequencies_tab.dump_group.setTitle("Optional list of fixed frequencies creating field dump data for visualization (Paraview files))")
|
|
2018
|
+
self.frequencies_tab.fdump_label.setVisible(True)
|
|
2019
|
+
self.frequencies_tab.fdump_edit.setVisible(True)
|
|
2020
|
+
self.frequencies_tab.fdump_enabled_checkbox.setVisible(False)
|
|
1954
2021
|
self.mesh_tab.AMR_group.setVisible(True)
|
|
1955
2022
|
self.mesh_tab.Elmer_group.setVisible(False)
|
|
1956
2023
|
|
|
@@ -1963,9 +2030,14 @@ class MainWindow(MainWindowBase):
|
|
|
1963
2030
|
self.PalaceMode = False
|
|
1964
2031
|
self.ElmerMode = True
|
|
1965
2032
|
self.setWindowTitle(APP_NAME + ' Elmer')
|
|
1966
|
-
#
|
|
1967
|
-
#
|
|
2033
|
+
# Elmer has no per-sample SaveStep like Palace - any fdump value turns on
|
|
2034
|
+
# field-dump output at every solved frequency, so it shows a plain on/off
|
|
2035
|
+
# checkbox here instead of Palace's per-frequency fdump list.
|
|
1968
2036
|
self.frequencies_tab.dump_group.setVisible(True)
|
|
2037
|
+
self.frequencies_tab.dump_group.setTitle("Create field dump data for visualization (Paraview files)")
|
|
2038
|
+
self.frequencies_tab.fdump_label.setVisible(False)
|
|
2039
|
+
self.frequencies_tab.fdump_edit.setVisible(False)
|
|
2040
|
+
self.frequencies_tab.fdump_enabled_checkbox.setVisible(True)
|
|
1969
2041
|
self.mesh_tab.AMR_group.setVisible(False)
|
|
1970
2042
|
self.mesh_tab.Elmer_group.setVisible(True)
|
|
1971
2043
|
|
|
@@ -1995,8 +2067,8 @@ class MainWindow(MainWindowBase):
|
|
|
1995
2067
|
|
|
1996
2068
|
|
|
1997
2069
|
def show_version(self):
|
|
1998
|
-
setupEM_version =
|
|
1999
|
-
gds2palace_version =
|
|
2070
|
+
setupEM_version = self.get_setupEM_version()
|
|
2071
|
+
gds2palace_version = self.get_gds2palace_version()
|
|
2000
2072
|
# snp2le (used by Model Fit) is an optional dependency, not installed by default
|
|
2001
2073
|
try:
|
|
2002
2074
|
snp2le_version = importlib.metadata.version("snp2le")
|
|
@@ -53,14 +53,14 @@ if __package__ in (None, ""):
|
|
|
53
53
|
FileDropLineEdit, FileInputTab, PythonHighlighter, CodeEditor,
|
|
54
54
|
VectorWidget, PopUpWindow, CreateModelTabBase, MainWindowBase,
|
|
55
55
|
)
|
|
56
|
-
from thermal_results import build_thermal_summary, format_source_table,
|
|
56
|
+
from thermal_results import build_thermal_summary, format_source_table, find_thermal_paraview_file
|
|
57
57
|
else:
|
|
58
58
|
from .setup_common import (
|
|
59
59
|
EDIT_STYLE_OPTIONAL, EDIT_STYLE_REQUIRED, COMBO_STYLE_REQUIRED, COMBO_STYLE_OPTIONAL,
|
|
60
60
|
FileDropLineEdit, FileInputTab, PythonHighlighter, CodeEditor,
|
|
61
61
|
VectorWidget, PopUpWindow, CreateModelTabBase, MainWindowBase,
|
|
62
62
|
)
|
|
63
|
-
from .thermal_results import build_thermal_summary, format_source_table,
|
|
63
|
+
from .thermal_results import build_thermal_summary, format_source_table, find_thermal_paraview_file
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
'''
|
|
@@ -501,6 +501,28 @@ class MeshTab(QWidget):
|
|
|
501
501
|
self.main_layout.addWidget(self.mesh_group)
|
|
502
502
|
|
|
503
503
|
|
|
504
|
+
# ---------- ELMER SOLVER GROUP ----------
|
|
505
|
+
self.Elmer_group = QGroupBox("Elmer solver settings")
|
|
506
|
+
self.Elmer_layout = QVBoxLayout()
|
|
507
|
+
|
|
508
|
+
self.solver_layout = QHBoxLayout()
|
|
509
|
+
self.solverlabel = QLabel("Solver")
|
|
510
|
+
self.solverlabel.setFixedWidth(label_width)
|
|
511
|
+
self.solver_layout.addWidget(self.solverlabel)
|
|
512
|
+
|
|
513
|
+
self.solver_box = QComboBox()
|
|
514
|
+
self.solver_box.setFixedWidth(edit_width)
|
|
515
|
+
self.solver_box.setStyleSheet(COMBO_STYLE_OPTIONAL)
|
|
516
|
+
self.solver_box.addItems(["iterative","direct"])
|
|
517
|
+
self.solver_layout.addWidget(self.solver_box)
|
|
518
|
+
self.solver_box.setCurrentIndex(1)
|
|
519
|
+
self.solver_layout.addStretch()
|
|
520
|
+
self.Elmer_layout.addLayout(self.solver_layout)
|
|
521
|
+
|
|
522
|
+
self.Elmer_group.setLayout(self.Elmer_layout)
|
|
523
|
+
self.main_layout.addWidget(self.Elmer_group)
|
|
524
|
+
|
|
525
|
+
|
|
504
526
|
# ---------- BOUNDARY GROUP ----------
|
|
505
527
|
self.mesh_group = QGroupBox("Boundary settings")
|
|
506
528
|
self.mesh_layout = QVBoxLayout()
|
|
@@ -551,6 +573,9 @@ class MeshTab(QWidget):
|
|
|
551
573
|
return False
|
|
552
574
|
saved_values ["margin"] = float(value)
|
|
553
575
|
|
|
576
|
+
# iterative or direct solver for Elmer
|
|
577
|
+
saved_values["iterative"] = "iterative" in self.solver_box.currentText()
|
|
578
|
+
|
|
554
579
|
# all saved
|
|
555
580
|
return True
|
|
556
581
|
|
|
@@ -560,6 +585,11 @@ class MeshTab(QWidget):
|
|
|
560
585
|
self.cells_maxsize_edit.setText(str(saved_values.get("meshsize_max","100")))
|
|
561
586
|
self.margins_edit.setText(str(saved_values.get("margin","100")))
|
|
562
587
|
|
|
588
|
+
if saved_values.get("iterative", False):
|
|
589
|
+
self.solver_box.setCurrentIndex(0)
|
|
590
|
+
else:
|
|
591
|
+
self.solver_box.setCurrentIndex(1)
|
|
592
|
+
|
|
563
593
|
|
|
564
594
|
|
|
565
595
|
class CreateModelTab(CreateModelTabBase):
|
|
@@ -615,7 +645,7 @@ class CreateModelTab(CreateModelTabBase):
|
|
|
615
645
|
|
|
616
646
|
def launch_paraview(self):
|
|
617
647
|
run_path = saved_values['sim_path'] + "/elmer_model/" + saved_values['model_basename'] + "_data"
|
|
618
|
-
vtu_path =
|
|
648
|
+
vtu_path = find_thermal_paraview_file(run_path)
|
|
619
649
|
self._open_in_paraview(
|
|
620
650
|
[vtu_path] if vtu_path else [],
|
|
621
651
|
f"⚠️ No thermal results .vtu found yet under {run_path}\n"
|
|
@@ -786,7 +816,7 @@ class ModelEditorTab(QWidget):
|
|
|
786
816
|
special_keylist = ['thermal_objects','materials_list','dielectrics_list','metals_list',
|
|
787
817
|
'layernumbers','allpolygons']
|
|
788
818
|
# List of keys that we don't write to Python model code editor
|
|
789
|
-
ignore_list = ['model_basename','sim_path'
|
|
819
|
+
ignore_list = ['model_basename','sim_path']
|
|
790
820
|
|
|
791
821
|
|
|
792
822
|
if forExport:
|
|
@@ -935,8 +965,8 @@ class MainWindow(MainWindowBase):
|
|
|
935
965
|
# ---------- Menu actions ----------
|
|
936
966
|
|
|
937
967
|
def show_version(self):
|
|
938
|
-
setupEM_version =
|
|
939
|
-
gds2palace_version =
|
|
968
|
+
setupEM_version = self.get_setupEM_version()
|
|
969
|
+
gds2palace_version = self.get_gds2palace_version()
|
|
940
970
|
version_info = f"Installed:\nsetupEM {setupEM_version}\ngds2palace {gds2palace_version}"
|
|
941
971
|
|
|
942
972
|
# get latest available version information
|