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/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..ab374d1a3d 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 @@ -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,109 +162,108 @@ 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 # 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/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 cfd077f34e..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: @@ -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) @@ -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: diff --git a/src/Mod/Fem/femsolver/run.py b/src/Mod/Fem/femsolver/run.py index 0e2f8dc4de..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): @@ -124,15 +173,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 +442,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 +499,3 @@ class _DocObserver(object): return True return False - -## @} diff --git a/src/Mod/Fem/femsolver/settings.py b/src/Mod/Fem/femsolver/settings.py index d6b73c5bfd..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,48 +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("UseTempDirectory"): - return TEMPORARY - elif param_group.GetBool("UseBesideDirectory"): - return BESIDE - elif param_group.GetBool("UseCustomDirectory"): - return CUSTOM - - -## @} 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 diff --git a/src/Mod/Fem/femtools/femutils.py b/src/Mod/Fem/femtools/femutils.py index c1304990c0..3d61d7b8e6 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 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. +""" __title__ = "FEM Utilities" @@ -38,16 +45,39 @@ if FreeCAD.GuiUp: from PySide import QtGui -# analysis and its members -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* + 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: + if FreeCAD.GuiUp and viewProxy is not None: viewProxy(obj.ViewObject) return obj 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 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 + :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 are not + 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 selected 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 constraint ``""`` is returned. + + :note: + 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). + """ 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: