Merge pull request #2549 from berndhahnebach/bhbdev230
FEM: more GSoC stuff
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.")
|
||||
|
||||
## @}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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": {},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
## @}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 <femsolver.solverbase.Proxy.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
|
||||
<femsolver.solverbase.Proxy.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
|
||||
<femsolver.solverbase.Proxy.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
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -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(
|
||||
@@ -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")
|
||||
@@ -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):
|
||||
@@ -26,7 +26,7 @@
|
||||
import unittest
|
||||
|
||||
import FreeCAD
|
||||
from femtest.utilstest import fcc_print
|
||||
from .support_utils import fcc_print
|
||||
|
||||
|
||||
class TestFemImport(unittest.TestCase):
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
import FreeCAD
|
||||
import unittest
|
||||
from .utilstest import fcc_print
|
||||
from .support_utils import fcc_print
|
||||
|
||||
from os.path import join
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
0
src/Mod/Fem/femtest/data/mesh/__init__.py
Normal file
0
src/Mod/Fem/femtest/data/mesh/__init__.py
Normal file
@@ -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
|
||||
``<Class>.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:
|
||||
|
||||
Reference in New Issue
Block a user