From bb3830c4119908e50198191187363dddfb6dd20e Mon Sep 17 00:00:00 2001 From: Massimo Capodiferro <77293250+maxcapodi78@users.noreply.github.com> Date: Thu, 26 Oct 2023 13:16:47 +0200 Subject: [PATCH] Support case files (#3799) * Added support to Case Files, minore fix improvement in the plot field and in animate field with pyvista. Added support to Q3D named expression field plot. * Improved Q3D DC IR Example * Improved Q3D DC IR Example * Add UT and pragma no cover --------- Co-authored-by: maxcapodi78 Co-authored-by: Samuel Lopez <85613111+Samuelopez-ansys@users.noreply.github.com> Co-authored-by: Samuel Lopez --- _unittest/test_12_1_PostProcessing.py | 4 + examples/05-Q3D/Q3D_DC_IR.py | 54 ++++++- .../06-Multiphysics/Hfss_Icepak_Coupling.py | 4 +- pyaedt/generic/plot.py | 48 ++++--- pyaedt/modules/AdvancedPostProcessing.py | 30 +++- pyaedt/modules/PostProcessor.py | 77 ++++++++-- pyaedt/modules/solutions.py | 133 ++++++++++-------- 7 files changed, 247 insertions(+), 103 deletions(-) diff --git a/_unittest/test_12_1_PostProcessing.py b/_unittest/test_12_1_PostProcessing.py index 120b5e46be3..2349af9db82 100644 --- a/_unittest/test_12_1_PostProcessing.py +++ b/_unittest/test_12_1_PostProcessing.py @@ -556,6 +556,10 @@ def test_15_export_plot(self): show=False, export_path=os.path.join(self.local_scratch.path, "image.jpg") ) assert os.path.exists(obj.image_file) + obj2 = self.aedtapp.post.plot_model_obj( + show=False, export_path=os.path.join(self.local_scratch.path, "image2.jpg"), plot_as_separate_objects=False + ) + assert os.path.exists(obj2.image_file) @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in ironpython") def test_16_create_field_plot(self): diff --git a/examples/05-Q3D/Q3D_DC_IR.py b/examples/05-Q3D/Q3D_DC_IR.py index cabbe6c6ea3..91a05e5440b 100644 --- a/examples/05-Q3D/Q3D_DC_IR.py +++ b/examples/05-Q3D/Q3D_DC_IR.py @@ -158,11 +158,11 @@ # Use previously calculated positions to identify faces, # select the net "1_Top" and # assign sources and sinks on nets. - sink_f = q3d.modeler.create_circle(q3d.PLANE.XY, location_u11_scl, 0.1) source_f1 = q3d.modeler.create_circle(q3d.PLANE.XY, location_u9_1_scl, 0.1) source_f2 = q3d.modeler.create_circle(q3d.PLANE.XY, location_u9_2_scl, 0.1) source_f3= q3d.modeler.create_circle(q3d.PLANE.XY, location_u11_r106, 0.1) +sources_objs = [source_f1, source_f2, source_f3] q3d.auto_identify_nets() identified_net = q3d.nets[0] @@ -173,9 +173,11 @@ source2 = q3d.source(source_f2, net_name=identified_net) source3 = q3d.source(source_f3, net_name=identified_net) +sources_bounds = [source1, source2, source3] -q3d.edit_sources(dcrl={"{}:{}".format(source1.props["Net"], source1.name): "1.0A", - "{}:{}".format(source2.props["Net"], source2.name): "1.0A"}) +q3d.edit_sources(dcrl={"{}:{}".format(source1.props["Net"], source1.name): "-1.0A", + "{}:{}".format(source2.props["Net"], source2.name): "-1.0A", + "{}:{}".format(source2.props["Net"], source3.name): "-1.0A"}) ############################################################################### # Create setup @@ -191,13 +193,27 @@ setup.props["DC"]["Cond"]["MaxPass"]=3 setup.analyze() +############################################################################### +# Field Calculator +# ~~~~~~~~~~~~~~~~ +# We will create a named expression using field calculator. + +drop_name = "Vdrop3_3" +fields = q3d.ofieldsreporter +q3d.ofieldsreporter.CalcStack("clear") +q3d.ofieldsreporter.EnterQty("Phidc") +q3d.ofieldsreporter.EnterScalar(3.3) +q3d.ofieldsreporter.CalcOp("+") +q3d.ofieldsreporter.AddNamedExpression(drop_name, "DC R/L Fields") + ############################################################################### # Phi plot # ~~~~~~~~ # Compute ACL solutions and plot them. -plot1 = q3d.post.create_fieldplot_surface(q3d.modeler.get_objects_by_material("copper"), "Phidc", +plot1 = q3d.post.create_fieldplot_surface(q3d.modeler.get_objects_by_material("copper"), quantityName=drop_name, intrinsincDict={"Freq": "1GHz"}) + q3d.post.plot_field_from_fieldplot( plot1.name, project_path=q3d.working_directory, @@ -209,6 +225,36 @@ log_scale=False, ) + +############################################################################### +# Computing Voltage on Source Circles +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Using Field Calculator we can compute the voltage on source circles and get the value +# using get_solution_data method. + +curves = [] +for source_circle, source_bound in zip(sources_objs, sources_bounds): + source_sheet_name = source_circle.name + + curves.append("V{}".format(source_bound.name)) + + q3d.ofieldsreporter.CalcStack("clear") + q3d.ofieldsreporter.CopyNamedExprToStack(drop_name) + q3d.ofieldsreporter.EnterSurf(source_sheet_name) + q3d.ofieldsreporter.CalcOp("Maximum") + q3d.ofieldsreporter.AddNamedExpression("V{}".format(source_bound.name), "DC R/L Fields") + + +data = q3d.post.get_solution_data( + curves, + q3d.nominal_adaptive, + variations={"Freq": "1GHz"}, + report_category="DC R/L Fields", + ) +for curve in curves: + print(data.data_real(curve)) + + ############################################################################### # Close AEDT # ~~~~~~~~~~ diff --git a/examples/06-Multiphysics/Hfss_Icepak_Coupling.py b/examples/06-Multiphysics/Hfss_Icepak_Coupling.py index 393d46ca912..658b0e6186f 100644 --- a/examples/06-Multiphysics/Hfss_Icepak_Coupling.py +++ b/examples/06-Multiphysics/Hfss_Icepak_Coupling.py @@ -287,8 +287,8 @@ log_scale=True, ) animated.gif_file = os.path.join(aedtapp.working_directory, "animate.gif") -animated.camera_position = [0, 0, 300] -animated.focal_point = [0, 0, 0] +# animated.camera_position = [0, 0, 300] +# animated.focal_point = [0, 0, 0] # Set off_screen to False to visualize the animation. # animated.off_screen = False animated.animate() diff --git a/pyaedt/generic/plot.py b/pyaedt/generic/plot.py index 0d68f27f88e..872ac5ade79 100644 --- a/pyaedt/generic/plot.py +++ b/pyaedt/generic/plot.py @@ -1320,7 +1320,12 @@ def _read_mesh_files(self, read_frames=False): obj_to_iterate.append(i) for field in obj_to_iterate: if field.path and not field._cached_polydata: - if ".aedtplt" in field.path: + if ".case" in field.path: + reader = pv.get_reader(os.path.abspath(field.path)).read() + field._cached_polydata = reader[reader.keys()[0]].extract_surface() + field.label = field._cached_polydata.point_data.active_scalars_name + + elif ".aedtplt" in field.path: vertices, faces, scalars, log1 = _parse_aedtplt(field.path) if self.convert_fields_in_db: scalars = [np.multiply(np.log10(i), self.log_multiplier) for i in scalars] @@ -1574,6 +1579,8 @@ def plot(self, export_image_path=None): cmap=field.color_map, opacity=field.opacity, show_edges=field.show_edge, + smooth_shading=True, + split_sharp_edges=True, ) self.pv.set_scale(self.x_scale, self.y_scale, self.z_scale) @@ -1587,9 +1594,9 @@ def plot(self, export_image_path=None): self.pv.show_grid(color=tuple(axes_color), grid=self.show_grid, fmt="%.2e") if self.bounding_box: self.pv.add_bounding_box(color=tuple(axes_color)) - self.pv.set_focus(self.pv.mesh.center) if not self.isometric_view: + self.pv.set_focus(self.pv.mesh.center) if isinstance(self.camera_position, (tuple, list)): self.pv.camera.position = self.camera_position self.pv.camera.focal_point = self.focal_point @@ -1695,19 +1702,7 @@ def animate(self): for m in self.fields: labels.append([m.name, "red"]) self.pv.add_legend(labels=labels, bcolor=None, face="circle", size=[0.15, 0.15]) - if not self.isometric_view: - if isinstance(self.camera_position, (tuple, list)): - self.pv.camera.position = self.camera_position - self.pv.camera.focal_point = self.focal_point - self.pv.camera.up = self.view_up - else: - self.pv.camera_position = self.camera_position - self.pv.camera.azimuth += self.azimuth_angle - self.pv.camera.roll += self.roll_angle - self.pv.camera.elevation += self.elevation_angle - else: - self.pv.isometric_view() - self.pv.zoom = self.zoom + self._animating = True if self.gif_file: @@ -1754,11 +1749,6 @@ def p_callback(): cmap=field.color_map, opacity=field.opacity, ) - # run until q is pressed - if self.pv.mesh: - self.pv.set_focus(self.pv.mesh.center) - - cpos = self.pv.show(interactive=False, auto_close=False, interactive_update=not self.off_screen) if self.range_min is not None and self.range_max is not None: mins = self.range_min @@ -1785,6 +1775,24 @@ def p_callback(): name="FieldPlot", opacity=self.frames[0].opacity, ) + # run until q is pressed + if self.pv.mesh: + self.pv.set_focus(self.pv.mesh.center) + if not self.isometric_view: + if isinstance(self.camera_position, (tuple, list)): + self.pv.camera.position = self.camera_position + self.pv.camera.focal_point = self.focal_point + self.pv.camera.up = self.view_up + else: + self.pv.camera_position = self.camera_position + self.pv.camera.azimuth += self.azimuth_angle + self.pv.camera.roll += self.roll_angle + self.pv.camera.elevation += self.elevation_angle + else: + self.pv.isometric_view() + self.pv.camera.zoom(self.zoom) + cpos = self.pv.show(interactive=False, auto_close=False, interactive_update=not self.off_screen) + start = time.time() try: self.pv.update(1, force_redraw=True) diff --git a/pyaedt/modules/AdvancedPostProcessing.py b/pyaedt/modules/AdvancedPostProcessing.py index b5373a42e15..de3dd31a747 100644 --- a/pyaedt/modules/AdvancedPostProcessing.py +++ b/pyaedt/modules/AdvancedPostProcessing.py @@ -322,6 +322,7 @@ def plot_field_from_fieldplot( show_grid=False, show_bounding=False, show_legend=True, + plot_as_separate_objects=True, ): """Export a field plot to an image file (JPG or PNG) using Python PyVista. @@ -367,6 +368,8 @@ def plot_field_from_fieldplot( Whether to display the axes bounding box or not. The default is ``False``. show_legend : bool, optional Whether to display the legend or not. The default is ``True``. + plot_as_separate_objects : bool, optional + Plot each object separately. It may require more time to export from AEDT. Returns ------- @@ -381,8 +384,12 @@ def plot_field_from_fieldplot( else: self.ofieldsreporter.UpdateQuantityFieldsPlots(plot_folder) - file_to_add = self.export_field_plot(plotname, self._app.working_directory) - model = self.get_model_plotter_geometries(generate_mesh=False, get_objects_from_aedt=plot_cad_objs) + file_to_add = self.export_field_plot(plotname, self._app.working_directory, file_format="case") + model = self.get_model_plotter_geometries( + generate_mesh=False, + get_objects_from_aedt=plot_cad_objs, + plot_as_separate_objects=plot_as_separate_objects, + ) model.show_legend = show_legend model.off_screen = not show if dark_mode: @@ -391,7 +398,10 @@ def plot_field_from_fieldplot( model.show_grid = show_grid if file_to_add: model.add_field_from_file( - file_to_add, coordinate_units=self.modeler.model_units, show_edges=meshplot, log_scale=log_scale + file_to_add, + coordinate_units=self.modeler.model_units, + show_edges=meshplot, + log_scale=log_scale, ) if plot_label: model.fields[0].label = plot_label @@ -427,7 +437,7 @@ def plot_field( scale_min=None, scale_max=None, plot_cad_objs=True, - log_scale=True, + log_scale=False, export_path="", imageformat="jpg", keep_plot_after_generation=False, @@ -436,6 +446,7 @@ def plot_field( show_grid=False, show_legend=True, filter_objects=[], + plot_as_separate_objects=True, ): """Create a field plot using Python PyVista and export to an image file (JPG or PNG). @@ -471,7 +482,7 @@ def plot_field( plot_cad_objs : bool, optional Whether to include objects in the plot. The default is ``True``. log_scale : bool, optional - Whether to plot fields in log scale. The default is ``True``. + Whether to plot fields in log scale. The default is ``False``. export_path : str, optional Image export path. Default is ``None`` to not export the image. imageformat : str, optional @@ -490,6 +501,8 @@ def plot_field( Whether to display the legend or not. The default is ``True``. filter_objects : list, optional Objects list for filtering the ``CutPlane`` plots. + plot_as_separate_objects : bool, optional + Plot each object separately. It may require more time to export from AEDT. Returns ------- @@ -534,6 +547,7 @@ def plot_field( show_grid=show_grid, show_bounding=show_bounding, show_legend=show_legend, + plot_as_separate_objects=plot_as_separate_objects, ) if not keep_plot_after_generation: plotf.delete() @@ -652,7 +666,7 @@ def plot_animated_field( object_list, quantity, setup_name, intrinsics, filter_objects=filter_objects ) if plotf: - file_to_add = self.export_field_plot(plotf.name, export_path, plotf.name + str(v)) + file_to_add = self.export_field_plot(plotf.name, export_path, plotf.name + str(v), file_format="case") if file_to_add: fields_to_add.append(file_to_add) plotf.delete() @@ -761,7 +775,9 @@ def animate_fields_from_aedtplt( ] ) fields_to_add.append( - self.export_field_plot(plotname, project_path, plotname + variation_variable + str(el)) + self.export_field_plot( + plotname, project_path, plotname + variation_variable + str(el), file_format="case" + ) ) model = self.get_model_plotter_geometries(generate_mesh=False) diff --git a/pyaedt/modules/PostProcessor.py b/pyaedt/modules/PostProcessor.py index 286207b85f1..7a79917c1ce 100644 --- a/pyaedt/modules/PostProcessor.py +++ b/pyaedt/modules/PostProcessor.py @@ -2636,7 +2636,15 @@ def export_field_plot(self, plotname, filepath, filename="", file_format="aedtpl if not filename: filename = plotname file_path = os.path.join(filepath, filename + "." + file_format) - self.ofieldsreporter.ExportFieldPlot(plotname, False, file_path) + if ".case" in file_path: + try: + self.ofieldsreporter.ExportFieldPlot(plotname, False, file_path) + except: # pragma: no cover + self.logger.warning("case file is not supported for this plot. Switching to aedtplt") + file_path = os.path.join(filepath, filename + ".aedtplt") + self.ofieldsreporter.ExportFieldPlot(plotname, False, file_path) + else: # pragma: no cover + self.ofieldsreporter.ExportFieldPlot(plotname, False, file_path) if settings.remote_rpc_session_temp_folder: local_path = os.path.join(settings.remote_rpc_session_temp_folder, filename + "." + file_format) file_path = check_and_download_file(local_path, file_path) @@ -2703,7 +2711,7 @@ def change_field_plot_scale(self, plot_name, minimum_value, maximum_value, is_lo @pyaedt_function_handler() def _create_fieldplot( - self, objlist, quantityName, setup_name, intrinsics, listtype, plot_name=None, filter_boxes=[] + self, objlist, quantityName, setup_name, intrinsics, listtype, plot_name=None, filter_boxes=[], field_type=None ): if not listtype.startswith("Layer") and self._app.design_type != "HFSS 3D Layout Design": objlist = self._app.modeler.convert_to_selections(objlist, True) @@ -2765,6 +2773,8 @@ def _create_fieldplot( intrinsincList=intrinsics, layers_plot_type=listtype, ) + if self._app.design_type == "Q3D Extractor": # pragma: no cover + plot.field_type = field_type plot.name = plot_name plot.plotFolder = plot_name plot.filter_boxes = filter_boxes @@ -2787,6 +2797,7 @@ def _create_fieldplot_line_traces( setup_name, intrinsics, plot_name=None, + field_type="", ): if not setup_name: setup_name = self._app.existing_analysis_sweeps[0] @@ -2814,6 +2825,8 @@ def _create_fieldplot_line_traces( intrinsincList=intrinsics, seedingFaces=seeding_faces_ids, ) + if field_type: + plot.field_type = field_type plot.name = plot_name plot.plotFolder = plot_name @@ -2827,7 +2840,9 @@ def _create_fieldplot_line_traces( return False @pyaedt_function_handler() - def create_fieldplot_line(self, objlist, quantityName, setup_name=None, intrinsincDict=None, plot_name=None): + def create_fieldplot_line( + self, objlist, quantityName, setup_name=None, intrinsincDict=None, plot_name=None, field_type="DC R/L Fields" + ): """Create a field plot of the line. Parameters @@ -2845,6 +2860,8 @@ def create_fieldplot_line(self, objlist, quantityName, setup_name=None, intrinsi is ``{}``. plot_name : str, optional Name of the fieldplot to create. + field_type : str, optional + Field type to plot. Valid only for Q3D Field plots. Returns ------- @@ -2861,7 +2878,9 @@ def create_fieldplot_line(self, objlist, quantityName, setup_name=None, intrinsi if plot_name and plot_name in list(self.field_plots.keys()): self.logger.info("Plot {} exists. returning the object.".format(plot_name)) return self.field_plots[plot_name] - return self._create_fieldplot(objlist, quantityName, setup_name, intrinsincDict, "Line", plot_name) + return self._create_fieldplot( + objlist, quantityName, setup_name, intrinsincDict, "Line", plot_name, field_type=field_type + ) @pyaedt_function_handler() def create_fieldplot_line_traces( @@ -2872,6 +2891,7 @@ def create_fieldplot_line_traces( setup_name=None, intrinsinc_dict=None, plot_name=None, + field_type="DC R/L Fields", ): """ Create a field plot of the line. @@ -2892,6 +2912,8 @@ def create_fieldplot_line_traces( is ``{}``. plot_name : str, optional Name of the field plot to create. The default is ``None``. + field_type : str, optional + Field type to plot. Valid only for Q3D Field plots. Returns ------- @@ -2965,6 +2987,7 @@ def create_fieldplot_line_traces( setup_name, intrinsinc_dict, plot_name, + field_type=field_type, ) @pyaedt_function_handler() @@ -3033,7 +3056,9 @@ def create_fieldplot_layers_nets( return self._create_fieldplot(layers_nets, quantity_name, setup_name, intrinsics, plot_type, plot_name) @pyaedt_function_handler() - def create_fieldplot_surface(self, objlist, quantityName, setup_name=None, intrinsincDict=None, plot_name=None): + def create_fieldplot_surface( + self, objlist, quantityName, setup_name=None, intrinsincDict=None, plot_name=None, field_type="DC R/L Fields" + ): """Create a field plot of surfaces. Parameters @@ -3051,6 +3076,8 @@ def create_fieldplot_surface(self, objlist, quantityName, setup_name=None, intri is ``{}``. plot_name : str, optional Name of the fieldplot to create. + field_type : str, optional + Field type to plot. Valid only for Q3D Field plots. Returns ------- @@ -3075,11 +3102,20 @@ def create_fieldplot_surface(self, objlist, quantityName, setup_name=None, intri new_obj_list.extend([i.id for i in self._app.modeler[objs].faces]) else: new_obj_list.append(objs) - return self._create_fieldplot(new_obj_list, quantityName, setup_name, intrinsincDict, "FacesList", plot_name) + return self._create_fieldplot( + new_obj_list, quantityName, setup_name, intrinsincDict, "FacesList", plot_name, field_type=field_type + ) @pyaedt_function_handler() def create_fieldplot_cutplane( - self, objlist, quantityName, setup_name=None, intrinsincDict=None, plot_name=None, filter_objects=[] + self, + objlist, + quantityName, + setup_name=None, + intrinsincDict=None, + plot_name=None, + filter_objects=[], + field_type="DC R/L Fields", ): """Create a field plot of cut planes. @@ -3100,6 +3136,8 @@ def create_fieldplot_cutplane( Name of the fieldplot to create. filter_objects : list, optional Objects list on which filter the plot. + field_type : str, optional + Field type to plot. Valid only for Q3D Field plots. Returns ------- @@ -3119,11 +3157,26 @@ def create_fieldplot_cutplane( if filter_objects: filter_objects = self._app.modeler.convert_to_selections(filter_objects, True) return self._create_fieldplot( - objlist, quantityName, setup_name, intrinsincDict, "CutPlane", plot_name, filter_boxes=filter_objects + objlist, + quantityName, + setup_name, + intrinsincDict, + "CutPlane", + plot_name, + filter_boxes=filter_objects, + field_type=field_type, ) @pyaedt_function_handler() - def create_fieldplot_volume(self, objlist, quantityName, setup_name=None, intrinsincDict=None, plot_name=None): + def create_fieldplot_volume( + self, + objlist, + quantityName, + setup_name=None, + intrinsincDict=None, + plot_name=None, + field_type="DC R/L Fields", + ): """Create a field plot of volumes. Parameters @@ -3157,7 +3210,9 @@ def create_fieldplot_volume(self, objlist, quantityName, setup_name=None, intrin if plot_name and plot_name in list(self.field_plots.keys()): self.logger.info("Plot {} exists. returning the object.".format(plot_name)) return self.field_plots[plot_name] - return self._create_fieldplot(objlist, quantityName, setup_name, intrinsincDict, "ObjList", plot_name) + return self._create_fieldplot( + objlist, quantityName, setup_name, intrinsincDict, "ObjList", plot_name, field_type=field_type + ) @pyaedt_function_handler() def export_field_jpg( @@ -3514,7 +3569,7 @@ def export_model_obj(self, obj_list=None, export_path=None, export_as_single_obj else: fname = os.path.join(export_path, "Model_AllObjs_AllMats.obj") self._app.modeler.oeditor.ExportModelMeshToFile(fname, obj_list) - return [[fname, "grey", 0.6]] + return [[fname, "aquamarine", 0.3]] @pyaedt_function_handler() def export_mesh_obj(self, setup_name=None, intrinsic_dict=None): diff --git a/pyaedt/modules/solutions.py b/pyaedt/modules/solutions.py index 561c5f61e69..9249f813c92 100644 --- a/pyaedt/modules/solutions.py +++ b/pyaedt/modules/solutions.py @@ -2566,6 +2566,7 @@ def __init__( self.SeedingPointsNumber = 15 self.FractionOfMaximum = 0.8 self._filter_boxes = [] + self.field_type = None @property def filter_boxes(self): @@ -2776,7 +2777,7 @@ def surfacePlotInstruction(self): List of surface plot settings. """ - return [ + out = [ "NAME:" + self.name, "SolutionName:=", self.solutionName, @@ -2784,26 +2785,33 @@ def surfacePlotInstruction(self): self.quantityName, "PlotFolder:=", self.plotFolder, - "UserSpecifyName:=", - 1, - "UserSpecifyFolder:=", - 1, - "StreamlinePlot:=", - False, - "AdjacentSidePlot:=", - False, - "FullModelPlot:=", - False, - "IntrinsicVar:=", - self.intrinsicVar, - "PlotGeomInfo:=", - self.plotGeomInfo, - "FilterBoxes:=", - [len(self.filter_boxes)] + self.filter_boxes, - self.plotsettings, - "EnableGaussianSmoothing:=", - False, ] + if self.field_type: + out.extend(["FieldType:=", self.field_type]) + out.extend( + [ + "UserSpecifyName:=", + 1, + "UserSpecifyFolder:=", + 1, + "StreamlinePlot:=", + False, + "AdjacentSidePlot:=", + False, + "FullModelPlot:=", + False, + "IntrinsicVar:=", + self.intrinsicVar, + "PlotGeomInfo:=", + self.plotGeomInfo, + "FilterBoxes:=", + [len(self.filter_boxes)] + self.filter_boxes, + self.plotsettings, + "EnableGaussianSmoothing:=", + False, + ] + ) + return out @property def surfacePlotInstructionLineTraces(self): @@ -2818,7 +2826,7 @@ def surfacePlotInstructionLineTraces(self): List of plot settings for line traces. """ - return [ + out = [ "NAME:" + self.name, "SolutionName:=", self.solutionName, @@ -2830,45 +2838,52 @@ def surfacePlotInstructionLineTraces(self): "QuantityName_FieldLineTrace", "PlotFolder:=", self.plotFolder, - "IntrinsicVar:=", - self.intrinsicVar, - "Trace Step Length:=", - self.TraceStepLength, - "Use Adaptive Step:=", - self.UseAdaptiveStep, - "Seeding Faces:=", - self.seeding_faces, - "Seeding Markers:=", - [0], - "Surface Tracing Objects:=", - self.surfaces_indexes, - "Volume Tracing Objects:=", - self.volume_indexes, - "Seeding Sampling Option:=", - self.SeedingSamplingOption, - "Seeding Points Number:=", - self.SeedingPointsNumber, - "Fractional of Maximal:=", - self.FractionOfMaximum, - "Discrete Seeds Option:=", - "Marker Point", - [ - "NAME:InceptionEvaluationSettings", - "Gas Type:=", - 0, - "Gas Pressure:=", - 1, - "Use Inception:=", - True, - "Potential U0:=", - 0, - "Potential K:=", - 0, - "Potential A:=", - 1, - ], - self.field_line_trace_plot_settings, ] + if self.field_type: + out.extend(["FieldType:=", self.field_type]) + out.extend( + [ + "IntrinsicVar:=", + self.intrinsicVar, + "Trace Step Length:=", + self.TraceStepLength, + "Use Adaptive Step:=", + self.UseAdaptiveStep, + "Seeding Faces:=", + self.seeding_faces, + "Seeding Markers:=", + [0], + "Surface Tracing Objects:=", + self.surfaces_indexes, + "Volume Tracing Objects:=", + self.volume_indexes, + "Seeding Sampling Option:=", + self.SeedingSamplingOption, + "Seeding Points Number:=", + self.SeedingPointsNumber, + "Fractional of Maximal:=", + self.FractionOfMaximum, + "Discrete Seeds Option:=", + "Marker Point", + [ + "NAME:InceptionEvaluationSettings", + "Gas Type:=", + 0, + "Gas Pressure:=", + 1, + "Use Inception:=", + True, + "Potential U0:=", + 0, + "Potential K:=", + 0, + "Potential A:=", + 1, + ], + self.field_line_trace_plot_settings, + ] + ) + return out @property def field_plot_settings(self):