From 9c728a03ccdade36b2e942909049cbf31326aee4 Mon Sep 17 00:00:00 2001 From: Markus Hovorka Date: Mon, 23 Sep 2019 21:16:37 +0200 Subject: [PATCH 01/10] FEM: Add documentation to femutils module --- src/Mod/Fem/femtools/femutils.py | 209 +++++++++++++++++++++++++++---- 1 file changed, 186 insertions(+), 23 deletions(-) diff --git a/src/Mod/Fem/femtools/femutils.py b/src/Mod/Fem/femtools/femutils.py index c1304990c0..f55afb8dc2 100644 --- a/src/Mod/Fem/femtools/femutils.py +++ b/src/Mod/Fem/femtools/femutils.py @@ -20,6 +20,13 @@ # * USA * # * * # *************************************************************************** +""" Collection of functions for the Fem module. + +This module contains function for managing a analysis and all the differnet +types of objects it contains, helper for executing a simulation, function for +extracting relevant parts of geometry and a few unrelated function useful at +various places in the Fem module. +""" __title__ = "FEM Utilities" @@ -38,8 +45,23 @@ if FreeCAD.GuiUp: from PySide import QtGui -# analysis and its members def createObject(doc, name, proxy, viewProxy): + """ Add python object to document using python type string. + + Add a document object suitable for the *proxy* and the *viewProxy* to *doc* + and attach it to the *proxy* and the *viewProxy*. This function can only be + used with python proxies that specify their C++ type via the BaseType class + member (e.g. Cube.BaseType). If there already exists a object with *name* a + suitable unique name is generated. To auto generate a name pass ``""``. + + :param doc: document object to which the object is added + :param name: string of the name of new object in *doc*, use + ``""`` to generate a name + :param proxy: python proxy for new object + :param viewProxy: view proxy for new object + + :returns: reference to new object + """ obj = doc.addObject(proxy.BaseType, name) proxy(obj) if FreeCAD.GuiUp: @@ -48,6 +70,14 @@ def createObject(doc, name, proxy, viewProxy): def findAnalysisOfMember(member): + """ Find Analysis the *member* belongs to. + + :param member: a document object + + :returns: + If a analysis that contains *member* can be found a reference is returned. + If no such object exists in the document of *member*, ``None`` is returned. + """ if member is None: raise ValueError("Member must not be None") for obj in member.Document.Objects: @@ -69,6 +99,22 @@ def _searchGroups(member, objs): def get_member(analysis, t): + """ Return list of all members of *analysis* of type *t*. + + Search *analysis* for members of type *t*. This method checks the custom + python typesytem (BaseType class property) used by the Fem module if + possible. If the object doens't use the python typesystem the usual + isDerivedFrom from the C++ dynamic type system is used. + + :param analysis: only objects part of this analysis are considered + :param t: only objects of this type are returned + + :note: + Inheritance of Fem types is not checked. If *obj* uses Fems typesystem the + type is just checked for equality. If the type doesn't match + ``obj.isDerivedFrom`` is called as usual. See + https://forum.freecadweb.org/viewtopic.php?f=10&t=32625 + """ if analysis is None: raise ValueError("Analysis must not be None") matching = [] @@ -81,12 +127,58 @@ def get_member(analysis, t): def get_single_member(analysis, t): + """ Return one object of type *t* and part of *analysis*. + + Search *analysis* for members of type *t* and return the first one that's + found. This method checks the custom python typesytem (BaseType class + property) used by the Fem module if possible. If the object doesn't use the + python typesystem the usual isDerivedFrom from the C++ dynamic type system + is used. + + :param analysis: only objects part of this analysis are considered + :param t: only a object of this type is returned + + :note: + Inheritance of Fem types is not checked. If *obj* uses Fems typesystem the + type is just checked for equality. If the type doesn't match + ``obj.isDerivedFrom`` is called as usual. See + https://forum.freecadweb.org/viewtopic.php?f=10&t=32625 + """ objs = get_member(analysis, t) return objs[0] if objs else None -# collect analysis members used in CalculiX and Z88 def get_several_member(analysis, t): + """ Get members and pack them for Calculix/Z88. + + Collect members by calling :py:func:`get_member` and pack them into a + data structure that can be consumed by calculix and Z88 solver modules. + + :param analysis: see :py:func:`get_member` + :param t: see :py:func:`get_member` + + :returns: + A list containing one dict per member. Each dict has two entries: + ``"Object"`` and ``"RefShapeType"``. ``dict["Object"]`` contains the + member document object. ``dict["RefShapeType"]`` contains the shape type + of the *References* property of the member (used by constraints) as a + string ("Vertex", "Edge", "Face" or "Solid"). If the member doesn't have a + *References* property ``dict["RefShapeType"]`` is the empty string ``""``. + + :note: + Undefined behaviour if one of the members has a *References* property + which is empty. + + :note: + Undefined behaviour if the type of the references of one object arn't all + the same. + + :note: + Inheritance of Fem types is not checked. If *obj* uses Fems typesystem the + type is just checked for equality. If the type doesn't match + ``obj.isDerivedFrom`` is called as usual. See + https://forum.freecadweb.org/viewtopic.php?f=10&t=32625 + """ # if no member is found, an empty list is returned objs = get_member(analysis, t) members = [] @@ -99,6 +191,14 @@ def get_several_member(analysis, t): def get_mesh_to_solve(analysis): + """ Find one and only mesh object of *analysis*. + + :returns: + A tuple ``(object, message)``. If and only if the analysis contains + exactely one mesh object the first value of the tuple is the mesh document + object. Otherwise the first value is ``None`` and the second value is a + error message indicating what went wrong. + """ mesh_to_solve = None for m in analysis.Group: if m.isDerivedFrom("Fem::FemMeshObject") and not is_of_type(m, "Fem::FemMeshResult"): @@ -114,27 +214,46 @@ def get_mesh_to_solve(analysis): # typeID and object type defs def type_of_obj(obj): - """returns objects TypeId (C++ objects) or Proxy.Type (Python objects)""" + """ Return type of *obj* honoring the special typesystem of Fem. + + Python objects of the Fem workbench define their type via a class member + ``.Type``. Return this type if the property exists. If not return + the conventional ``TypeId`` value. + + :para obj: a document object + """ if hasattr(obj, "Proxy") and hasattr(obj.Proxy, "Type"): return obj.Proxy.Type return obj.TypeId def is_of_type(obj, ty): - """returns True if an object is of - a given TypeId (C++ objects) or Proxy.Type (Python Features)""" - # only returns true if the exact TypeId is given. - # For FeaturPythons the Proxy.Type has to be given. - # Keep in mind the TypeId for them is the TypeId from the C++ father class + """ Compare type of *obj* with *ty* honoring Fems typesystem. + + See :py:func:`type_of_obj` for more info about the special typesystem of + the Fem module. + + :returns: + ``True`` if *obj* is of type *ty*, ``False`` otherwise. Type must match + exactely: Derived objects are not considered to be of type of one of their + super classes. + """ return type_of_obj(obj) == ty def is_derived_from(obj, t): - """returns True if an object or its inheritance chain is of a - given TypeId (C++ objects) or Proxy.Type (Python objects)""" - # returns true for all FEM objects if given t == "App::DocumentObject" - # since this is a father of the given object - # see https://forum.freecadweb.org/viewtopic.php?f=10&t=32625 + """ Check if *obj* is derived from *t* honoring Fems typesytem. + + Essentially just call ``obj.isDerivedFrom(t)`` and return it's value. For + objects using Fems typesystem (see :py:func:`type_of_obj`) return always + True if the Fem type is equal to *t*. + + :note: + Inheritance of Fem types is not checked. If *obj* uses Fems typesystem the + type is just checked for equality. If the type doesn't match + ``obj.isDerivedFrom`` is called as usual. See + https://forum.freecadweb.org/viewtopic.php?f=10&t=32625 + """ if (hasattr(obj, "Proxy") and hasattr(obj.Proxy, "Type") and obj.Proxy.Type == t): return True return obj.isDerivedFrom(t) @@ -143,8 +262,16 @@ def is_derived_from(obj, t): # ************************************************************************************************ # working dir def get_pref_working_dir(solver_obj): - # _dirTypes from run are not used - # be aware beside could get an error if the document has not been saved + """ Return working directory for solver honoring user settings. + + :throws femsolver.run.MustSaveError: + If user setting is set to BESIDE and the document isn't saved. + + :note: + Not working correctely for most cases because this circumvents directory + caching of the solver framework. For solver use getMachine from run.py + instead. + """ dir_setting = settings.get_dir_setting() if dir_setting == settings.TEMPORARY: setting_working_dir = get_temp_dir(solver_obj) @@ -255,6 +382,13 @@ def get_part_to_mesh(mesh_obj): def getBoundBoxOfAllDocumentShapes(doc): + """ Calculate bounding box containing all objects inside *doc*. + + :returns: + A bounding box containing all objects that have a *Shape* attribute (all + Part and PartDesign objects). If the document contains no such objects or + no objects at all return ``None``. + """ overalboundbox = None for o in doc.Objects: # netgen mesh obj has an attribute Shape which is an Document obj, which has no BB @@ -271,6 +405,16 @@ def getBoundBoxOfAllDocumentShapes(doc): def getSelectedFace(selectionex): + """ Return selected face if exactly one face is selected. + + :returns: + The selcted face as a ``Part::TopoShape`` if exactly one face is selected. + Otherwise return ``None``. + + :param selectionex: + A list of selection object like the one Gui.Selection.getSelectionEx() + returns. + """ aFace = None # print(selectionex) if len(selectionex) != 1: @@ -290,14 +434,27 @@ def getSelectedFace(selectionex): def get_refshape_type(fem_doc_object): - # returns the reference shape type - # for force object: - # in GUI defined frc_obj all frc_obj have at least one ref_shape - # and ref_shape have all the same shape type - # for material object: - # in GUI defined material_obj could have no RefShape and RefShapes could be different type - # we're going to need the RefShapes to be the same type inside one fem_doc_object - # TODO: check if all RefShapes inside the object really have the same type + """ Return shape type the constraints references. + + Determine single shape type of references of *fem_doc_object* which must be + a constraint (=have a *References* property). All references must be of the + same type which is than returned as a string. A type can be "Vertex", + "Edge", "Face" or "Solid". + + :param fem_doc_object: + A constraint object with a *References* property. + + :returns: + A string representing the shape type ("Vertex", "Edge", "Face" or + "Solid"). If *fem_doc_object* isn't a contraint ``""`` is returned. + + :note: + Undefined behaviour if the type of the references of one object arn't all + the same. + + :note: + Undefined behaviour if constraint contains no references (empty list). + """ import femmesh.meshtools as FemMeshTools if hasattr(fem_doc_object, "References") and fem_doc_object.References: first_ref_obj = fem_doc_object.References[0] @@ -315,6 +472,12 @@ def get_refshape_type(fem_doc_object): def pydecode(bytestring): + """ Return *bytestring* as a unicode string for python 2 and 3. + + For python 2 *bytestring* is converted to a string of type ``unicode``. For + python 3 it is returned as is because it uses unicode for it's ``str`` type + already. + """ if sys.version_info.major < 3: return bytestring else: From 708ef0cd6ae87aecf84ec094c4be3ee2a27d543f Mon Sep 17 00:00:00 2001 From: Markus Hovorka Date: Mon, 23 Sep 2019 21:16:39 +0200 Subject: [PATCH 02/10] FEM: Redirect ElmerGrid output to /dev/null Up until now the output would appear in the cli in which FreeCAD was started. This is unnecessary and makes test output very confusing. --- src/Mod/Fem/femsolver/elmer/writer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Fem/femsolver/elmer/writer.py b/src/Mod/Fem/femsolver/elmer/writer.py index cfd077f34e..469300496e 100644 --- a/src/Mod/Fem/femsolver/elmer/writer.py +++ b/src/Mod/Fem/femsolver/elmer/writer.py @@ -135,7 +135,7 @@ class Writer(object): _ELMERGRID_OFORMAT, unvPath, "-out", self.directory] - subprocess.call(args) + subprocess.call(args, stdout=subprocess.DEVNULL) def _writeStartinfo(self): path = os.path.join(self.directory, _STARTINFO_NAME) From d0b7472ab1d33ce0a48602c9b507388210d1964f Mon Sep 17 00:00:00 2001 From: Markus Hovorka Date: Mon, 23 Sep 2019 21:16:39 +0200 Subject: [PATCH 03/10] FEM: Make temp directory default for solver Previously it would return None if no setting is found (which can happen if the settings system hasn't been loaded at least once). This would make some other code fail. --- src/Mod/Fem/femsolver/settings.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Mod/Fem/femsolver/settings.py b/src/Mod/Fem/femsolver/settings.py index d6b73c5bfd..7b3621fde8 100644 --- a/src/Mod/Fem/femsolver/settings.py +++ b/src/Mod/Fem/femsolver/settings.py @@ -158,12 +158,11 @@ def get_custom_dir(): def get_dir_setting(): param_group = FreeCAD.ParamGet(_GENERAL_PARAM) - if param_group.GetBool("UseTempDirectory"): - return TEMPORARY - elif param_group.GetBool("UseBesideDirectory"): + if param_group.GetBool("UseBesideDirectory"): return BESIDE elif param_group.GetBool("UseCustomDirectory"): return CUSTOM + return TEMPORARY ## @} From f5e67238efd4c00856178fae01bfb2869cd7cc8a Mon Sep 17 00:00:00 2001 From: Markus Hovorka Date: Mon, 23 Sep 2019 21:16:43 +0200 Subject: [PATCH 04/10] FEM: Make view proxy optional on object creation --- src/Mod/Fem/femtools/femutils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Fem/femtools/femutils.py b/src/Mod/Fem/femtools/femutils.py index f55afb8dc2..c2af8d5062 100644 --- a/src/Mod/Fem/femtools/femutils.py +++ b/src/Mod/Fem/femtools/femutils.py @@ -45,7 +45,7 @@ if FreeCAD.GuiUp: from PySide import QtGui -def createObject(doc, name, proxy, viewProxy): +def createObject(doc, name, proxy, viewProxy=None): """ Add python object to document using python type string. Add a document object suitable for the *proxy* and the *viewProxy* to *doc* @@ -64,7 +64,7 @@ def createObject(doc, name, proxy, viewProxy): """ obj = doc.addObject(proxy.BaseType, name) proxy(obj) - if FreeCAD.GuiUp: + if FreeCAD.GuiUp and viewProxy is not None: viewProxy(obj.ViewObject) return obj From f96c805dbb3fb93653e13f0c606f5e64bed2cce5 Mon Sep 17 00:00:00 2001 From: Markus Hovorka Date: Mon, 23 Sep 2019 21:16:45 +0200 Subject: [PATCH 05/10] FEM: Restructure python test modules/packages There is a new split into app and gui tests. For this purpose two packages where created: femtest.app and femtest.gui. Tests that don't require the GUI up and running are inside the femtest.app package. Tests that do require the GUI are inside the femtest.gui package. Also underscores where added to the module names: testcommon to test_common. --- src/Mod/Fem/App/FemMesh.cpp | 4 +- src/Mod/Fem/CMakeLists.txt | 110 +++++++++--------- src/Mod/Fem/TestFem.py | 33 +++--- .../femtest/{testfiles => app}/__init__.py | 0 .../{utilstest.py => app/support_utils.py} | 2 +- .../{testccxtools.py => app/test_ccxtools.py} | 22 ++-- .../{testcommon.py => app/test_common.py} | 4 +- .../test_femimport.py} | 2 +- .../{testmaterial.py => app/test_material.py} | 2 +- .../femtest/{testmesh.py => app/test_mesh.py} | 4 +- .../{testobject.py => app/test_object.py} | 4 +- .../{testresult.py => app/test_result.py} | 4 +- .../test_solverframework.py} | 8 +- .../{testfiles/ccx => data}/__init__.py | 0 .../{testfiles => data}/ccx/Flow1D_mesh.py | 0 .../ccx/Flow1D_thermomech.FCStd | Bin .../ccx/Flow1D_thermomech.dat | 0 .../ccx/Flow1D_thermomech.frd | 0 .../ccx/Flow1D_thermomech.inp | 0 .../ccx/Flow1D_thermomech_expected_values | 0 .../ccx/Flow1D_thermomech_inout_nodes.txt | 0 .../{testfiles/elmer => data/ccx}/__init__.py | 0 .../{testfiles => data}/ccx/cube.FCStd | Bin .../ccx/cube_frequency.FCStd | Bin .../ccx/cube_frequency.dat | 0 .../ccx/cube_frequency.frd | 0 .../ccx/cube_frequency.inp | 0 .../ccx/cube_frequency_expected_values | 0 .../{testfiles => data}/ccx/cube_mesh.py | 0 .../{testfiles => data}/ccx/cube_static.FCStd | Bin .../{testfiles => data}/ccx/cube_static.dat | 0 .../{testfiles => data}/ccx/cube_static.frd | 0 .../{testfiles => data}/ccx/cube_static.inp | 0 .../ccx/cube_static_expected_values | 0 .../{testfiles => data}/ccx/multimat.inp | 0 .../{testfiles => data}/ccx/multimat_mesh.py | 0 .../{testfiles => data}/ccx/spine_mesh.py | 0 .../{testfiles => data}/ccx/spine_points.csv | 0 .../ccx/spine_thermomech.FCStd | Bin .../ccx/spine_thermomech.dat | 0 .../ccx/spine_thermomech.frd | 0 .../ccx/spine_thermomech.inp | 0 .../ccx/spine_thermomech_expected_values | 0 .../{testfiles => data}/ccx/spine_volumes.csv | 0 .../elmer/ELMERSOLVER_STARTINFO | 0 .../mesh => data/elmer}/__init__.py | 0 .../{testfiles => data}/elmer/case.sif | 0 .../{testfiles => data}/elmer/group_mesh.geo | 0 src/Mod/Fem/femtest/data/mesh/__init__.py | 0 .../{testfiles => data}/mesh/tetra10_mesh.inp | 0 .../{testfiles => data}/mesh/tetra10_mesh.unv | 0 .../{testfiles => data}/mesh/tetra10_mesh.vtk | 0 .../{testfiles => data}/mesh/tetra10_mesh.yml | 0 .../{testfiles => data}/mesh/tetra10_mesh.z88 | 0 54 files changed, 102 insertions(+), 97 deletions(-) rename src/Mod/Fem/femtest/{testfiles => app}/__init__.py (100%) rename src/Mod/Fem/femtest/{utilstest.py => app/support_utils.py} (99%) rename src/Mod/Fem/femtest/{testccxtools.py => app/test_ccxtools.py} (98%) rename src/Mod/Fem/femtest/{testcommon.py => app/test_common.py} (98%) rename src/Mod/Fem/femtest/{testfemimport.py => app/test_femimport.py} (99%) rename src/Mod/Fem/femtest/{testmaterial.py => app/test_material.py} (99%) rename src/Mod/Fem/femtest/{testmesh.py => app/test_mesh.py} (99%) rename src/Mod/Fem/femtest/{testobject.py => app/test_object.py} (99%) rename src/Mod/Fem/femtest/{testresult.py => app/test_result.py} (99%) rename src/Mod/Fem/femtest/{testsolverframework.py => app/test_solverframework.py} (98%) rename src/Mod/Fem/femtest/{testfiles/ccx => data}/__init__.py (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/Flow1D_mesh.py (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/Flow1D_thermomech.FCStd (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/Flow1D_thermomech.dat (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/Flow1D_thermomech.frd (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/Flow1D_thermomech.inp (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/Flow1D_thermomech_expected_values (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/Flow1D_thermomech_inout_nodes.txt (100%) rename src/Mod/Fem/femtest/{testfiles/elmer => data/ccx}/__init__.py (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube.FCStd (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_frequency.FCStd (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_frequency.dat (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_frequency.frd (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_frequency.inp (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_frequency_expected_values (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_mesh.py (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_static.FCStd (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_static.dat (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_static.frd (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_static.inp (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/cube_static_expected_values (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/multimat.inp (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/multimat_mesh.py (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/spine_mesh.py (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/spine_points.csv (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/spine_thermomech.FCStd (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/spine_thermomech.dat (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/spine_thermomech.frd (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/spine_thermomech.inp (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/spine_thermomech_expected_values (100%) rename src/Mod/Fem/femtest/{testfiles => data}/ccx/spine_volumes.csv (100%) rename src/Mod/Fem/femtest/{testfiles => data}/elmer/ELMERSOLVER_STARTINFO (100%) rename src/Mod/Fem/femtest/{testfiles/mesh => data/elmer}/__init__.py (100%) rename src/Mod/Fem/femtest/{testfiles => data}/elmer/case.sif (100%) rename src/Mod/Fem/femtest/{testfiles => data}/elmer/group_mesh.geo (100%) create mode 100644 src/Mod/Fem/femtest/data/mesh/__init__.py rename src/Mod/Fem/femtest/{testfiles => data}/mesh/tetra10_mesh.inp (100%) rename src/Mod/Fem/femtest/{testfiles => data}/mesh/tetra10_mesh.unv (100%) rename src/Mod/Fem/femtest/{testfiles => data}/mesh/tetra10_mesh.vtk (100%) rename src/Mod/Fem/femtest/{testfiles => data}/mesh/tetra10_mesh.yml (100%) rename src/Mod/Fem/femtest/{testfiles => data}/mesh/tetra10_mesh.z88 (100%) diff --git a/src/Mod/Fem/App/FemMesh.cpp b/src/Mod/Fem/App/FemMesh.cpp index 6cbf412d19..a544125bef 100644 --- a/src/Mod/Fem/App/FemMesh.cpp +++ b/src/Mod/Fem/App/FemMesh.cpp @@ -1179,7 +1179,7 @@ void FemMesh::readAbaqus(const std::string &FileName) /* Python command to read Abaqus inp mesh file from test suite: from feminout.importInpMesh import read as read_inp - femmesh = read_inp(FreeCAD.ConfigGet("AppHomePath") + 'Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.inp') + femmesh = read_inp(FreeCAD.ConfigGet("AppHomePath") + 'Mod/Fem/femtest/data/mesh/tetra10_mesh.inp') */ PyObject* module = PyImport_ImportModule("feminout.importInpMesh"); @@ -1215,7 +1215,7 @@ void FemMesh::readZ88(const std::string &FileName) /* Python command to read Z88 mesh file from test suite: from feminout.importZ88Mesh import read as read_z88 - femmesh = read_z88(FreeCAD.ConfigGet("AppHomePath") + 'Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.z88') + femmesh = read_z88(FreeCAD.ConfigGet("AppHomePath") + 'Mod/Fem/femtest/data/mesh/tetra10_mesh.z88') */ PyObject* module = PyImport_ImportModule("feminout.importZ88Mesh"); diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 0dde69df42..9a7606b3e3 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -130,66 +130,70 @@ SET(FemSolverZ88_SRCS SET(FemTests_SRCS femtest/__init__.py - femtest/testccxtools.py - femtest/testcommon.py - femtest/testfemimport.py - femtest/testmaterial.py - femtest/testmesh.py - femtest/testobject.py - femtest/testresult.py - femtest/testsolverframework.py - femtest/utilstest.py +) + +SET(FemTestsApp_SRCS + femtest/app/__init__.py + femtest/app/support_utils.py + femtest/app/test_ccxtools.py + femtest/app/test_common.py + femtest/app/test_femimport.py + femtest/app/test_material.py + femtest/app/test_mesh.py + femtest/app/test_object.py + femtest/app/test_result.py + femtest/app/test_solverframework.py ) SET(FemTestsFiles_SRCS - femtest/testfiles/__init__.py + femtest/data/__init__.py ) SET(FemTestsCcx_SRCS - femtest/testfiles/ccx/__init__.py - femtest/testfiles/ccx/cube_mesh.py - femtest/testfiles/ccx/cube_frequency.inp - femtest/testfiles/ccx/cube_frequency.dat - femtest/testfiles/ccx/cube_frequency.frd - femtest/testfiles/ccx/cube_frequency_expected_values - femtest/testfiles/ccx/cube_frequency.FCStd - femtest/testfiles/ccx/cube_static.inp - femtest/testfiles/ccx/cube_static.dat - femtest/testfiles/ccx/cube_static.frd - femtest/testfiles/ccx/cube_static_expected_values - femtest/testfiles/ccx/cube_static.FCStd - femtest/testfiles/ccx/cube.FCStd - femtest/testfiles/ccx/multimat.inp - femtest/testfiles/ccx/multimat_mesh.py - femtest/testfiles/ccx/spine_mesh.py - femtest/testfiles/ccx/spine_thermomech.inp - femtest/testfiles/ccx/spine_thermomech.dat - femtest/testfiles/ccx/spine_thermomech.frd - femtest/testfiles/ccx/spine_thermomech_expected_values - femtest/testfiles/ccx/spine_thermomech.FCStd - femtest/testfiles/ccx/Flow1D_mesh.py - femtest/testfiles/ccx/Flow1D_thermomech.inp - femtest/testfiles/ccx/Flow1D_thermomech.dat - femtest/testfiles/ccx/Flow1D_thermomech.frd - femtest/testfiles/ccx/Flow1D_thermomech_expected_values - femtest/testfiles/ccx/Flow1D_thermomech_inout_nodes.txt - femtest/testfiles/ccx/Flow1D_thermomech.FCStd + femtest/data/ccx/__init__.py + femtest/data/ccx/cube_mesh.py + femtest/data/ccx/cube_frequency.inp + femtest/data/ccx/cube_frequency.dat + femtest/data/ccx/cube_frequency.frd + femtest/data/ccx/cube_frequency_expected_values + femtest/data/ccx/cube_frequency.FCStd + femtest/data/ccx/cube_static.inp + femtest/data/ccx/cube_static.dat + femtest/data/ccx/cube_static.frd + femtest/data/ccx/cube_static_expected_values + femtest/data/ccx/cube_static.FCStd + femtest/data/ccx/cube.FCStd + femtest/data/ccx/multimat.inp + femtest/data/ccx/multimat_mesh.py + femtest/data/ccx/spine_mesh.py + femtest/data/ccx/spine_thermomech.inp + femtest/data/ccx/spine_thermomech.dat + femtest/data/ccx/spine_thermomech.frd + femtest/data/ccx/spine_thermomech_expected_values + femtest/data/ccx/spine_thermomech.FCStd + femtest/data/ccx/Flow1D_mesh.py + femtest/data/ccx/Flow1D_thermomech.inp + femtest/data/ccx/Flow1D_thermomech.dat + femtest/data/ccx/Flow1D_thermomech.frd + femtest/data/ccx/Flow1D_thermomech_expected_values + femtest/data/ccx/Flow1D_thermomech_inout_nodes.txt + femtest/data/ccx/Flow1D_thermomech.FCStd ) SET(FemTestsElmer_SRCS - femtest/testfiles/elmer/__init__.py - femtest/testfiles/elmer/case.sif - femtest/testfiles/elmer/group_mesh.geo - femtest/testfiles/elmer/ELMERSOLVER_STARTINFO + femtest/data/elmer/__init__.py + femtest/data/elmer/case.sif + femtest/data/elmer/group_mesh.geo + femtest/data/elmer/ELMERSOLVER_STARTINFO ) SET(FemTestsMesh_SRCS - femtest/testfiles/mesh/__init__.py - femtest/testfiles/mesh/tetra10_mesh.inp - femtest/testfiles/mesh/tetra10_mesh.unv - femtest/testfiles/mesh/tetra10_mesh.vtk - femtest/testfiles/mesh/tetra10_mesh.yml - femtest/testfiles/mesh/tetra10_mesh.z88 + femtest/data/mesh/__init__.py + femtest/data/mesh/tetra10_mesh.inp + femtest/data/mesh/tetra10_mesh.unv + femtest/data/mesh/tetra10_mesh.vtk + femtest/data/mesh/tetra10_mesh.yml + femtest/data/mesh/tetra10_mesh.z88 ) SET(FemTools_SRCS @@ -237,6 +241,7 @@ SET(FemAllScripts ${FemSolverFenics_SRCS} ${FemSolverZ88_SRCS} ${FemTests_SRCS} + ${FemTestsApp_SRCS} ${FemTestsFiles_SRCS} ${FemTestsCcx_SRCS} ${FemTestsElmer_SRCS} @@ -268,10 +273,11 @@ INSTALL(FILES ${FemSolverElmerEquations_SRCS} DESTINATION Mod/Fem/femsolver/elme INSTALL(FILES ${FemSolverFenics_SRCS} DESTINATION Mod/Fem/femsolver/fenics) INSTALL(FILES ${FemSolverZ88_SRCS} DESTINATION Mod/Fem/femsolver/z88) INSTALL(FILES ${FemTests_SRCS} DESTINATION Mod/Fem/femtest) -INSTALL(FILES ${FemTestsFiles_SRCS} DESTINATION Mod/Fem/femtest/testfiles) -INSTALL(FILES ${FemTestsCcx_SRCS} DESTINATION Mod/Fem/femtest/testfiles/ccx) -INSTALL(FILES ${FemTestsElmer_SRCS} DESTINATION Mod/Fem/femtest/testfiles/elmer) -INSTALL(FILES ${FemTestsMesh_SRCS} DESTINATION Mod/Fem/femtest/testfiles/mesh) +INSTALL(FILES ${FemTestsApp_SRCS} DESTINATION Mod/Fem/femtest/app) +INSTALL(FILES ${FemTestsFiles_SRCS} DESTINATION Mod/Fem/femtest/data) +INSTALL(FILES ${FemTestsCcx_SRCS} DESTINATION Mod/Fem/femtest/data/ccx) +INSTALL(FILES ${FemTestsElmer_SRCS} DESTINATION Mod/Fem/femtest/data/elmer) +INSTALL(FILES ${FemTestsMesh_SRCS} DESTINATION Mod/Fem/femtest/data/mesh) INSTALL(FILES ${FemTools_SRCS} DESTINATION Mod/Fem/femtools) INSTALL(FILES ${FemObjectsScripts_SRCS} DESTINATION Mod/Fem/femobjects) diff --git a/src/Mod/Fem/TestFem.py b/src/Mod/Fem/TestFem.py index d181777a6d..fdeb9bdfa7 100644 --- a/src/Mod/Fem/TestFem.py +++ b/src/Mod/Fem/TestFem.py @@ -26,16 +26,16 @@ # Unit test for the FEM module # to get the right order import as is used -from femtest.testfemimport import TestFemImport as FemTest01 -from femtest.testcommon import TestFemCommon as FemTest02 -from femtest.testobject import TestObjectCreate as FemTest03 -from femtest.testobject import TestObjectType as FemTest04 -from femtest.testmaterial import TestMaterialUnits as FemTest05 -from femtest.testmesh import TestMeshCommon as FemTest06 -from femtest.testmesh import TestMeshEleTetra10 as FemTest07 -from femtest.testresult import TestResult as FemTest08 -from femtest.testccxtools import TestCcxTools as FemTest09 -from femtest.testsolverframework import TestSolverFrameWork as FemTest10 +from femtest.app.test_femimport import TestFemImport as FemTest01 +from femtest.app.test_common import TestFemCommon as FemTest02 +from femtest.app.test_object import TestObjectCreate as FemTest03 +from femtest.app.test_object import TestObjectType as FemTest04 +from femtest.app.test_material import TestMaterialUnits as FemTest05 +from femtest.app.test_mesh import TestMeshCommon as FemTest06 +from femtest.app.test_mesh import TestMeshEleTetra10 as FemTest07 +from femtest.app.test_result import TestResult as FemTest08 +from femtest.app.test_ccxtools import TestCcxTools as FemTest09 +from femtest.app.test_solverframework import TestSolverFrameWork as FemTest10 # dummy usage to get flake8 and lgtm quiet False if FemTest01.__name__ else True @@ -258,13 +258,12 @@ unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.t # open files from FEM test suite source code # be careful on updating these files, they contain the original results! # TODO update files, because some of them have non-existing FEM object classes -app_home = FreeCAD.ConfigGet("AppHomePath") -doc = FreeCAD.open(app_home + "Mod/Fem/femtest/testfiles/ccx/cube.FCStd") -doc = FreeCAD.open(app_home + "Mod/Fem/femtest/testfiles/ccx/cube_frequency.FCStd") -doc = FreeCAD.open(app_home + "Mod/Fem/femtest/testfiles/ccx/cube_static.FCStd") -doc = FreeCAD.open(app_home + "Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech.FCStd") -doc = FreeCAD.open(app_home + "Mod/Fem/femtest/testfiles/ccx/multimat.FCStd") -doc = FreeCAD.open(app_home + "Mod/Fem/femtest/testfiles/ccx/spine_thermomech.FCStd") +doc = FreeCAD.open(FreeCAD.ConfigGet("AppHomePath") + 'Mod/Fem/femtest/data/ccx/cube.FCStd') +doc = FreeCAD.open(FreeCAD.ConfigGet("AppHomePath") + 'Mod/Fem/femtest/data/ccx/cube_frequency.FCStd') +doc = FreeCAD.open(FreeCAD.ConfigGet("AppHomePath") + 'Mod/Fem/femtest/data/ccx/cube_static.FCStd') +doc = FreeCAD.open(FreeCAD.ConfigGet("AppHomePath") + 'Mod/Fem/femtest/data/ccx/Flow1D_thermomech.FCStd') +doc = FreeCAD.open(FreeCAD.ConfigGet("AppHomePath") + 'Mod/Fem/femtest/data/ccx/multimat.FCStd') +doc = FreeCAD.open(FreeCAD.ConfigGet("AppHomePath") + 'Mod/Fem/femtest/data/ccx/spine_thermomech.FCStd') # open files generated from test suite import femtest.utilstest as ut diff --git a/src/Mod/Fem/femtest/testfiles/__init__.py b/src/Mod/Fem/femtest/app/__init__.py similarity index 100% rename from src/Mod/Fem/femtest/testfiles/__init__.py rename to src/Mod/Fem/femtest/app/__init__.py diff --git a/src/Mod/Fem/femtest/utilstest.py b/src/Mod/Fem/femtest/app/support_utils.py similarity index 99% rename from src/Mod/Fem/femtest/utilstest.py rename to src/Mod/Fem/femtest/app/support_utils.py index d0deb96fb5..ecb6f740ca 100644 --- a/src/Mod/Fem/femtest/utilstest.py +++ b/src/Mod/Fem/femtest/app/support_utils.py @@ -36,7 +36,7 @@ from os.path import join def get_fem_test_home_dir( ): - return join(FreeCAD.getHomePath(), "Mod", "Fem", "femtest", "testfiles") + return join(FreeCAD.getHomePath(), "Mod", "Fem", "femtest", "data") def get_fem_test_tmp_dir( diff --git a/src/Mod/Fem/femtest/testccxtools.py b/src/Mod/Fem/femtest/app/test_ccxtools.py similarity index 98% rename from src/Mod/Fem/femtest/testccxtools.py rename to src/Mod/Fem/femtest/app/test_ccxtools.py index 0c49c2ad7f..d0956973e1 100644 --- a/src/Mod/Fem/femtest/testccxtools.py +++ b/src/Mod/Fem/femtest/app/test_ccxtools.py @@ -28,8 +28,8 @@ from femtools import ccxtools import FreeCAD import ObjectsFem import unittest -from . import utilstest as testtools -from .utilstest import fcc_print +from . import support_utils as testtools +from .support_utils import fcc_print from os.path import join @@ -167,8 +167,8 @@ class TestCcxTools(unittest.TestCase): analysis.addObject(pressure_constraint) fcc_print("Checking FEM new mesh...") - from .testfiles.ccx.cube_mesh import create_nodes_cube - from .testfiles.ccx.cube_mesh import create_elements_cube + from ..data.ccx.cube_mesh import create_nodes_cube + from ..data.ccx.cube_mesh import create_elements_cube mesh = Fem.FemMesh() ret = create_nodes_cube(mesh) self.assertTrue( @@ -380,7 +380,7 @@ class TestCcxTools(unittest.TestCase): analysis.addObject(pressure_constraint) mesh = Fem.FemMesh() - import femtest.testfiles.ccx.multimat_mesh as multimatmesh + import femtest.data.ccx.multimat_mesh as multimatmesh multimatmesh.create_nodes(mesh) multimatmesh.create_elements(mesh) mesh_object = self.active_doc.addObject("Fem::FemMeshObject", self.mesh_name) @@ -481,8 +481,8 @@ class TestCcxTools(unittest.TestCase): analysis.addObject(material_object) fcc_print("Checking FEM new mesh...") - from .testfiles.ccx.cube_mesh import create_nodes_cube - from .testfiles.ccx.cube_mesh import create_elements_cube + from ..data.ccx.cube_mesh import create_nodes_cube + from ..data.ccx.cube_mesh import create_elements_cube mesh = Fem.FemMesh() ret = create_nodes_cube(mesh) self.assertTrue(ret, "Import of mesh nodes failed") @@ -704,8 +704,8 @@ class TestCcxTools(unittest.TestCase): analysis.addObject(heatflux_constraint) fcc_print("Checking FEM new mesh...") - from .testfiles.ccx.spine_mesh import create_nodes_spine - from .testfiles.ccx.spine_mesh import create_elements_spine + from ..data.ccx.spine_mesh import create_nodes_spine + from ..data.ccx.spine_mesh import create_elements_spine mesh = Fem.FemMesh() ret = create_nodes_spine(mesh) self.assertTrue( @@ -1106,8 +1106,8 @@ class TestCcxTools(unittest.TestCase): analysis.addObject(Flow1d_self_weight) fcc_print("Checking FEM new mesh...") - from .testfiles.ccx.Flow1D_mesh import create_nodes_Flow1D - from .testfiles.ccx.Flow1D_mesh import create_elements_Flow1D + from ..data.ccx.Flow1D_mesh import create_nodes_Flow1D + from ..data.ccx.Flow1D_mesh import create_elements_Flow1D mesh = Fem.FemMesh() ret = create_nodes_Flow1D(mesh) self.assertTrue(ret, "Import of mesh nodes failed") diff --git a/src/Mod/Fem/femtest/testcommon.py b/src/Mod/Fem/femtest/app/test_common.py similarity index 98% rename from src/Mod/Fem/femtest/testcommon.py rename to src/Mod/Fem/femtest/app/test_common.py index 4f5334253c..93170e1606 100644 --- a/src/Mod/Fem/femtest/testcommon.py +++ b/src/Mod/Fem/femtest/app/test_common.py @@ -26,8 +26,8 @@ import FreeCAD import ObjectsFem import unittest -from . import utilstest as testtools -from .utilstest import fcc_print +from . import support_utils as testtools +from .support_utils import fcc_print class TestFemCommon(unittest.TestCase): diff --git a/src/Mod/Fem/femtest/testfemimport.py b/src/Mod/Fem/femtest/app/test_femimport.py similarity index 99% rename from src/Mod/Fem/femtest/testfemimport.py rename to src/Mod/Fem/femtest/app/test_femimport.py index de4cc42532..7d6e6bc100 100644 --- a/src/Mod/Fem/femtest/testfemimport.py +++ b/src/Mod/Fem/femtest/app/test_femimport.py @@ -26,7 +26,7 @@ import unittest import FreeCAD -from femtest.utilstest import fcc_print +from .support_utils import fcc_print class TestFemImport(unittest.TestCase): diff --git a/src/Mod/Fem/femtest/testmaterial.py b/src/Mod/Fem/femtest/app/test_material.py similarity index 99% rename from src/Mod/Fem/femtest/testmaterial.py rename to src/Mod/Fem/femtest/app/test_material.py index 47c43317e8..1accd77366 100644 --- a/src/Mod/Fem/femtest/testmaterial.py +++ b/src/Mod/Fem/femtest/app/test_material.py @@ -25,7 +25,7 @@ import FreeCAD import unittest -from .utilstest import fcc_print +from .support_utils import fcc_print from os.path import join diff --git a/src/Mod/Fem/femtest/testmesh.py b/src/Mod/Fem/femtest/app/test_mesh.py similarity index 99% rename from src/Mod/Fem/femtest/testmesh.py rename to src/Mod/Fem/femtest/app/test_mesh.py index 28dad0c37f..a5c792e176 100644 --- a/src/Mod/Fem/femtest/testmesh.py +++ b/src/Mod/Fem/femtest/app/test_mesh.py @@ -26,8 +26,8 @@ import Fem import FreeCAD import unittest -from . import utilstest as testtools -from .utilstest import fcc_print +from . import support_utils as testtools +from .support_utils import fcc_print from os.path import join diff --git a/src/Mod/Fem/femtest/testobject.py b/src/Mod/Fem/femtest/app/test_object.py similarity index 99% rename from src/Mod/Fem/femtest/testobject.py rename to src/Mod/Fem/femtest/app/test_object.py index a24aba05ab..3c7ad38d40 100644 --- a/src/Mod/Fem/femtest/testobject.py +++ b/src/Mod/Fem/femtest/app/test_object.py @@ -26,8 +26,8 @@ import FreeCAD import ObjectsFem import unittest -from . import utilstest as testtools -from .utilstest import fcc_print +from . import support_utils as testtools +from .support_utils import fcc_print class TestObjectCreate(unittest.TestCase): diff --git a/src/Mod/Fem/femtest/testresult.py b/src/Mod/Fem/femtest/app/test_result.py similarity index 99% rename from src/Mod/Fem/femtest/testresult.py rename to src/Mod/Fem/femtest/app/test_result.py index b4f94e0543..1d4a39a2ac 100644 --- a/src/Mod/Fem/femtest/testresult.py +++ b/src/Mod/Fem/femtest/app/test_result.py @@ -25,8 +25,8 @@ import FreeCAD import unittest -from . import utilstest as testtools -from .utilstest import fcc_print +from . import support_utils as testtools +from .support_utils import fcc_print from os.path import join diff --git a/src/Mod/Fem/femtest/testsolverframework.py b/src/Mod/Fem/femtest/app/test_solverframework.py similarity index 98% rename from src/Mod/Fem/femtest/testsolverframework.py rename to src/Mod/Fem/femtest/app/test_solverframework.py index b7ea497659..fa0dbce4d2 100644 --- a/src/Mod/Fem/femtest/testsolverframework.py +++ b/src/Mod/Fem/femtest/app/test_solverframework.py @@ -27,8 +27,8 @@ import FreeCAD import ObjectsFem import femsolver.run import unittest -from . import utilstest as testtools -from .utilstest import fcc_print +from . import support_utils as testtools +from .support_utils import fcc_print from os.path import join @@ -127,8 +127,8 @@ class TestSolverFrameWork(unittest.TestCase): analysis.addObject(pressure_constraint) fcc_print("Checking FEM new mesh...") - from .testfiles.ccx.cube_mesh import create_nodes_cube - from .testfiles.ccx.cube_mesh import create_elements_cube + from ..data.ccx.cube_mesh import create_nodes_cube + from ..data.ccx.cube_mesh import create_elements_cube mesh = Fem.FemMesh() ret = create_nodes_cube(mesh) self.assertTrue(ret, "Import of mesh nodes failed") diff --git a/src/Mod/Fem/femtest/testfiles/ccx/__init__.py b/src/Mod/Fem/femtest/data/__init__.py similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/__init__.py rename to src/Mod/Fem/femtest/data/__init__.py diff --git a/src/Mod/Fem/femtest/testfiles/ccx/Flow1D_mesh.py b/src/Mod/Fem/femtest/data/ccx/Flow1D_mesh.py similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/Flow1D_mesh.py rename to src/Mod/Fem/femtest/data/ccx/Flow1D_mesh.py diff --git a/src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech.FCStd b/src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech.FCStd similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech.FCStd rename to src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech.FCStd diff --git a/src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech.dat b/src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech.dat similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech.dat rename to src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech.dat diff --git a/src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech.frd b/src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech.frd similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech.frd rename to src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech.frd diff --git a/src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech.inp b/src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech.inp similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech.inp rename to src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech.inp diff --git a/src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech_expected_values b/src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech_expected_values similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech_expected_values rename to src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech_expected_values diff --git a/src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech_inout_nodes.txt b/src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech_inout_nodes.txt similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/Flow1D_thermomech_inout_nodes.txt rename to src/Mod/Fem/femtest/data/ccx/Flow1D_thermomech_inout_nodes.txt diff --git a/src/Mod/Fem/femtest/testfiles/elmer/__init__.py b/src/Mod/Fem/femtest/data/ccx/__init__.py similarity index 100% rename from src/Mod/Fem/femtest/testfiles/elmer/__init__.py rename to src/Mod/Fem/femtest/data/ccx/__init__.py diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube.FCStd b/src/Mod/Fem/femtest/data/ccx/cube.FCStd similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube.FCStd rename to src/Mod/Fem/femtest/data/ccx/cube.FCStd diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_frequency.FCStd b/src/Mod/Fem/femtest/data/ccx/cube_frequency.FCStd similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_frequency.FCStd rename to src/Mod/Fem/femtest/data/ccx/cube_frequency.FCStd diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_frequency.dat b/src/Mod/Fem/femtest/data/ccx/cube_frequency.dat similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_frequency.dat rename to src/Mod/Fem/femtest/data/ccx/cube_frequency.dat diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_frequency.frd b/src/Mod/Fem/femtest/data/ccx/cube_frequency.frd similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_frequency.frd rename to src/Mod/Fem/femtest/data/ccx/cube_frequency.frd diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_frequency.inp b/src/Mod/Fem/femtest/data/ccx/cube_frequency.inp similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_frequency.inp rename to src/Mod/Fem/femtest/data/ccx/cube_frequency.inp diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_frequency_expected_values b/src/Mod/Fem/femtest/data/ccx/cube_frequency_expected_values similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_frequency_expected_values rename to src/Mod/Fem/femtest/data/ccx/cube_frequency_expected_values diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_mesh.py b/src/Mod/Fem/femtest/data/ccx/cube_mesh.py similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_mesh.py rename to src/Mod/Fem/femtest/data/ccx/cube_mesh.py diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_static.FCStd b/src/Mod/Fem/femtest/data/ccx/cube_static.FCStd similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_static.FCStd rename to src/Mod/Fem/femtest/data/ccx/cube_static.FCStd diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_static.dat b/src/Mod/Fem/femtest/data/ccx/cube_static.dat similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_static.dat rename to src/Mod/Fem/femtest/data/ccx/cube_static.dat diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_static.frd b/src/Mod/Fem/femtest/data/ccx/cube_static.frd similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_static.frd rename to src/Mod/Fem/femtest/data/ccx/cube_static.frd diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_static.inp b/src/Mod/Fem/femtest/data/ccx/cube_static.inp similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_static.inp rename to src/Mod/Fem/femtest/data/ccx/cube_static.inp diff --git a/src/Mod/Fem/femtest/testfiles/ccx/cube_static_expected_values b/src/Mod/Fem/femtest/data/ccx/cube_static_expected_values similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/cube_static_expected_values rename to src/Mod/Fem/femtest/data/ccx/cube_static_expected_values diff --git a/src/Mod/Fem/femtest/testfiles/ccx/multimat.inp b/src/Mod/Fem/femtest/data/ccx/multimat.inp similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/multimat.inp rename to src/Mod/Fem/femtest/data/ccx/multimat.inp diff --git a/src/Mod/Fem/femtest/testfiles/ccx/multimat_mesh.py b/src/Mod/Fem/femtest/data/ccx/multimat_mesh.py similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/multimat_mesh.py rename to src/Mod/Fem/femtest/data/ccx/multimat_mesh.py diff --git a/src/Mod/Fem/femtest/testfiles/ccx/spine_mesh.py b/src/Mod/Fem/femtest/data/ccx/spine_mesh.py similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/spine_mesh.py rename to src/Mod/Fem/femtest/data/ccx/spine_mesh.py diff --git a/src/Mod/Fem/femtest/testfiles/ccx/spine_points.csv b/src/Mod/Fem/femtest/data/ccx/spine_points.csv similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/spine_points.csv rename to src/Mod/Fem/femtest/data/ccx/spine_points.csv diff --git a/src/Mod/Fem/femtest/testfiles/ccx/spine_thermomech.FCStd b/src/Mod/Fem/femtest/data/ccx/spine_thermomech.FCStd similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/spine_thermomech.FCStd rename to src/Mod/Fem/femtest/data/ccx/spine_thermomech.FCStd diff --git a/src/Mod/Fem/femtest/testfiles/ccx/spine_thermomech.dat b/src/Mod/Fem/femtest/data/ccx/spine_thermomech.dat similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/spine_thermomech.dat rename to src/Mod/Fem/femtest/data/ccx/spine_thermomech.dat diff --git a/src/Mod/Fem/femtest/testfiles/ccx/spine_thermomech.frd b/src/Mod/Fem/femtest/data/ccx/spine_thermomech.frd similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/spine_thermomech.frd rename to src/Mod/Fem/femtest/data/ccx/spine_thermomech.frd diff --git a/src/Mod/Fem/femtest/testfiles/ccx/spine_thermomech.inp b/src/Mod/Fem/femtest/data/ccx/spine_thermomech.inp similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/spine_thermomech.inp rename to src/Mod/Fem/femtest/data/ccx/spine_thermomech.inp diff --git a/src/Mod/Fem/femtest/testfiles/ccx/spine_thermomech_expected_values b/src/Mod/Fem/femtest/data/ccx/spine_thermomech_expected_values similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/spine_thermomech_expected_values rename to src/Mod/Fem/femtest/data/ccx/spine_thermomech_expected_values diff --git a/src/Mod/Fem/femtest/testfiles/ccx/spine_volumes.csv b/src/Mod/Fem/femtest/data/ccx/spine_volumes.csv similarity index 100% rename from src/Mod/Fem/femtest/testfiles/ccx/spine_volumes.csv rename to src/Mod/Fem/femtest/data/ccx/spine_volumes.csv diff --git a/src/Mod/Fem/femtest/testfiles/elmer/ELMERSOLVER_STARTINFO b/src/Mod/Fem/femtest/data/elmer/ELMERSOLVER_STARTINFO similarity index 100% rename from src/Mod/Fem/femtest/testfiles/elmer/ELMERSOLVER_STARTINFO rename to src/Mod/Fem/femtest/data/elmer/ELMERSOLVER_STARTINFO diff --git a/src/Mod/Fem/femtest/testfiles/mesh/__init__.py b/src/Mod/Fem/femtest/data/elmer/__init__.py similarity index 100% rename from src/Mod/Fem/femtest/testfiles/mesh/__init__.py rename to src/Mod/Fem/femtest/data/elmer/__init__.py diff --git a/src/Mod/Fem/femtest/testfiles/elmer/case.sif b/src/Mod/Fem/femtest/data/elmer/case.sif similarity index 100% rename from src/Mod/Fem/femtest/testfiles/elmer/case.sif rename to src/Mod/Fem/femtest/data/elmer/case.sif diff --git a/src/Mod/Fem/femtest/testfiles/elmer/group_mesh.geo b/src/Mod/Fem/femtest/data/elmer/group_mesh.geo similarity index 100% rename from src/Mod/Fem/femtest/testfiles/elmer/group_mesh.geo rename to src/Mod/Fem/femtest/data/elmer/group_mesh.geo diff --git a/src/Mod/Fem/femtest/data/mesh/__init__.py b/src/Mod/Fem/femtest/data/mesh/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.inp b/src/Mod/Fem/femtest/data/mesh/tetra10_mesh.inp similarity index 100% rename from src/Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.inp rename to src/Mod/Fem/femtest/data/mesh/tetra10_mesh.inp diff --git a/src/Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.unv b/src/Mod/Fem/femtest/data/mesh/tetra10_mesh.unv similarity index 100% rename from src/Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.unv rename to src/Mod/Fem/femtest/data/mesh/tetra10_mesh.unv diff --git a/src/Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.vtk b/src/Mod/Fem/femtest/data/mesh/tetra10_mesh.vtk similarity index 100% rename from src/Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.vtk rename to src/Mod/Fem/femtest/data/mesh/tetra10_mesh.vtk diff --git a/src/Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.yml b/src/Mod/Fem/femtest/data/mesh/tetra10_mesh.yml similarity index 100% rename from src/Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.yml rename to src/Mod/Fem/femtest/data/mesh/tetra10_mesh.yml diff --git a/src/Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.z88 b/src/Mod/Fem/femtest/data/mesh/tetra10_mesh.z88 similarity index 100% rename from src/Mod/Fem/femtest/testfiles/mesh/tetra10_mesh.z88 rename to src/Mod/Fem/femtest/data/mesh/tetra10_mesh.z88 From b2483c0a1dbdd82a3303ac451d10499a1e709edf Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Mon, 23 Sep 2019 21:16:47 +0200 Subject: [PATCH 06/10] FEM: unit tests, fix comments --- src/Mod/Fem/TestFem.py | 158 ++++++++++++++++++++--------------------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/src/Mod/Fem/TestFem.py b/src/Mod/Fem/TestFem.py index fdeb9bdfa7..ab374d1a3d 100644 --- a/src/Mod/Fem/TestFem.py +++ b/src/Mod/Fem/TestFem.py @@ -93,22 +93,22 @@ unittest.TextTestRunner().run(alltest) ./bin/FreeCADCmd --run-test "femtest.testfemimport" # other module -./bin/FreeCAD --run-test "femtest.testfemimport" -./bin/FreeCAD --run-test "femtest.testccxtools" -./bin/FreeCAD --run-test "femtest.testcommon" -./bin/FreeCAD --run-test "femtest.testmaterial" -./bin/FreeCAD --run-test "femtest.testmesh" -./bin/FreeCAD --run-test "femtest.testobject" -./bin/FreeCAD --run-test "femtest.testresult" -./bin/FreeCAD --run-test "femtest.testsolverframework" -./bin/FreeCADCmd --run-test "femtest.testfemimport" -./bin/FreeCADCmd --run-test "femtest.testccxtools" -./bin/FreeCADCmd --run-test "femtest.testcommon" -./bin/FreeCADCmd --run-test "femtest.testmaterial" -./bin/FreeCADCmd --run-test "femtest.testmesh" -./bin/FreeCADCmd --run-test "femtest.testobject" -./bin/FreeCADCmd --run-test "femtest.testresult" -./bin/FreeCADCmd --run-test "femtest.testsolverframework" +./bin/FreeCAD --run-test "femtest.app.test_femimport" +./bin/FreeCAD --run-test "femtest.app.test_ccxtools" +./bin/FreeCAD --run-test "femtest.app.test_common" +./bin/FreeCAD --run-test "femtest.app.test_material" +./bin/FreeCAD --run-test "femtest.app.test_mesh" +./bin/FreeCAD --run-test "femtest.app.test_object" +./bin/FreeCAD --run-test "femtest.app.test_result" +./bin/FreeCAD --run-test "femtest.app.test_solverframework" +./bin/FreeCADCmd --run-test "femtest.app.test_femimport" +./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools" +./bin/FreeCADCmd --run-test "femtest.app.test_common" +./bin/FreeCADCmd --run-test "femtest.app.test_material" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh" +./bin/FreeCADCmd --run-test "femtest.app.test_object" +./bin/FreeCADCmd --run-test "femtest.app.test_result" +./bin/FreeCADCmd --run-test "femtest.app.test_solverframework" # class ./bin/FreeCAD --run-test "femtest.testcommon.TestFemCommon" @@ -122,38 +122,38 @@ unittest.TextTestRunner().run(alltest) from femtest.utilstest import get_fem_test_defs as gf gf() -./bin/FreeCADCmd --run-test "femtest.testfemimport.TestObjectExistance.test_objects_existance" -./bin/FreeCADCmd --run-test "femtest.testccxtools.TestCcxTools.test_1_static_analysis" -./bin/FreeCADCmd --run-test "femtest.testccxtools.TestCcxTools.test_2_static_multiple_material" -./bin/FreeCADCmd --run-test "femtest.testccxtools.TestCcxTools.test_3_freq_analysis" -./bin/FreeCADCmd --run-test "femtest.testccxtools.TestCcxTools.test_4_thermomech_analysis" -./bin/FreeCADCmd --run-test "femtest.testccxtools.TestCcxTools.test_5_Flow1D_thermomech_analysis" -./bin/FreeCADCmd --run-test "femtest.testcommon.TestFemCommon.test_adding_refshaps" -./bin/FreeCADCmd --run-test "femtest.testcommon.TestFemCommon.test_pyimport_all_FEM_modules" -./bin/FreeCADCmd --run-test "femtest.testmaterial.TestMaterialUnits.test_known_quantity_units" -./bin/FreeCADCmd --run-test "femtest.testmaterial.TestMaterialUnits.test_material_card_quantities" -./bin/FreeCADCmd --run-test "femtest.testmesh.TestMeshCommon.test_mesh_seg2_python" -./bin/FreeCADCmd --run-test "femtest.testmesh.TestMeshCommon.test_mesh_seg3_python" -./bin/FreeCADCmd --run-test "femtest.testmesh.TestMeshCommon.test_unv_save_load" -./bin/FreeCADCmd --run-test "femtest.testmesh.TestMeshCommon.test_writeAbaqus_precision" -./bin/FreeCADCmd --run-test "femtest.testmesh.TestMeshEleTetra10.test_tetra10_create" -./bin/FreeCADCmd --run-test "femtest.testmesh.TestMeshEleTetra10.test_tetra10_inp" -./bin/FreeCADCmd --run-test "femtest.testmesh.TestMeshEleTetra10.test_tetra10_unv" -./bin/FreeCADCmd --run-test "femtest.testmesh.TestMeshEleTetra10.test_tetra10_vkt" -./bin/FreeCADCmd --run-test "femtest.testmesh.TestMeshEleTetra10.test_tetra10_yml" -./bin/FreeCADCmd --run-test "femtest.testmesh.TestMeshEleTetra10.test_tetra10_z88" -./bin/FreeCADCmd --run-test "femtest.testobject.TestObjectCreate.test_femobjects_make" -./bin/FreeCADCmd --run-test "femtest.testobject.TestObjectType.test_femobjects_type" -./bin/FreeCADCmd --run-test "femtest.testobject.TestObjectType.test_femobjects_isoftype" -./bin/FreeCADCmd --run-test "femtest.testobject.TestObjectType.test_femobjects_derivedfromfem" -./bin/FreeCADCmd --run-test "femtest.testobject.TestObjectType.test_femobjects_derivedfromstd" -./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_read_frd_massflow_networkpressure" -./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_stress_von_mises" -./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_stress_principal_std" -./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_stress_principal_reinforced" -./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_rho" -./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_disp_abs" -./bin/FreeCADCmd --run-test "femtest.testsolverframework.TestSolverFrameWork.test_solver_framework" +./bin/FreeCADCmd --run-test "femtest.app.test_femimport.TestObjectExistance.test_objects_existance" +./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_1_static_analysis" +./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_2_static_multiple_material" +./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_3_freq_analysis" +./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_4_thermomech_analysis" +./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_5_Flow1D_thermomech_analysis" +./bin/FreeCADCmd --run-test "femtest.app.test_common.TestFemCommon.test_adding_refshaps" +./bin/FreeCADCmd --run-test "femtest.app.test_common.TestFemCommon.test_pyimport_all_FEM_modules" +./bin/FreeCADCmd --run-test "femtest.app.test_material.TestMaterialUnits.test_known_quantity_units" +./bin/FreeCADCmd --run-test "femtest.app.test_material.TestMaterialUnits.test_material_card_quantities" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh.TestMeshCommon.test_mesh_seg2_python" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh.TestMeshCommon.test_mesh_seg3_python" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh.TestMeshCommon.test_unv_save_load" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh.TestMeshCommon.test_writeAbaqus_precision" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_create" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_inp" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_unv" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_vkt" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_yml" +./bin/FreeCADCmd --run-test "femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_z88" +./bin/FreeCADCmd --run-test "femtest.app.test_object.TestObjectCreate.test_femobjects_make" +./bin/FreeCADCmd --run-test "femtest.app.test_object.TestObjectType.test_femobjects_type" +./bin/FreeCADCmd --run-test "femtest.app.test_object.TestObjectType.test_femobjects_isoftype" +./bin/FreeCADCmd --run-test "femtest.app.test_object.TestObjectType.test_femobjects_derivedfromfem" +./bin/FreeCADCmd --run-test "femtest.app.test_object.TestObjectType.test_femobjects_derivedfromstd" +./bin/FreeCADCmd --run-test "femtest.app.test_result.TestResult.test_read_frd_massflow_networkpressure" +./bin/FreeCADCmd --run-test "femtest.app.test_result.TestResult.test_stress_von_mises" +./bin/FreeCADCmd --run-test "femtest.app.test_result.TestResult.test_stress_principal_std" +./bin/FreeCADCmd --run-test "femtest.app.test_result.TestResult.test_stress_principal_reinforced" +./bin/FreeCADCmd --run-test "femtest.app.test_result.TestResult.test_rho" +./bin/FreeCADCmd --run-test "femtest.app.test_result.TestResult.test_disp_abs" +./bin/FreeCADCmd --run-test "femtest.app.test_solverframework.TestSolverFrameWork.test_solver_framework" # to get all command to start FreeCAD from build dir on Linux @@ -162,97 +162,97 @@ from femtest.utilstest import get_fem_test_defs as gf gf("in") import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testccxtools.TestCcxTools.test_1_static_analysis")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_1_static_analysis")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testccxtools.TestCcxTools.test_2_static_multiple_material")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_2_static_multiple_material")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testccxtools.TestCcxTools.test_3_freq_analysis")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_3_freq_analysis")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testccxtools.TestCcxTools.test_4_thermomech_analysis")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_4_thermomech_analysis")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testccxtools.TestCcxTools.test_5_Flow1D_thermomech_analysis")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_5_Flow1D_thermomech_analysis")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testcommon.TestFemCommon.test_adding_refshaps")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_common.TestFemCommon.test_adding_refshaps")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testcommon.TestFemCommon.test_pyimport_all_FEM_modules")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_common.TestFemCommon.test_pyimport_all_FEM_modules")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmaterial.TestMaterialUnits.test_known_quantity_units")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_material.TestMaterialUnits.test_known_quantity_units")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmaterial.TestMaterialUnits.test_material_card_quantities")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_material.TestMaterialUnits.test_material_card_quantities")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmesh.TestMeshCommon.test_mesh_seg2_python")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_mesh.TestMeshCommon.test_mesh_seg2_python")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmesh.TestMeshCommon.test_mesh_seg3_python")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_mesh.TestMeshCommon.test_mesh_seg3_python")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmesh.TestMeshCommon.test_unv_save_load")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_mesh.TestMeshCommon.test_unv_save_load")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmesh.TestMeshCommon.test_writeAbaqus_precision")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_mesh.TestMeshCommon.test_writeAbaqus_precision")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmesh.TestMeshEleTetra10.test_tetra10_create")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_create")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmesh.TestMeshEleTetra10.test_tetra10_inp")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_inp")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmesh.TestMeshEleTetra10.test_tetra10_unv")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_unv")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmesh.TestMeshEleTetra10.test_tetra10_vkt")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_vkt")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmesh.TestMeshEleTetra10.test_tetra10_yml")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_yml")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testmesh.TestMeshEleTetra10.test_tetra10_z88")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_mesh.TestMeshEleTetra10.test_tetra10_z88")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testobject.TestObjectCreate.test_femobjects_make")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_object.TestObjectCreate.test_femobjects_make")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testobject.TestObjectType.test_femobjects_type")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_object.TestObjectType.test_femobjects_type")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testobject.TestObjectType.test_femobjects_isoftype")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_object.TestObjectType.test_femobjects_isoftype")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testobject.TestObjectType.test_femobjects_derivedfromfem")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_object.TestObjectType.test_femobjects_derivedfromfem")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testobject.TestObjectType.test_femobjects_derivedfromstd")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_object.TestObjectType.test_femobjects_derivedfromstd")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_read_frd_massflow_networkpressure")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_result.TestResult.test_read_frd_massflow_networkpressure")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_von_mises")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_result.TestResult.test_stress_von_mises")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_principal_std")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_result.TestResult.test_stress_principal_std")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_principal_reinforced")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_result.TestResult.test_stress_principal_reinforced")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_rho")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_result.TestResult.test_rho")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_disp_abs")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_result.TestResult.test_disp_abs")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testsolverframework.TestSolverFrameWork.test_solver_framework")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_solverframework.TestSolverFrameWork.test_solver_framework")) # open files from FEM test suite source code From 80270c7bbf962a5e44644e9c5860c72e9b877087 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Mon, 23 Sep 2019 21:16:49 +0200 Subject: [PATCH 07/10] FEM: typos --- src/Mod/Fem/App/FemAnalysis.h | 8 ++++---- src/Mod/Fem/App/FemConstraint.h | 20 ++++++++++---------- src/Mod/Fem/femtools/femutils.py | 16 ++++++++-------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Mod/Fem/App/FemAnalysis.h b/src/Mod/Fem/App/FemAnalysis.h index 797a61d8c2..7e82ddb92b 100644 --- a/src/Mod/Fem/App/FemAnalysis.h +++ b/src/Mod/Fem/App/FemAnalysis.h @@ -34,15 +34,15 @@ namespace Fem { * @brief Container of objects relevant to one simulation. * * @details - * A Analysis contains all objects nessesary for a complete specification + * A Analysis contains all objects necessary for a complete specification * of a simulation. After computing it also contains the result of the - * simulation. The Analysis object is just a container. It is not reponsible + * simulation. The Analysis object is just a container. It is not responsible * for anything else like executing the simulation. * * The Analysis class is essentially a App::DocumentObjectGroup. It handles * all the container stuff. The difference is that the Analysis document * object uses a different ViewProvider, has a Uid property and does some - * compability handling via handleChangedPropertyName. + * compatibility handling via handleChangedPropertyName. * * This implies that it is not checked which objects are put into the * Analsis object. Every document object of FreeCAD can be part of a @@ -73,7 +73,7 @@ public: protected: /** - * @brief Retain compability with old "Member" property. + * @brief Retain compatibility with old "Member" property. * * @details * In an older version of FreeCAD FemAnalysis handles it's member itself diff --git a/src/Mod/Fem/App/FemConstraint.h b/src/Mod/Fem/App/FemConstraint.h index a28e029d08..b4270b1afe 100644 --- a/src/Mod/Fem/App/FemConstraint.h +++ b/src/Mod/Fem/App/FemConstraint.h @@ -40,7 +40,7 @@ namespace Fem { * used to specify a simulation are children of this class. The base class * essentially does two things: Most importantely it has a property @ref * Constraint::References which is a list of all sub objects the constraint - * applys to. Defining it in the base class exposes a common interface to code + * applies to. Defining it in the base class exposes a common interface to code * using different constraints. * * The second purpose of @ref Constraint is to support the redering to the @@ -146,7 +146,7 @@ public: * This is just used to make code more understandable. Other versions * (overloads) of this function do useful calculations based on faces or * edges. Used by @ref getPoints if no useful shape information is - * avaliable. + * available. * * @return always the integer 1 */ @@ -167,7 +167,7 @@ protected: * @brief Triggers @ref onChanged to update View Provider. * * @note - * This should not be nessesary and is properly a bug in the View Provider + * This should not be necessary and is properly a bug in the View Provider * of FemConstraint. */ virtual void onDocumentRestored(); @@ -203,7 +203,7 @@ protected: * * @return * If the calculation of points, normals and scale was successful it - * returns true. If an error occured and the data couldn't be extracted + * returns true. If an error occurred and the data couldn't be extracted * properly false is returned. */ bool getPoints( @@ -215,8 +215,8 @@ protected: * @brief Extract properties of cylindrical face. * * @note - * This method is very specific and doesn't requre access to member - * variables. It should be rewritten at a different palce. + * This method is very specific and doesn't require access to member + * variables. It should be rewritten at a different place. */ bool getCylinder( double& radius, double& height, @@ -226,8 +226,8 @@ protected: * @brief Calculate point of cylidrical face where to render widget. * * @note - * This method is very specific and doesn't requre access to member - * variables. It should be rewritten at a different palce. + * This method is very specific and doesn't require access to member + * variables. It should be rewritten at a different place. */ Base::Vector3d getBasePoint(const Base::Vector3d& base, const Base::Vector3d& axis, const App::PropertyLinkSub &location, const double& dist); @@ -235,8 +235,8 @@ protected: * @brief Get normal vector of point calculated by @ref getBasePoint. * * @note - * This method is very specific and doesn't requre access to member - * variables. It should be rewritten at a different palce. + * This method is very specific and doesn't require access to member + * variables. It should be rewritten at a different place. */ const Base::Vector3d getDirection(const App::PropertyLinkSub &direction); }; diff --git a/src/Mod/Fem/femtools/femutils.py b/src/Mod/Fem/femtools/femutils.py index c2af8d5062..3d61d7b8e6 100644 --- a/src/Mod/Fem/femtools/femutils.py +++ b/src/Mod/Fem/femtools/femutils.py @@ -22,7 +22,7 @@ # *************************************************************************** """ Collection of functions for the Fem module. -This module contains function for managing a analysis and all the differnet +This module contains function for managing a analysis and all the different types of objects it contains, helper for executing a simulation, function for extracting relevant parts of geometry and a few unrelated function useful at various places in the Fem module. @@ -103,7 +103,7 @@ def get_member(analysis, t): Search *analysis* for members of type *t*. This method checks the custom python typesytem (BaseType class property) used by the Fem module if - possible. If the object doens't use the python typesystem the usual + possible. If the object does not use the python typesystem the usual isDerivedFrom from the C++ dynamic type system is used. :param analysis: only objects part of this analysis are considered @@ -170,8 +170,8 @@ def get_several_member(analysis, t): which is empty. :note: - Undefined behaviour if the type of the references of one object arn't all - the same. + Undefined behaviour if the type of the references of one object are not + all the same. :note: Inheritance of Fem types is not checked. If *obj* uses Fems typesystem the @@ -408,7 +408,7 @@ def getSelectedFace(selectionex): """ Return selected face if exactly one face is selected. :returns: - The selcted face as a ``Part::TopoShape`` if exactly one face is selected. + The selected face as a ``Part::TopoShape`` if exactly one face is selected. Otherwise return ``None``. :param selectionex: @@ -446,11 +446,11 @@ def get_refshape_type(fem_doc_object): :returns: A string representing the shape type ("Vertex", "Edge", "Face" or - "Solid"). If *fem_doc_object* isn't a contraint ``""`` is returned. + "Solid"). If *fem_doc_object* isn't a constraint ``""`` is returned. :note: - Undefined behaviour if the type of the references of one object arn't all - the same. + Undefined behaviour if the type of the references of one object are + not all the same. :note: Undefined behaviour if constraint contains no references (empty list). From a5843cc7fdc27cfdfb0874794eadddf7ee1636a6 Mon Sep 17 00:00:00 2001 From: Markus Hovorka Date: Mon, 23 Sep 2019 21:16:51 +0200 Subject: [PATCH 08/10] FEM: in out modules, Replace print with Console.Print* calls --- src/Mod/Fem/feminout/convert2TetGen.py | 23 +++-- src/Mod/Fem/feminout/importCcxDatResults.py | 4 +- src/Mod/Fem/feminout/importCcxFrdResults.py | 18 ++-- src/Mod/Fem/feminout/importFenicsMesh.py | 13 +-- src/Mod/Fem/feminout/importInpMesh.py | 3 +- src/Mod/Fem/feminout/importToolsFem.py | 15 +-- src/Mod/Fem/feminout/importVTKResults.py | 13 +-- src/Mod/Fem/feminout/importYamlJsonMesh.py | 13 +-- src/Mod/Fem/feminout/importZ88Mesh.py | 85 ++++++++-------- src/Mod/Fem/feminout/importZ88O2Results.py | 8 +- src/Mod/Fem/feminout/readFenicsXDMF.py | 4 +- src/Mod/Fem/feminout/readFenicsXML.py | 32 +++--- src/Mod/Fem/feminout/writeFenicsXDMF.py | 24 +++-- src/Mod/Fem/feminout/writeFenicsXML.py | 13 +-- src/Mod/Fem/femmesh/gmshtools.py | 105 ++++++++++---------- src/Mod/Fem/femsolver/elmer/writer.py | 6 +- 16 files changed, 199 insertions(+), 180 deletions(-) diff --git a/src/Mod/Fem/feminout/convert2TetGen.py b/src/Mod/Fem/feminout/convert2TetGen.py index db4ab46aeb..c380f993af 100644 --- a/src/Mod/Fem/feminout/convert2TetGen.py +++ b/src/Mod/Fem/feminout/convert2TetGen.py @@ -32,18 +32,23 @@ __url__ = "http://www.freecadweb.org" # Make mesh of pn junction in TetGen format import FreeCAD +from FreeCAD import Console import Mesh + App = FreeCAD # shortcut if FreeCAD.GuiUp: import FreeCADGui Gui = FreeCADGui # shortcut +## \addtogroup FEM +# @{ + def exportMeshToTetGenPoly(meshToExport, filePath, beVerbose=1): """Export mesh to TetGen *.poly file format""" # ********** Part 1 - write node list to output file if beVerbose == 1: - FreeCAD.Console.PrintMessage("\nExport of mesh to TetGen file ...") + Console.PrintMessage("\nExport of mesh to TetGen file ...") (allVertices, allFacets) = meshToExport.Topology f = open(filePath, "w") f.write("# This file was generated from FreeCAD geometry\n") @@ -94,7 +99,7 @@ def exportMeshToTetGenPoly(meshToExport, filePath, beVerbose=1): EdgeKeys = EdgeFacets.keys() # disconnectedEdges = len(EdgeKeys) if beVerbose == 1: - FreeCAD.Console.PrintMessage( + Console.PrintMessage( "\nBoundaryMarker:" + repr(BoundaryMarker) + " " + repr(len(EdgeFacets)) ) searchForPair = 1 @@ -146,7 +151,7 @@ def exportMeshToTetGenPoly(meshToExport, filePath, beVerbose=1): searchForPair = 0 # End of main loop if beVerbose == 1: - FreeCAD.Console.PrintMessage( + Console.PrintMessage( "\nNew BoundaryMarker:" + repr(BoundaryMarker) + " " + repr(len(EdgeFacets)) ) @@ -185,7 +190,7 @@ def createMesh(): # ======================== Script beginning... ======================== beVerbose = 1 if beVerbose == 1: - FreeCAD.Console.PrintMessage("\n\n\n\n\n\n\n\nScript starts...") + Console.PrintMessage("\n\n\n\n\n\n\n\nScript starts...") # Geometry definition # Define objects names PyDocumentName = "pnJunction" @@ -199,7 +204,7 @@ def createMesh(): # Init objects if beVerbose == 1: - FreeCAD.Console.PrintMessage("\nInit Objects...") + Console.PrintMessage("\nInit Objects...") # closeDocument after restart of macro. Needs any ActiveDocument. # App.closeDocument(App.ActiveDocument.Label) AppPyDoc = App.newDocument(PyDocumentName) @@ -235,13 +240,13 @@ def createMesh(): ] if beVerbose == 1: if len(BoxList) != len(BoxMeshList): - FreeCAD.Console.PrintMessage( + Console.PrintMessage( "\n ERROR! Input len() of BoxList and BoxMeshList is not the same! " ) # Set sizes in nanometers if beVerbose == 1: - FreeCAD.Console.PrintMessage("\nSet sizes...") + Console.PrintMessage("\nSet sizes...") tessellationTollerance = 0.05 ModelWidth = 300 BulkHeight = 300 @@ -303,7 +308,7 @@ def createMesh(): # Unite if beVerbose == 1: - FreeCAD.Console.PrintMessage("\nFuse objects...") + Console.PrintMessage("\nFuse objects...") fuseShape = BoxList[0].Shape for index in range(1, len(BoxList), 1): fuseShape = fuseShape.fuse(BoxList[index].Shape) @@ -342,6 +347,6 @@ def createMesh(): Gui.SendMsgToActiveView("ViewFit") if beVerbose == 1: - FreeCAD.Console.PrintMessage("\nScript finished without errors.") + Console.PrintMessage("\nScript finished without errors.") ## @} diff --git a/src/Mod/Fem/feminout/importCcxDatResults.py b/src/Mod/Fem/feminout/importCcxDatResults.py index 37f6e292f1..7c57fc5a41 100644 --- a/src/Mod/Fem/feminout/importCcxDatResults.py +++ b/src/Mod/Fem/feminout/importCcxDatResults.py @@ -29,6 +29,7 @@ __url__ = "http://www.freecadweb.org" # \brief FreeCAD Calculix DAT reader for FEM workbench import FreeCAD +from FreeCAD import Console import os @@ -71,7 +72,6 @@ def import_dat( Analysis=None ): r = readResult(filename) - # print("Results {}".format(r)) return r @@ -79,7 +79,7 @@ def import_dat( def readResult( dat_input ): - FreeCAD.Console.PrintMessage("Read ccx results from dat file: {}\n".format(dat_input)) + Console.PrintMessage("Read ccx results from dat file: {}\n".format(dat_input)) dat_file = pyopen(dat_input, "r") eigenvalue_output_section_found = False mode_reading = False diff --git a/src/Mod/Fem/feminout/importCcxFrdResults.py b/src/Mod/Fem/feminout/importCcxFrdResults.py index 2e182066bd..fc4a5cd4bf 100644 --- a/src/Mod/Fem/feminout/importCcxFrdResults.py +++ b/src/Mod/Fem/feminout/importCcxFrdResults.py @@ -31,6 +31,7 @@ __url__ = "http://www.freecadweb.org" # \brief FreeCAD Calculix FRD Reader for FEM workbench import FreeCAD +from FreeCAD import Console import os @@ -88,7 +89,7 @@ def importFrd( nodenumbers_for_compacted_mesh = [] number_of_increments = len(m["Results"]) - FreeCAD.Console.PrintLog( + Console.PrintLog( "Increments: " + str(number_of_increments) + "\n" ) if len(m["Results"]) > 0: @@ -175,7 +176,7 @@ def importFrd( "or if CalculiX returned no results because " "of nonpositive jacobian determinant in at least one element.\n" ) - FreeCAD.Console.PrintMessage(error_message) + Console.PrintMessage(error_message) if analysis: analysis_object.addObject(result_mesh_object) @@ -186,7 +187,7 @@ def importFrd( FreeCAD.ActiveDocument.recompute() else: - FreeCAD.Console.PrintError( + Console.PrintError( "Problem on frd file import. No nodes found in frd file.\n" ) return res_obj @@ -197,14 +198,14 @@ def importFrd( def read_frd_result( frd_input ): - FreeCAD.Console.PrintMessage( + Console.PrintMessage( "Read ccx results from frd file: {}\n" .format(frd_input) ) inout_nodes = [] inout_nodes_file = frd_input.rsplit(".", 1)[0] + "_inout_nodes.txt" if os.path.exists(inout_nodes_file): - FreeCAD.Console.PrintMessage( + Console.PrintMessage( "Read special 1DFlow nodes data form: {}\n".format(inout_nodes_file) ) f = pyopen(inout_nodes_file, "r") @@ -213,7 +214,7 @@ def read_frd_result( a = line.split(",") inout_nodes.append(a) f.close() - FreeCAD.Console.PrintMessage("{}\n".format(inout_nodes)) + Console.PrintMessage("{}\n".format(inout_nodes)) frd_file = pyopen(frd_input, "r") nodes = {} elements_hexa8 = {} @@ -370,7 +371,6 @@ def read_frd_result( nd8, nd5, nd6, nd7, nd4, nd1, nd2, nd3, nd20, nd17, nd18, nd19, nd12, nd9, nd10, nd11, nd16, nd13, nd14, nd15 ) - # print(elements_hexa20[elem]) elif elemType == 5 and input_continues is False: # first line # C3D15 Calculix --> penta15 FreeCAD @@ -719,11 +719,11 @@ def read_frd_result( if not inout_nodes: if results: if "mflow" in results[0] or "npressure" in results[0]: - FreeCAD.Console.PrintError( + Console.PrintError( "We have mflow or npressure, but no inout_nodes file.\n" ) if not nodes: - FreeCAD.Console.PrintError("FEM: No nodes found in Frd file.\n") + Console.PrintError("FEM: No nodes found in Frd file.\n") return { "Nodes": nodes, diff --git a/src/Mod/Fem/feminout/importFenicsMesh.py b/src/Mod/Fem/feminout/importFenicsMesh.py index c34bbb25b2..5f5a19b136 100644 --- a/src/Mod/Fem/feminout/importFenicsMesh.py +++ b/src/Mod/Fem/feminout/importFenicsMesh.py @@ -31,6 +31,7 @@ __url__ = "http://www.freecadweb.org" import os import FreeCAD +from FreeCAD import Console from . import importToolsFem from . import readFenicsXML from . import writeFenicsXML @@ -122,7 +123,7 @@ if FreeCAD.GuiUp: default_value = int(self.form.tableGroups.item(r, 3).text()) marked_value = int(self.form.tableGroups.item(r, 4).text()) except ValueError: - FreeCAD.Console.PrintError( + Console.PrintError( "ERROR: value conversion failed " "in table to dict: assuming 0 for default, " "1 for marked.\n" @@ -165,22 +166,22 @@ def export(objectslist, fileString, group_values_dict_nogui=None): of (marked_value (default=1), default_value (default=0)) """ if len(objectslist) != 1: - FreeCAD.Console.PrintError( + Console.PrintError( "This exporter can only export one object.\n") return obj = objectslist[0] if not obj.isDerivedFrom("Fem::FemMeshObject"): - FreeCAD.Console.PrintError("No FEM mesh object selected.\n") + Console.PrintError("No FEM mesh object selected.\n") return if fileString != "": fileName, fileExtension = os.path.splitext(fileString) if fileExtension.lower() == ".xml": - FreeCAD.Console.PrintWarning( + Console.PrintWarning( "XML is not designed to save higher order elements.\n") - FreeCAD.Console.PrintWarning( + Console.PrintWarning( "Reducing order for second order mesh.\n") - FreeCAD.Console.PrintWarning("Tri6 -> Tri3, Tet10 -> Tet4, etc.\n") + Console.PrintWarning("Tri6 -> Tri3, Tet10 -> Tet4, etc.\n") writeFenicsXML.write_fenics_mesh_xml(obj, fileString) elif fileExtension.lower() == ".xdmf": mesh_groups = importToolsFem.get_FemMeshObjectMeshGroups(obj) diff --git a/src/Mod/Fem/feminout/importInpMesh.py b/src/Mod/Fem/feminout/importInpMesh.py index c0dad0a730..a0792a518c 100644 --- a/src/Mod/Fem/feminout/importInpMesh.py +++ b/src/Mod/Fem/feminout/importInpMesh.py @@ -30,6 +30,7 @@ __date__ = "04/08/2016" # \brief FreeCAD INP file reader for FEM workbench import FreeCAD +from FreeCAD import Console import os @@ -211,7 +212,7 @@ def read_inp(file_name): elif line[:5].upper() == "*STEP": model_definition = False if error_seg3 is True: # to print "not supported" - FreeCAD.Console.PrintError("Error: seg3 (3-node beam element type) not supported, yet.\n") + Console.PrintError("Error: seg3 (3-node beam element type) not supported, yet.\n") f.close() # switch from the CalculiX node numbering to the FreeCAD node numbering diff --git a/src/Mod/Fem/feminout/importToolsFem.py b/src/Mod/Fem/feminout/importToolsFem.py index b16a74ec43..d5e8558707 100644 --- a/src/Mod/Fem/feminout/importToolsFem.py +++ b/src/Mod/Fem/feminout/importToolsFem.py @@ -29,6 +29,7 @@ __url__ = "http://www.freecadweb.org" # \brief FreeCAD FEM import tools import FreeCAD +from FreeCAD import Console def get_FemMeshObjectMeshGroups( @@ -69,7 +70,7 @@ def get_FemMeshObjectOrder( else: presumable_order = [el - 1 for el in edges_length_set] else: - FreeCAD.Console.PrintMessage( + Console.PrintMessage( "Found no edges in mesh: Element order determination does not work without them.\n" ) @@ -212,7 +213,7 @@ def make_femmesh( for i in elms_seg3: e = elms_seg3[i] mesh.addEdge([e[0], e[1], e[2]], i) - FreeCAD.Console.PrintLog( + Console.PrintLog( "imported mesh: {} nodes, {} HEXA8, {} PENTA6, {} TETRA4, {} TETRA10, {} PENTA15" .format( len(nds), @@ -223,7 +224,7 @@ def make_femmesh( len(elms_penta15) ) ) - FreeCAD.Console.PrintLog( + Console.PrintLog( "imported mesh: {} HEXA20, {} TRIA3, {} TRIA6, {} QUAD4, {} QUAD8, {} SEG2, {} SEG3" .format( len(elms_hexa20), @@ -236,9 +237,9 @@ def make_femmesh( ) ) else: - FreeCAD.Console.PrintError("No Elements found!\n") + Console.PrintError("No Elements found!\n") else: - FreeCAD.Console.PrintError("No Nodes found!\n") + Console.PrintError("No Nodes found!\n") return mesh @@ -412,7 +413,7 @@ def fill_femresult_mechanical( if len(Peeq) > 0: if len(Peeq.values()) != len(disp.values()): # how is this possible? An example is needed! - FreeCAD.Console.PrintError("PEEQ seams to have exptra nodes.\n") + Console.PrintError("PEEQ seams to have exptra nodes.\n") Pe = [] Pe_extra_nodes = list(Peeq.values()) nodes = len(disp.values()) @@ -439,7 +440,7 @@ def fill_femresult_mechanical( nodes = len(disp.values()) for i in range(nodes): # how is this possible? An example is needed! - FreeCAD.Console.PrintError("Temperature seams to have exptra nodes.\n") + Console.PrintError("Temperature seams to have exptra nodes.\n") Temp_value = Temp_extra_nodes[i] Temp.append(Temp_value) res_obj.Temperature = list(map((lambda x: x), Temp)) diff --git a/src/Mod/Fem/feminout/importVTKResults.py b/src/Mod/Fem/feminout/importVTKResults.py index 0b9dab84b2..3a2a54d70e 100644 --- a/src/Mod/Fem/feminout/importVTKResults.py +++ b/src/Mod/Fem/feminout/importVTKResults.py @@ -32,6 +32,7 @@ __url__ = "http://www.freecadweb.org" import os import FreeCAD +from FreeCAD import Console import Fem @@ -71,26 +72,26 @@ def export( ): "called when freecad exports an object to vtk" if len(objectslist) > 1: # the case of no selected obj is caught by FreeCAD already - FreeCAD.Console.PrintError( + Console.PrintError( "This exporter can only export one object at once\n" ) return obj = objectslist[0] if obj.isDerivedFrom("Fem::FemPostPipeline"): - FreeCAD.Console.PrintError( - "Export of a VTK post object to vtk is not yet implemented !\n" + Console.PrintError( + "Export of a VTK post object to vtk is not yet implemented!\n" ) return elif obj.isDerivedFrom("Fem::FemMeshObject"): - FreeCAD.Console.PrintError( + Console.PrintError( "Use export to FEM mesh formats to export a FEM mesh object to vtk!\n" ) return elif obj.isDerivedFrom("Fem::FemResultObject"): Fem.writeResult(filename, obj) else: - FreeCAD.Console.PrintError( + Console.PrintError( "Selected object is not supported by export to VTK.\n" ) return @@ -119,7 +120,7 @@ def importVtk( # FreeCAD result object importVtkFCResult(filename, object_name) else: - FreeCAD.Console.PrintError( + Console.PrintError( "Error, wrong parameter in VTK import pref: {}\n" .format(object_type) ) diff --git a/src/Mod/Fem/feminout/importYamlJsonMesh.py b/src/Mod/Fem/feminout/importYamlJsonMesh.py index 2a95a7ab67..41252a0c58 100644 --- a/src/Mod/Fem/feminout/importYamlJsonMesh.py +++ b/src/Mod/Fem/feminout/importYamlJsonMesh.py @@ -32,13 +32,14 @@ import json import os import FreeCAD +from FreeCAD import Console from . import importToolsFem has_yaml = True try: import yaml except ImportError: - FreeCAD.Console.PrintMessage( + Console.PrintMessage( "No YAML available (import yaml failure), " "yaml import/export won't work\n" ) @@ -88,13 +89,13 @@ def insert( def export(objectslist, fileString): "called when freecad exports a file" if len(objectslist) != 1: - FreeCAD.Console.PrintError( + Console.PrintError( "This exporter can only " "export one object.\n") return obj = objectslist[0] if not obj.isDerivedFrom("Fem::FemMeshObject"): - FreeCAD.Console.PrintError("No FEM mesh object selected.\n") + Console.PrintError("No FEM mesh object selected.\n") return write(fileString, obj.FemMesh) @@ -162,13 +163,13 @@ def read( raw_mesh_data = yaml.load(fp) fp.close() else: - FreeCAD.Console.PrintError( + Console.PrintError( "Unknown extension, " "please select other importer.\n") - FreeCAD.Console.PrintMessage("Converting indices to integer numbers ...") + Console.PrintMessage("Converting indices to integer numbers ...") mesh_data = convert_raw_data_to_mesh_data(raw_mesh_data) - FreeCAD.Console.PrintMessage("OK\n") + Console.PrintMessage("OK\n") return importToolsFem.make_femmesh(mesh_data) diff --git a/src/Mod/Fem/feminout/importZ88Mesh.py b/src/Mod/Fem/feminout/importZ88Mesh.py index fb5a0e306c..8f2803dd5a 100644 --- a/src/Mod/Fem/feminout/importZ88Mesh.py +++ b/src/Mod/Fem/feminout/importZ88Mesh.py @@ -31,6 +31,7 @@ __url__ = "http://www.freecadweb.org" import os import FreeCAD +from FreeCAD import Console # ************************************************************************************************ # ********* generic FreeCAD import and export methods ******************************************** @@ -78,11 +79,11 @@ def export( ): "called when freecad exports a file" if len(objectslist) != 1: - FreeCAD.Console.PrintError("This exporter can only export one object.\n") + Console.PrintError("This exporter can only export one object.\n") return obj = objectslist[0] if not obj.isDerivedFrom("Fem::FemMeshObject"): - FreeCAD.Console.PrintError("No FEM mesh object selected.\n") + Console.PrintError("No FEM mesh object selected.\n") return femnodes_mesh = obj.FemMesh.Nodes import femmesh.meshtools as FemMeshTools @@ -179,7 +180,7 @@ def read_z88_mesh( kflag = int(mesh_info[4]) # for non rotational elements ist --> kflag = 0 --> cartesian, kflag = 1 polar coordinates if kflag: - FreeCAD.Console.PrintError( + Console.PrintError( "KFLAG = 1, Rotational coordinates not supported at the moment\n" ) return {} @@ -188,15 +189,15 @@ def read_z88_mesh( elemts_first_line = nodes_last_line + 1 elements_last_line = elemts_first_line - 1 + elements_count * 2 - FreeCAD.Console.PrintLog(nodes_count) + Console.PrintLog(nodes_count) + Console.PrintLog("\n") + Console.PrintLog(elements_count) FreeCAD.Console.PrintLog("\n") - FreeCAD.Console.PrintLog(elements_count) - FreeCAD.Console.PrintLog("\n") - FreeCAD.Console.PrintLog(nodes_last_line) - FreeCAD.Console.PrintLog("\n") - FreeCAD.Console.PrintLog(elemts_first_line) - FreeCAD.Console.PrintLog("\n") - FreeCAD.Console.PrintLog(elements_last_line) + Console.PrintLog(nodes_last_line) + Console.PrintLog("\n") + Console.PrintLog(elemts_first_line) + Console.PrintLog("\n") + Console.PrintLog(elements_last_line) z88_mesh_file.seek(0) # go back to the beginning of the file for no, line in enumerate(z88_mesh_file): @@ -226,55 +227,55 @@ def read_z88_mesh( # not supported elements if z88_element_type == 8: # torus8 - FreeCAD.Console.PrintError( + Console.PrintError( "Z88 Element No. 8, torus8\n" ) - FreeCAD.Console.PrintError( + Console.PrintError( "Rotational elements are not supported at the moment\n" ) return {} elif z88_element_type == 12: # torus12 - FreeCAD.Console.PrintError( + Console.PrintError( "Z88 Element No. 12, torus12\n" ) - FreeCAD.Console.PrintError( + Console.PrintError( "Rotational elements are not supported at the moment\n" ) return {} elif z88_element_type == 15: # torus6 - FreeCAD.Console.PrintError( + Console.PrintError( "Z88 Element No. 15, torus6\n" ) - FreeCAD.Console.PrintError( + Console.PrintError( "Rotational elements are not supported at the moment\n" ) return {} elif z88_element_type == 19: # platte16 - FreeCAD.Console.PrintError( + Console.PrintError( "Z88 Element No. 19, platte16\n" ) - FreeCAD.Console.PrintError( + Console.PrintError( "Not supported at the moment\n" ) return {} elif z88_element_type == 21: # schale16, mixture made from hexa8 and hexa20 (thickness is linear) - FreeCAD.Console.PrintError( + Console.PrintError( "Z88 Element No. 21, schale16\n" ) - FreeCAD.Console.PrintError( + Console.PrintError( "Not supported at the moment\n" ) return {} elif z88_element_type == 22: # schale12, mixtrue made from prism6 and prism15 (thickness is linear) - FreeCAD.Console.PrintError( + Console.PrintError( "Z88 Element No. 22, schale12\n" ) - FreeCAD.Console.PrintError( + Console.PrintError( "Not supported at the moment\n" ) return {} @@ -392,13 +393,13 @@ def read_z88_mesh( # unknown elements # some examples have -1 for some teaching reasons to show some other stuff else: - FreeCAD.Console.PrintError("Unknown element\n") + Console.PrintError("Unknown element\n") return {} for n in nodes: - FreeCAD.Console.PrintLog(str(n) + " " + str(nodes[n]) + "\n") + Console.PrintLog(str(n) + " " + str(nodes[n]) + "\n") for e in elements_tria6: - FreeCAD.Console.PrintLog(str(e) + " " + str(elements_tria6[e]) + "\n") + Console.PrintLog(str(e) + " " + str(elements_tria6[e]) + "\n") FreeCAD.Console.PrintLog("\n") z88_mesh_file.close() @@ -429,7 +430,7 @@ def write( fem_mesh: a FemMesh""" if not fem_mesh.isDerivedFrom("Fem::FemMesh"): - FreeCAD.Console.PrintError("Not a FemMesh was given as parameter.\n") + Console.PrintError("Not a FemMesh was given as parameter.\n") return femnodes_mesh = fem_mesh.Nodes import femmesh.meshtools as FemMeshTools @@ -461,7 +462,7 @@ def write_z88_mesh_to_file( ): node_dof = 6 # schalenelemente else: - FreeCAD.Console.PrintError("Error: wrong z88_element_type.\n") + Console.PrintError("Error: wrong z88_element_type.\n") return node_count = len(femnodes_mesh) element_count = len(femelement_table) @@ -545,7 +546,7 @@ def write_z88_mesh_to_file( ) ) else: - FreeCAD.Console.PrintError( + Console.PrintError( "Writing of Z88 elementtype {0} not supported.\n".format(z88_element_type) ) # TODO support schale12 (made from prism15) and schale16 (made from hexa20) @@ -559,14 +560,14 @@ def get_z88_element_type( ): import femmesh.meshtools as FemMeshTools if not femmesh: - FreeCAD.Console.PrintMessage("Error: No femmesh!\n") + Console.PrintError("Error: No femmesh!") if not femelement_table: - FreeCAD.Console.PrintMessage("We need to get the femelement_table first!\n") + Console.PrintError("We need to get the femelement_table first!") femelement_table = FemMeshTools.get_femelement_table(femmesh) # in some cases lowest key in femelement_table is not [1] for elem in sorted(femelement_table): elem_length = len(femelement_table[elem]) - FreeCAD.Console.PrintLog("node count of first element: " + str(elem_length) + "\n") + Console.PrintLog("node count of first element: " + str(elem_length) + "\n") break # break after the first elem if FemMeshTools.is_solid_femmesh(femmesh): if femmesh.TetraCount == femmesh.VolumeCount: @@ -575,43 +576,43 @@ def get_z88_element_type( elif elem_length == 10: return 16 else: - FreeCAD.Console.PrintMessage("Tetra with neither 4 nor 10 nodes.\n") + Console.PrintMessage("Tetra with neither 4 nor 10 nodes.\n") elif femmesh.HexaCount == femmesh.VolumeCount: if elem_length == 8: return 1 elif elem_length == 20: return 10 else: - FreeCAD.Console.PrintMessage("Hexa with neither 8 nor 20 nodes.\n") + Console.PrintError("Hexa with neither 8 nor 20 nodes.\n") return 0 else: - FreeCAD.Console.PrintMessage("no tetra, no hexa or Mixed Volume Elements.\n") + Console.PrintError("no tetra, no hexa or Mixed Volume Elements.\n") elif FemMeshTools.is_face_femmesh(femmesh): if femmesh.TriangleCount == femmesh.FaceCount: if elem_length == 3: - FreeCAD.Console.PrintMessage("tria3mesh, not supported by Z88.\n") + Console.PrintError("tria3mesh, not supported by Z88.\n") return 0 elif elem_length == 6: return 24 else: - FreeCAD.Console.PrintMessage("Tria with neither 3 nor 6 nodes.\n") + Console.PrintError("Tria with neither 3 nor 6 nodes.\n") return 0 elif femmesh.QuadrangleCount == femmesh.FaceCount: if elem_length == 4: - FreeCAD.Console.PrintMessage("quad4mesh, not supported by Z88.\n") + Console.PrintError("quad4mesh, not supported by Z88.\n") return 0 elif elem_length == 8: return 23 else: - FreeCAD.Console.PrintMessage("Quad with neither 4 nor 8 nodes.\n") + Console.PrintError("Quad with neither 4 nor 8 nodes.\n") return 0 else: - FreeCAD.Console.PrintMessage("no tria, no quad\n") + Console.PrintError("no tria, no quad\n") return 0 elif FemMeshTools.is_edge_femmesh(femmesh): - FreeCAD.Console.PrintMessage("Edge femmesh will be exported as 3D truss element nr 4.\n") + Console.PrintMessage("Edge femmesh will be exported as 3D truss element nr 4.\n") return 4 else: - FreeCAD.Console.PrintMessage("Neither edge nor face nor solid femmesh.\n") + Console.PrintError("Neither edge nor face nor solid femmesh.\n") return 0 return 0 diff --git a/src/Mod/Fem/feminout/importZ88O2Results.py b/src/Mod/Fem/feminout/importZ88O2Results.py index e1d9662b22..8b597dc153 100644 --- a/src/Mod/Fem/feminout/importZ88O2Results.py +++ b/src/Mod/Fem/feminout/importZ88O2Results.py @@ -29,6 +29,7 @@ __url__ = "http://www.freecadweb.org" # \brief FreeCAD Z88 Disp Reader for FEM workbench import FreeCAD +from FreeCAD import Console import os @@ -99,7 +100,7 @@ def import_z88_disp( ) result_mesh_object.FemMesh = femmesh else: - FreeCAD.Console.PrintError("Z88 mesh file z88i1.txt not found!") + Console.PrintError("Z88 mesh file z88i1.txt not found!") # create result obj for result_set in disp_read["Results"]: @@ -118,7 +119,7 @@ def import_z88_disp( FreeCAD.ActiveDocument.recompute() else: - FreeCAD.Console.PrintError( + Console.PrintError( "Problem on Z88 result file import. No nodes found in Z88 result file.\n" ) return res_obj @@ -145,7 +146,6 @@ def read_z88_disp( if lno >= 6: # disp line - # print(linelist) node_no = int(linelist[0]) mode_disp_x = float(linelist[1]) mode_disp_y = float(linelist[2]) @@ -160,7 +160,7 @@ def read_z88_disp( results.append(mode_results) for r in results[0]["disp"]: - FreeCAD.Console.PrintLog("{} --> {}\n".format(r, results[0]["disp"][r])) + Console.PrintLog("{} --> {}\n".format(r, results[0]["disp"][r])) z88_disp_file.close() return {"Nodes": nodes, "Results": results} diff --git a/src/Mod/Fem/feminout/readFenicsXDMF.py b/src/Mod/Fem/feminout/readFenicsXDMF.py index 3cc59311bb..4a6ed32517 100644 --- a/src/Mod/Fem/feminout/readFenicsXDMF.py +++ b/src/Mod/Fem/feminout/readFenicsXDMF.py @@ -28,12 +28,12 @@ __url__ = "http://www.freecadweb.org" # \ingroup FEM # \brief FreeCAD Fenics Mesh XDMF reader for FEM workbench -import FreeCAD +from FreeCAD import Console def read_fenics_mesh_xdmf(xdmffilename): - FreeCAD.Console.PrintMessage("Not operational, yet\n") + Console.PrintMessage("Not operational, yet\n") return { "Nodes": {}, diff --git a/src/Mod/Fem/feminout/readFenicsXML.py b/src/Mod/Fem/feminout/readFenicsXML.py index 9afa651086..3db4ed21c2 100644 --- a/src/Mod/Fem/feminout/readFenicsXML.py +++ b/src/Mod/Fem/feminout/readFenicsXML.py @@ -19,7 +19,6 @@ # * USA * # * * # *************************************************************************** -from __future__ import print_function __title__ = "FreeCAD Fenics XML mesh reader" __author__ = "Johannes Hartung" @@ -31,6 +30,7 @@ __url__ = "http://www.freecadweb.org" import FreeCAD +from FreeCAD import Console from xml.etree import ElementTree as ET import itertools @@ -58,8 +58,8 @@ def read_fenics_mesh_xml(xmlfilename): vertex_size = 0 - print("Mesh dimension: %d" % (dim,)) - print("Mesh cell type: %s" % (cell_type,)) + Console.PrintLog("Mesh dimension: %d\n" % (dim,)) + Console.PrintLog("Mesh cell type: %s\n" % (cell_type,)) # every cell type contains a dict with key=dimension and value=number @@ -77,10 +77,10 @@ def read_fenics_mesh_xml(xmlfilename): cell_dict = {} if find_vertices is None: - print("No vertices found!") + Console.PrintWarning("No vertices found!\n") else: vertex_size = int(find_vertices.attrib.get("size")) - print("Reading %d vertices" % (vertex_size,)) + Console.PrintLog("Reading %d vertices\n" % (vertex_size,)) for vertex in find_vertices: ind = int(vertex.get("index")) @@ -94,18 +94,18 @@ def read_fenics_mesh_xml(xmlfilename): # increase node index by one, since fenics starts at 0, FreeCAD at 1 # print("%d %f %f %f" % (ind, node_x, node_y, node_z)) else: - print("found strange vertex tag: %s" % (vertex.tag,)) + Console.PrintWarning("found strange vertex tag: %s\n" % (vertex.tag,)) if find_cells is None: - print("No cells found!") + Console.PrintWarning("No cells found!\n") else: - print("Reading %d cells" % (int(find_cells.attrib.get("size")),)) + Console.PrintLog("Reading %d cells\n" % (int(find_cells.attrib.get("size")),)) for cell in find_cells: ind = int(cell.get("index")) if cell.tag.lower() != cell_type.lower(): - print( - "Strange mismatch between cell type {} and cell tag {}" + Console.PrintWarning( + "Strange mismatch between cell type {} and cell tag {}\n" .format(cell_type, cell.tag.lower()) ) num_vertices = cells_parts_dim[cell_type][0] @@ -232,23 +232,23 @@ def read_fenics_mesh_xml(xmlfilename): root = tree.getroot() if root.tag.lower() != "dolfin": - print("Strange root tag, should be dolfin!") + Console.PrintWarning("Strange root tag, should be dolfin!\n") find_mesh = root.find("mesh") if find_mesh is not None: # these are consistency checks of the XML structure - print("Mesh found") + Console.PrintMessage("Mesh found\n") (nodes, cells_dict, cell_type, dim) = read_mesh_block(find_mesh) element_dict = generate_lower_dimensional_structures(nodes, cells_dict, cell_type, dim) - print("Show min max element dict") + Console.PrintMessage("Show min max element dict") for (elm, numbers) in list(element_dict.items()): lst = sorted(list(numbers.items()), key=lambda x: x[0]) if lst != []: - print(elm, " min: ", lst[0], " max: ", lst[-1]) + Console.PrintWarning(elm, " min: ", lst[0], " max: ", lst[-1], "\n") else: - print("No mesh found") + Console.PrintError("No mesh found") if root.find("data") is not None: - print("Internal mesh data found") + Console.PrintLog("Internal mesh data found\n") return { "Nodes": nodes, diff --git a/src/Mod/Fem/feminout/writeFenicsXDMF.py b/src/Mod/Fem/feminout/writeFenicsXDMF.py index ce59c2ddb5..db8099eb0b 100644 --- a/src/Mod/Fem/feminout/writeFenicsXDMF.py +++ b/src/Mod/Fem/feminout/writeFenicsXDMF.py @@ -28,6 +28,7 @@ __url__ = "http://www.freecadweb.org" # \ingroup FEM # \brief FreeCAD Fenics Mesh XDMF writer for FEM workbench +from FreeCAD import Console from .importToolsFem import \ get_FemMeshObjectDimension,\ get_FemMeshObjectElementTypes,\ @@ -168,7 +169,10 @@ def write_fenics_mesh_codim_xdmf( fc_topo = fem_mesh_obj.FemMesh.Nodes else: fc_topo = [] - print("Dimension of mesh incompatible with export XDMF function: %d" % (dim_topo,)) + Console.PrintError( + "Dimension of mesh incompatible with export XDMF function: %d\n" + % (dim_topo,) + ) nodeindices = [( nodes_dict[ind] for ind in fem_mesh_obj.FemMesh.getElementNodes(fc_topo_ind) @@ -271,16 +275,16 @@ def write_fenics_mesh_xdmf( "Prism": "unknown", "Pyramid": "unknown", } - print("Converting " + fem_mesh_obj.Label + " to fenics XDMF File") - print("Dimension of mesh: %d" % (get_FemMeshObjectDimension(fem_mesh_obj),)) + Console.PrintMessage("Converting " + fem_mesh_obj.Label + " to fenics XDMF File\n") + Console.PrintMessage("Dimension of mesh: %d\n" % (get_FemMeshObjectDimension(fem_mesh_obj),)) elements_in_mesh = get_FemMeshObjectElementTypes(fem_mesh_obj) - print("Elements appearing in mesh: %s" % (str(elements_in_mesh),)) + Console.PrintMessage("Elements appearing in mesh: %s\n" % (str(elements_in_mesh),)) celltype_in_mesh = get_MaxDimElementFromList(elements_in_mesh) (num_cells, cellname_fc, dim_cell) = celltype_in_mesh cellname_fenics = FreeCAD_to_Fenics_dict[cellname_fc] - print( - "Celltype in mesh -> {} and its Fenics dolfin name: {}" + Console.PrintMessage( + "Celltype in mesh -> {} and its Fenics dolfin name: {}\n" .format(celltype_in_mesh, cellname_fenics) ) @@ -313,15 +317,17 @@ def write_fenics_mesh_xdmf( gmshgroups = get_FemMeshObjectMeshGroups(fem_mesh_obj) if gmshgroups is not (): - print("found mesh groups") + Console.PrintMessage("found mesh groups\n") for g in gmshgroups: mesh_function_type = fem_mesh.getGroupElementType(g) mesh_function_codim = dim_cell - FreeCAD_Group_Dimensions[mesh_function_type] mesh_function_name = fem_mesh.getGroupName(g) - print("group id: %d (label: %s) with element type %s and codim %d" - % (g, mesh_function_name, mesh_function_type, mesh_function_codim)) + Console.PrintMessage( + "group id: %d (label: %s) with element type %s and codim %d\n" + % (g, mesh_function_name, mesh_function_type, mesh_function_codim) + ) mesh_function_grid = ET.SubElement( domain, "Grid", diff --git a/src/Mod/Fem/feminout/writeFenicsXML.py b/src/Mod/Fem/feminout/writeFenicsXML.py index ea5c7940d1..920d45aa0f 100644 --- a/src/Mod/Fem/feminout/writeFenicsXML.py +++ b/src/Mod/Fem/feminout/writeFenicsXML.py @@ -19,7 +19,6 @@ # * USA * # * * # *************************************************************************** -from __future__ import print_function __title__ = "FreeCAD Fenics XML mesh writer" __author__ = "Johannes Hartung" @@ -30,6 +29,7 @@ __url__ = "http://www.freecadweb.org" # \brief FreeCAD Fenics Mesh XML writer for FEM workbench +from FreeCAD import Console from .importToolsFem import get_FemMeshObjectDimension from .importToolsFem import get_FemMeshObjectElementTypes from .importToolsFem import get_MaxDimElementFromList @@ -68,17 +68,18 @@ def write_fenics_mesh_xml(fem_mesh_obj, outputfile): "hexahedron": 8 } - print("Converting " + fem_mesh_obj.Label + " to fenics XML File") - print("Dimension of mesh: %d" % (get_FemMeshObjectDimension(fem_mesh_obj),)) + Console.Message("Converting " + fem_mesh_obj.Label + " to fenics XML File\n") + Console.Message("Dimension of mesh: %d\n" % (get_FemMeshObjectDimension(fem_mesh_obj),)) elements_in_mesh = get_FemMeshObjectElementTypes(fem_mesh_obj) - print("Elements appearing in mesh: %s" % (str(elements_in_mesh),)) + Console.Message("Elements appearing in mesh: %s" % (str(elements_in_mesh),)) celltype_in_mesh = get_MaxDimElementFromList(elements_in_mesh) (num_cells, cellname_fc, dim_cell) = celltype_in_mesh cellname_fenics = FreeCAD_to_Fenics_dict[cellname_fc] num_verts_cell = XML_Number_of_Nodes_dict[cellname_fenics] - print( - "Celltype in mesh -> %s and its Fenics name: %s" % (str(celltype_in_mesh), cellname_fenics) + Console.Message( + "Celltype in mesh -> %s and its Fenics name: %s\n" + % (str(celltype_in_mesh), cellname_fenics) ) root = ET.Element("dolfin", dolfin="http://fenicsproject.org") diff --git a/src/Mod/Fem/femmesh/gmshtools.py b/src/Mod/Fem/femmesh/gmshtools.py index 70e039e765..54ebc6e231 100644 --- a/src/Mod/Fem/femmesh/gmshtools.py +++ b/src/Mod/Fem/femmesh/gmshtools.py @@ -31,6 +31,7 @@ import sys import subprocess import FreeCAD +from FreeCAD import Console import Fem from FreeCAD import Units from . import meshtools @@ -73,7 +74,7 @@ class GmshTools(): elif self.order == "2nd": self.order = "2" else: - print("Error in order") + Console.PrintError("Error in order\n") # dimension self.dimension = self.mesh_obj.ElementDimension @@ -160,15 +161,15 @@ class GmshTools(): return error def start_logs(self): - print("\nGmsh FEM mesh run is being started.") - print(" Part to mesh: Name --> {}, Label --> {}, ShapeType --> {}".format( + Console.PrintLog("\nGmsh FEM mesh run is being started.\n") + Console.PrintLog(" Part to mesh: Name --> {}, Label --> {}, ShapeType --> {}\n".format( self.part_obj.Name, self.part_obj.Label, self.part_obj.Shape.ShapeType )) - print(" CharacteristicLengthMax: {}".format(self.clmax)) - print(" CharacteristicLengthMin: {}".format(self.clmin)) - print(" ElementOrder: {}".format(self.order)) + Console.PrintLog(" CharacteristicLengthMax: {}\n".format(self.clmax)) + Console.PrintLog(" CharacteristicLengthMin: {}\n".format(self.clmin)) + Console.PrintLog(" ElementOrder: {}\n".format(self.order)) def get_dimension(self): # Dimension @@ -188,18 +189,18 @@ class GmshTools(): self.dimension = "1" elif shty == "Vertex": # print("Found: " + shty) - FreeCAD.Console.PrintError("You can not mesh a Vertex.\n") + Console.PrintError("You can not mesh a Vertex.\n") self.dimension = "0" elif shty == "Compound": # print(" Found a " + shty) - FreeCAD.Console.PrintLog( + Console.PrintLog( " Found a Compound. Since it could contain" "any kind of shape dimension 3 is used.\n" ) self.dimension = "3" # dimension 3 works for 2D and 1d shapes as well else: self.dimension = "0" - FreeCAD.Console.PrintError( + Console.PrintError( "Could not retrieve Dimension from shape type. Please choose dimension." ) elif self.dimension == "3D": @@ -209,8 +210,8 @@ class GmshTools(): elif self.dimension == "1D": self.dimension = "1" else: - print("Error in dimension") - print(" ElementDimension: " + self.dimension) + Console.PrintError("Error in dimension\n") + Console.PrintMessage(" ElementDimension: " + self.dimension + "\n") def get_tmp_file_paths(self, param_working_dir=None, create=False): self.working_dir = "" @@ -219,7 +220,7 @@ class GmshTools(): self.working_dir = param_working_dir if femutils.check_working_dir(self.working_dir) is not True: if create is True: - FreeCAD.Console.PrintMessage( + Console.PrintMessage( "Dir given as parameter \'{}\' doesn't exist, " "but parameter to create it is set to True. " "Dir will be created.\n".format(self.working_dir) @@ -227,13 +228,13 @@ class GmshTools(): from os import mkdir mkdir(param_working_dir) else: - FreeCAD.Console.PrintError( + Console.PrintError( "Dir given as parameter \'{}\' doesn't exist " "and create parameter is set to False.\n" .format(self.working_dir) ) self.working_dir = femutils.get_pref_working_dir(self.mesh_obj) - FreeCAD.Console.PrintMessage( + Console.PrintMessage( "Dir \'{}\' will be used instead.\n" .format(self.working_dir) ) @@ -242,12 +243,12 @@ class GmshTools(): # check working_dir exist, if not use a tmp dir and inform the user if femutils.check_working_dir(self.working_dir) is not True: - FreeCAD.Console.PrintError( + Console.PrintError( "Dir \'{}\' doesn't exist or cannot be created.\n" .format(self.working_dir) ) self.working_dir = femutils.get_temp_dir(self.mesh_obj) - FreeCAD.Console.PrintMessage( + Console.PrintMessage( "Dir \'{}\' will be used instead.\n" .format(self.working_dir) ) @@ -259,9 +260,9 @@ class GmshTools(): self.temp_file_geometry = join(self.working_dir, _geometry_name + ".brep") # geometry file self.temp_file_mesh = join(self.working_dir, self.mesh_name + ".unv") # mesh file self.temp_file_geo = join(self.working_dir, "shape2mesh.geo") # Gmsh input file - print(" " + self.temp_file_geometry) - print(" " + self.temp_file_mesh) - print(" " + self.temp_file_geo) + Console.PrintMessage(" " + self.temp_file_geometry + "\n") + Console.PrintMessage(" " + self.temp_file_mesh + "\n") + Console.PrintMessage(" " + self.temp_file_geo + "\n") def get_gmsh_command(self): from platform import system @@ -288,7 +289,7 @@ class GmshTools(): "Please install Gmsh or set path to binary " "in FEM preferences tab Gmsh.\n" ) - FreeCAD.Console.PrintError(error_message) + Console.PrintError(error_message) raise Exception(error_message) self.gmsh_bin = gmsh_path else: @@ -296,7 +297,7 @@ class GmshTools(): "No standard location implemented for your operating system. " "Set GMHS binary path in FEM preferences.\n" ) - FreeCAD.Console.PrintError(error_message) + Console.PrintError(error_message) raise Exception(error_message) else: if not self.gmsh_bin: @@ -310,7 +311,7 @@ class GmshTools(): self.gmsh_bin = FreeCAD.getHomePath() + "bin/gmsh.exe" else: self.gmsh_bin = "gmsh" - print(" " + self.gmsh_bin) + Console.PrintMessage(" " + self.gmsh_bin + "\n") def get_group_data(self): # TODO: solids, faces, edges and vertexes don't seem to work together in one group, @@ -321,21 +322,21 @@ class GmshTools(): # print(" No mesh group objects.") pass else: - print(" Mesh group objects, we need to get the elements.") + Console.PrintMessage(" Mesh group objects, we need to get the elements.\n") for mg in self.mesh_obj.MeshGroupList: new_group_elements = meshtools.get_mesh_group_elements(mg, self.part_obj) for ge in new_group_elements: if ge not in self.group_elements: self.group_elements[ge] = new_group_elements[ge] else: - FreeCAD.Console.PrintError(" A group with this name exists already.\n") + Console.PrintError(" A group with this name exists already.\n") # group meshing for analysis analysis_group_meshing = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Fem/General" ).GetBool("AnalysisGroupMeshing", False) if self.analysis and analysis_group_meshing: - print(" Group meshing for analysis.") + Console.PrintMessage(" Group meshing for analysis.\n") self.group_nodes_export = True new_group_elements = meshtools.get_analysis_group_elements( self.analysis, @@ -345,12 +346,12 @@ class GmshTools(): if ge not in self.group_elements: self.group_elements[ge] = new_group_elements[ge] else: - FreeCAD.Console.PrintError(" A group with this name exists already.\n") + Console.PrintError(" A group with this name exists already.\n") else: - print(" No Group meshing for analysis.") + Console.PrintMessage(" No Group meshing for analysis.\n") if self.group_elements: - print(" {}".format(self.group_elements)) + Console.PrintMessage(" {}\n".format(self.group_elements)) def get_region_data(self): # mesh regions @@ -358,7 +359,7 @@ class GmshTools(): # print(" No mesh regions.") pass else: - print(" Mesh regions, we need to get the elements.") + Console.PrintMessage(' Mesh regions, we need to get the elements.\n') # by the use of MeshRegion object and a BooleanSplitCompound # there could be problems with node numbers see # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467 @@ -377,7 +378,7 @@ class GmshTools(): "It is strongly recommended to extract the shape to mesh " "from the Compound and use this one." ) - FreeCAD.Console.PrintError(error_message + "\n") + Console.PrintError(error_message + "\n") # TODO: no gui popup because FreeCAD will be in a endless output loop # as long as the pop up is on --> maybe find a better solution for # either of both --> thus the pop up is in task panel @@ -394,7 +395,7 @@ class GmshTools(): # if not try to find the element in the shape to mesh search_ele_in_shape_to_mesh = False if not self.part_obj.Shape.isSame(sub[0].Shape): - FreeCAD.Console.PrintLog( + Console.PrintLog( " One element of the meshregion {} is " "not an element of the Part to mesh.\n" "But we are going to try to find it in " @@ -416,7 +417,7 @@ class GmshTools(): if found_element: elems = found_element else: - FreeCAD.Console.PrintError( + Console.PrintError( "One element of the meshregion {} could not be found " "in the Part to mesh. It will be ignored.\n" .format(mr_obj.Name) @@ -427,19 +428,19 @@ class GmshTools(): mr_obj.CharacteristicLength ).Value else: - FreeCAD.Console.PrintError( + Console.PrintError( "The element {} of the meshregion {} has " "been added to another mesh region.\n" .format(elems, mr_obj.Name) ) else: - FreeCAD.Console.PrintError( + Console.PrintError( "The meshregion: {} is not used to create the mesh " "because the reference list is empty.\n" .format(mr_obj.Name) ) else: - FreeCAD.Console.PrintError( + Console.PrintError( "The meshregion: {} is not used to create the " "mesh because the CharacteristicLength is 0.0 mm.\n" .format(mr_obj.Name) @@ -449,8 +450,8 @@ class GmshTools(): ele_shape = meshtools.get_element(self.part_obj, eleml) ele_vertexes = meshtools.get_vertexes_by_element(self.part_obj.Shape, ele_shape) self.ele_node_map[eleml] = ele_vertexes - print(" {}".format(self.ele_length_map)) - print(" {}".format(self.ele_node_map)) + Console.PrintMessage(" {}\n".format(self.ele_length_map)) + Console.PrintMessage(" {}\n".format(self.ele_node_map)) def get_boundary_layer_data(self): # mesh boundary layer @@ -462,7 +463,7 @@ class GmshTools(): # print(" No mesh boundary layer setting document object.") pass else: - print(" Mesh boundary layers, we need to get the elements.") + Console.PrintMessage(" Mesh boundary layers, we need to get the elements.\n") if self.part_obj.Shape.ShapeType == "Compound": # see http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467 and # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&p=149520#p149520 @@ -471,7 +472,7 @@ class GmshTools(): "It is strongly recommended to extract the shape to mesh " "from the Compound and use this one." ) - FreeCAD.Console.PrintError(err + "\n") + Console.PrintError(err + "\n") for mr_obj in self.mesh_obj.MeshBoundaryLayerList: if mr_obj.MinimumThickness and Units.Quantity(mr_obj.MinimumThickness).Value > 0: if mr_obj.References: @@ -483,7 +484,7 @@ class GmshTools(): # if not try to find the element in the shape to mesh search_ele_in_shape_to_mesh = False if not self.part_obj.Shape.isSame(sub[0].Shape): - FreeCAD.Console.PrintLog( + Console.PrintLog( " One element of the mesh boundary layer {} is " "not an element of the Part to mesh.\n" "But we are going to try to find it in " @@ -505,7 +506,7 @@ class GmshTools(): if found_element: # also elems = found_element else: - FreeCAD.Console.PrintError( + Console.PrintError( "One element of the mesh boundary layer {} could " "not be found in the Part to mesh. " "It will be ignored.\n" @@ -518,7 +519,7 @@ class GmshTools(): belem_list.append(elems) self.bl_boundary_list.append(elems) else: - FreeCAD.Console.PrintError( + Console.PrintError( "The element {} of the mesh boundary " "layer {} has been added " "to another mesh boundary layer.\n" @@ -550,23 +551,23 @@ class GmshTools(): elif self.dimension == "3": setting["FacesList"] = belem_list else: - FreeCAD.Console.PrintError( + Console.PrintError( "boundary layer is only supported for 2D and 3D mesh" ) self.bl_setting_list.append(setting) else: - FreeCAD.Console.PrintError( + Console.PrintError( "The mesh boundary layer: {} is not used to create " "the mesh because the reference list is empty.\n" .format(mr_obj.Name) ) else: - FreeCAD.Console.PrintError( + Console.PrintError( "The mesh boundary layer: {} is not used to create " "the mesh because the min thickness is 0.0 mm.\n" .format(mr_obj.Name) ) - print(" {}".format(self.bl_setting_list)) + Console.PrintMessage(" {}\n".format(self.bl_setting_list)) def write_groups(self, geo): if self.group_elements: @@ -612,7 +613,7 @@ class GmshTools(): # currently single body is supported if len(self.bl_setting_list): geo.write("// boundary layer setting\n") - print(" Start to write boundary layer setup") + Console.PrintMessage(" Start to write boundary layer setup\n") field_number = 1 for item in self.bl_setting_list: prefix = "Field[" + str(field_number) + "]" @@ -629,13 +630,13 @@ class GmshTools(): else: line = prefix + "." + str(k) + " = " + str(v) + ";\n" geo.write(line) - print(line) + Console.PrintMessage("{}\n".format(line)) geo.write("BoundaryLayer Field = " + str(field_number) + ";\n") geo.write("// end of this boundary layer setup \n") field_number += 1 geo.write("\n") geo.flush() - print(" finished in boundary layer setup") + Console.PrintMessage(" finished in boundary layer setup\n") else: # print(" no boundary layer setup is found for this mesh") geo.write("// no boundary layer settings for this mesh\n") @@ -811,7 +812,7 @@ class GmshTools(): # print(error) except: error = "Error executing: {}\n".format(" ".join(comandlist)) - FreeCAD.Console.PrintError(error) + Console.PrintError(error) self.error = True return error @@ -819,9 +820,9 @@ class GmshTools(): if not self.error: fem_mesh = Fem.read(self.temp_file_mesh) self.mesh_obj.FemMesh = fem_mesh - FreeCAD.Console.PrintMessage(" The Part should have a pretty new FEM mesh!\n") + Console.PrintMessage(" The Part should have a pretty new FEM mesh!\n") else: - FreeCAD.Console.PrintError("No mesh was created.\n") + Console.PrintError("No mesh was created.\n") ## @} diff --git a/src/Mod/Fem/femsolver/elmer/writer.py b/src/Mod/Fem/femsolver/elmer/writer.py index 469300496e..e02537056c 100644 --- a/src/Mod/Fem/femsolver/elmer/writer.py +++ b/src/Mod/Fem/femsolver/elmer/writer.py @@ -31,8 +31,8 @@ import os.path import subprocess import tempfile -import FreeCAD from FreeCAD import Units +from FreeCAD import Console import Fem import femtools.femutils as femutils import femmesh.gmshtools as gmshtools @@ -125,7 +125,7 @@ class Writer(object): groups.extend(self._builder.getBoundaryNames()) self._exportToUnv(groups, mesh, unvPath) if self.testmode: - FreeCAD.Console.PrintMessage("We are in testmode ElmerGrid may not be installed.\n") + Console.PrintMessage("We are in testmode ElmerGrid may not be installed.\n") else: binary = settings.get_binary("ElmerGrid") if binary is None: @@ -165,7 +165,7 @@ class Writer(object): tools.write_part_file() tools.write_geo() if self.testmode: - FreeCAD.Console.PrintMessage("We are in testmode, Gmsh may not be installed.\n") + Console.PrintMessage("We are in testmode, Gmsh may not be installed.\n") import shutil shutil.copyfile(geoPath, os.path.join(self.directory, "group_mesh.geo")) else: From 688a6ddf058ed9ec1283d08ba4cbcb16f230e893 Mon Sep 17 00:00:00 2001 From: Markus Hovorka Date: Mon, 23 Sep 2019 21:16:53 +0200 Subject: [PATCH 09/10] FEM: Add documentation to setting module --- src/Mod/Fem/femsolver/run.py | 27 ++-- src/Mod/Fem/femsolver/settings.py | 220 +++++++++++++++++++----------- 2 files changed, 151 insertions(+), 96 deletions(-) diff --git a/src/Mod/Fem/femsolver/run.py b/src/Mod/Fem/femsolver/run.py index 0e2f8dc4de..ed63130fc2 100644 --- a/src/Mod/Fem/femsolver/run.py +++ b/src/Mod/Fem/femsolver/run.py @@ -124,15 +124,15 @@ def _isPathValid(m, path): setting = settings.get_dir_setting() if path is not None: return t is None and m.directory == path - if setting == settings.BESIDE: - if t == settings.BESIDE: + if setting == settings.DirSetting.BESIDE: + if t == settings.DirSetting.BESIDE: base = os.path.split(m.directory.rstrip("/"))[0] return base == femutils.get_beside_base(m.solver) return False - if setting == settings.TEMPORARY: - return t == settings.TEMPORARY - if setting == settings.CUSTOM: - if t == settings.CUSTOM: + if setting == settings.DirSetting.TEMPORARY: + return t == settings.DirSetting.TEMPORARY + if setting == settings.DirSetting.CUSTOM: + if t == settings.DirSetting.CUSTOM: firstBase = os.path.split(m.directory.rstrip("/"))[0] customBase = os.path.split(firstBase)[0] return customBase == femutils.get_custom_base(m.solver) @@ -393,17 +393,11 @@ class _DocObserver(object): def _deleteMachine(self, obj): m = _machines[obj] t = _dirTypes[m.directory] - - def delegate(): - m.join() - if t == settings.TEMPORARY: - shutil.rmtree(m.directory) - del _dirTypes[m.directory] - del _machines[obj] m.abort() - thread = threading.Thread(target=delegate) - thread.daemon = False - thread.start() + if t == settings.DirSetting.TEMPORARY: + shutil.rmtree(m.directory) + del _machines[obj] + del _dirTypes[m.directory] def _checkEquation(self, obj): for o in obj.Document.Objects: @@ -456,5 +450,4 @@ class _DocObserver(object): return True return False - ## @} diff --git a/src/Mod/Fem/femsolver/settings.py b/src/Mod/Fem/femsolver/settings.py index 7b3621fde8..48b4f685c4 100644 --- a/src/Mod/Fem/femsolver/settings.py +++ b/src/Mod/Fem/femsolver/settings.py @@ -19,28 +19,58 @@ # * USA * # * * # *************************************************************************** +""" Query FEM specific settings including solver settings. + +Query settings from the hierarchically organized settings/parameter system of +FreeCAD related to the FEM module. The collection of independed functions use +the settings system as a backend and expose a easy to use interface for other +modules of the FEM module. + +Functions quering solver specific settings always take a solver name as a +string to identify the solver in question. At the moment the following solvers +are supported: + + - Calculix + - ElmerSolver + - Z88 + +To query settings about those solver the solver name must be given exactely in +the form written in the list above. To make the solver recognize settings for a +new solver have a look at :class:`_SolverDlg`. +""" __title__ = "FreeCAD FEM solver settings" __author__ = "Markus Hovorka, Bernd Hahnebach" __url__ = "http://www.freecadweb.org" -## \addtogroup FEM -# @{ - -""" -parameter in FreeCAD can be edited in two ways, either in the -Preferences: menu Edit --> Preferences -or -Parameter editor: menu Tools --> Edit parameter -""" import FreeCAD -# working directory: possible choices -TEMPORARY = "temporary" -BESIDE = "beside" -CUSTOM = "custom" +class DirSetting: + """ Enum of possible directory setting values. + + Strings used to indicate the solver directory setting set in FreeCADs + setting system. Returned by :func:`get_dir_setting` for that purpose. There + are three different possible values: + + :cvar TEMPORARY: + Let FreeCAD manage (create, delete) the working directories for all + solver. Use temporary directories. + + :cvar BESIDE: + Create a directory in the same folder in which the FCStd file of the + document is located. Use Subfolder for each solver (e.g. for a file + ./mydoc.FCStd and a solver with the label Elmer002 use + ./mydoc/Elmer002). + + :cvar CUSTOM: + Use directory set below. Create own subdirectory for every solver. Name + directory after the solver label prefixed with the document name. + """ + TEMPORARY = "temporary" + BESIDE = "beside" + CUSTOM = "custom" # FEM parameter location path @@ -48,26 +78,117 @@ _PARAM_PATH = "User parameter:BaseApp/Preferences/Mod/Fem/" _GENERAL_PARAM = _PARAM_PATH + "General" -# ******** binary parameter ********************************************************************** +def get_binary(name): + """ Find binary of solver *name* honoring user settings. + + Return the specific path set by the user in FreeCADs settings/parameter + system if set or the default binary name if no specific path is set. If no + path was found because the solver *name* isn't supported ``None`` is + returned. This method does not check whether the binary actually exists + and is callable. + + :param name: solver id as a ``str`` (see :mod:`femsolver.settings`) + """ + if name in _SOLVER_PARAM: + binary = _SOLVER_PARAM[name].get_binary() + FreeCAD.Console.PrintMessage('Solver binary path: {} \n'.format(binary)) + return binary + else: + FreeCAD.Console.PrintError( + 'Settings solver name: {} not found in ' + 'solver settings modules _SOLVER_PARAM dirctionary.\n' + .format(name) + ) + return None + + +def get_write_comments(name): + """ Check whether "write_comments" is set for solver. + + Returns ``True`` if the "write_comments" setting/parameter is set for the + solver with the id *name*. Returns ``False`` otherwise. If the solver isn't + supported ``None`` is returned. + + :param name: solver id as a ``str`` (see :mod:`femsolver.settings`) + """ + if name in _SOLVER_PARAM: + return _SOLVER_PARAM[name].get_write_comments() + else: + FreeCAD.Console.PrintError( + 'Settings solver name: {} not found in ' + 'solver settings modules _SOLVER_PARAM dirctionary.\n' + .format(name) + ) + return None + + +def get_custom_dir(): + """ Get value for :term:`General/CustomDirectoryPath` parameter. """ + param_group = FreeCAD.ParamGet(_GENERAL_PARAM) + return param_group.GetString("CustomDirectoryPath") + + +def get_dir_setting(): + """ Return directory setting set by the user. + + Return one of the three possible values of the :class:`DirSetting` enum + depending on the setting set in FreeCAD parameter system. Result dependes + on the values of :term:`General/UseTempDirectory`, + :term:`General/UseBesideDirectory` and :term:`General/UseCustomDirectory`. + """ + param_group = FreeCAD.ParamGet(_GENERAL_PARAM) + if param_group.GetBool("UseBesideDirectory"): + return DirSetting.BESIDE + elif param_group.GetBool("UseCustomDirectory"): + return DirSetting.CUSTOM + return DirSetting.TEMPORARY + + class _SolverDlg(object): + """ Internal query logic for solver specific settings. + + Each instance queries settings for one specific solver (e.g. Elmer) common + among all solvers. To clearify: There are a few settings that are useful + for every solver (e.g. where to find the solver binary) but the value and + the FreeCAD parameter path is different for each one. A instance of this + class contains all the solver specific paths needed. The settings can be + queried via the methods which use those path members to query the value for + the specific solver. + + :ivar default: + Default binary name as a string preferably without a prefix path to + make it more generic (e.g. "ccx"). This only works if the binary can be + found via the PATH environment variable on linux or similar mechanisms + on other operating systems. Used if nothing else is specified by the + user. + + :ivar param_path: + Parent param path (FreeCADs settings/parameter system) that contains + all settings for the specific solver. + + :ivar use_default: + Param path identifying the "use_default" setting. Only specifie the + last part as the *param_path* is prepended to this value. + + :ivar custom_path: + Param path identifying the "custom_path" setting. Only specifie the + last part as the *param_path* is prepended to this value. + """ + + WRITE_COMMENTS_PARAM = "writeCommentsToInputFile" def __init__(self, default, param_path, use_default, custom_path): - - # set the parameter identifier self.default = default self.param_path = param_path self.use_default = use_default self.custom_path = custom_path - self.write_comments = "writeCommentsToInputFile" - # get the parameter object where the paramete are saved in self.param_group = FreeCAD.ParamGet(self.param_path) def get_binary(self): # set the binary path to the FreeCAD defaults # ATM pure unix shell commands without path names are used - # TODO see todo on use_default later in this module binary = self.default FreeCAD.Console.PrintLog("Solver binary path: {} \n".format(binary)) @@ -82,24 +203,9 @@ class _SolverDlg(object): return find_bin(binary) def get_write_comments(self): - return self.param_group.GetBool(self.write_comments, True) + return self.param_group.GetBool(self.WRITE_COMMENTS_PARAM, True) -""" -default: - default command to run the binary - this one is taken if the UseStandardXXXLocationis not given or set to True -param: - path where these settings are saved, in FEM normally one path in one Tab in Preferences GUI -use_default: - the UseStandardXXXLocation parameter identifier - if this parameter is set to True FreeCAD standards - for the binary are usedor FreeCAD tries to find the binary - TODO: see method setup_ccx in ccx tools module, which sets up ccx binary for various os -custom_path: - the xxxBinaryPath parameter identifier - binary path given by the user -""" _SOLVER_PARAM = { "Calculix": _SolverDlg( default="ccx", @@ -122,47 +228,3 @@ _SOLVER_PARAM = { use_default="UseStandardZ88Location", custom_path="z88BinaryPath"), } - - -def get_binary(name): - if name in _SOLVER_PARAM: - binary = _SOLVER_PARAM[name].get_binary() - FreeCAD.Console.PrintMessage("Solver binary path: {} \n".format(binary)) - return binary - else: - FreeCAD.Console.PrintError( - "Settings solver name: {} not found in " - "solver settings modules _SOLVER_PARAM dirctionary.\n" - .format(name) - ) - return None - - -def get_write_comments(name): - if name in _SOLVER_PARAM: - return _SOLVER_PARAM[name].get_write_comments() - else: - FreeCAD.Console.PrintError( - "Settings solver name: {} not found in " - "solver settings modules _SOLVER_PARAM dirctionary.\n" - .format(name) - ) - return None - - -# ******** working directory parameter *********************************************************** -def get_custom_dir(): - param_group = FreeCAD.ParamGet(_GENERAL_PARAM) - return param_group.GetString("CustomDirectoryPath") - - -def get_dir_setting(): - param_group = FreeCAD.ParamGet(_GENERAL_PARAM) - if param_group.GetBool("UseBesideDirectory"): - return BESIDE - elif param_group.GetBool("UseCustomDirectory"): - return CUSTOM - return TEMPORARY - - -## @} From 44833137b743e2af6cbfdaaa5baf9e64d697bd2a Mon Sep 17 00:00:00 2001 From: Markus Hovorka Date: Mon, 23 Sep 2019 21:16:55 +0200 Subject: [PATCH 10/10] FEM: Add documentation to run module --- src/Mod/Fem/femsolver/run.py | 56 +++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/src/Mod/Fem/femsolver/run.py b/src/Mod/Fem/femsolver/run.py index ed63130fc2..c7e4815b24 100644 --- a/src/Mod/Fem/femsolver/run.py +++ b/src/Mod/Fem/femsolver/run.py @@ -18,14 +18,21 @@ # * USA * # * * # *************************************************************************** +""" Execute Solver and obtain Reports and Results. + +Integral part of the Solver Framework which contains components responsible for +executing the solver in the background. Also provides an asynchronous +communication system with the solver running in the background. The purpose of +this module is to be as generic as possible. It can execute every solver +supported by the fem workbench. The threading and communication support is +mainly implemented by the :mod:`femsolver.task` and :mod:`femsolver.signal` +modules. +""" __title__ = "FreeCAD FEM solver run" __author__ = "Markus Hovorka" __url__ = "http://www.freecadweb.org" -## \addtogroup FEM -# @{ - import os import os.path import threading @@ -54,6 +61,35 @@ _dirTypes = {} def run_fem_solver(solver, working_dir=None): + """ Execute *solver* of the solver framwork. + + Uses :meth:`getMachine ` to obtain a + :class:`Machine` instance of the solver. It than executes the Machine with + using the ``RESULTS`` target (see :class:`Machine` for infos about + different targets). This method is blocking, it waits for the solver to + finished before returning. Be aware of :class:`Machine` caching when using + the function. + + :param solver: + A document object which must be a famework complient solver. This means + that it should be derived from the document object provided by + :mod:`femsolver.solverbase` and implement all required methods + correctely. Of particular importance is :meth:`getMachine + ` as it is used by this method + the get the :class:`Machine` used to execute the solver. + + :param working_dir: + If specified it overwrites the automatic and user configurable working + directory management of the Solver framework. Should always be a + absolute path because the location of the binary is not consistent + among platforms. If ``None`` the automatic working directory management + is used. + + :note: + There is some legacy code to execute the old Calculix solver + (pre-framework) which behaives differently because it doesn't use a + :class:`Machine`. + """ if solver.Proxy.Type == "Fem::FemSolverCalculixCcxTools": App.Console.PrintMessage("CalxuliX ccx tools solver!\n") @@ -112,6 +148,19 @@ def run_fem_solver(solver, working_dir=None): def getMachine(solver, path=None): + """ Get or create :class:`Machine` using caching mechanism. + + :param solver: + A document object which must be a famework complient solver. This means + that it should be derived from the document object provided by + :mod:`femsolver.solverbase` and implement all required methods + correctely. Of particular importance is :meth:`getMachine + ` as it is used by this method + to create a new :class:`Machine` on cache miss. + + :param path: + A valid filesystem path which shall be associetad with the machine. + """ _DocObserver.attach() m = _machines.get(solver) if m is None or not _isPathValid(m, path): @@ -450,4 +499,3 @@ class _DocObserver(object): return True return False -## @}