Merge branch 'master' into pathpocketshape_fix

This commit is contained in:
Russell Johnson
2019-06-16 16:38:09 -05:00
committed by GitHub
57 changed files with 3907 additions and 147 deletions

View File

@@ -229,7 +229,7 @@ if(MSVC)
# Copy libpack 'bin' directory contents to build 'bin' per user request - only IF NOT EXISTS already
if (NOT EXISTS ${CMAKE_BINARY_DIR}/bin/DLLs)
set(COPY_LIBPACK_BIN_TO_BUILD ON)
option(FREECAD_COPY_LIBPACK_BIN_TO_BUILD "Copy larger libpack dependency 'bin' folder to the build direcctory." OFF)
option(FREECAD_COPY_LIBPACK_BIN_TO_BUILD "Copy larger libpack dependency 'bin' folder to the build directory." OFF)
endif()
else()
message("Libpack NOT found.\nIf you intend to use a Windows libpack, set the FREECAD_LIBPACK_DIR to the libpack directory.")

View File

@@ -37,7 +37,7 @@ namespace Dialog {
* \author Jürgen Riegel
*/
class DlgMacroRecordImp : public QDialog, public Ui_DlgMacroRecord, public Gui::WindowParameter
{
{
Q_OBJECT
public:
@@ -52,8 +52,8 @@ protected Q_SLOTS:
void on_lineEditMacroPath_textChanged ( const QString & );
protected:
/// conviniance pointer
MacroManager* macroManager;
/// convenience pointer
MacroManager* macroManager;
QString macroPath; // Macro file to save in
};

View File

@@ -47,9 +47,11 @@ params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
def precision():
"precision(): returns the Draft precision setting"
# Set precision level with a cap to avoid overspecification that:-
# 1 - whilst it is precise enough (e.g. that OCC would consider 2 points are conincident) (not sure what it should be 10 or otherwise);
# 2 - but FreeCAD / OCC can handle 'internally' (e.g. otherwise user may set something like 15 that the code would never consider 2 points are coincident as internal float is not that precise);
# Set precision level with a cap to avoid overspecification that:
# 1 - whilst it is precise enough (e.g. that OCC would consider 2 points are coincident)
# (not sure what it should be 10 or otherwise);
# 2 - but FreeCAD/OCC can handle 'internally' (e.g. otherwise user may set something like
# 15 that the code would never consider 2 points are coincident as internal float is not that precise);
precisionMax = 10
precisionInt = params.GetInt("precision",6)

View File

@@ -946,10 +946,10 @@ std::set<int> FemMesh::getFacesOnly(void) const
// get the volume nodes
// if the face nodes are a subset of the volume nodes
// add the face to the volume faces and break
// if face not belongs to a volume
// if face doesn't belong to a volume
// add it to faces only
//
// This means it is iterated over a lot of volumes many times, this is quite expensive !
// This means it is iterated over a lot of volumes many times, this is quite expensive!
//
// TODO make this faster
// Idea:
@@ -959,7 +959,7 @@ std::set<int> FemMesh::getFacesOnly(void) const
// if not in volume faces
// add it to the faces only
//
// but the volume faces does not seam know their global mesh ID, I could not found any method in SMESH
// but the volume faces do not seem to know their global mesh ID, I could not find any method in SMESH
std::set<int> resultIDs;
@@ -2050,4 +2050,3 @@ Base::Quantity FemMesh::getVolume(void)const
}

View File

@@ -660,6 +660,10 @@ std::map<std::string, std::string> _getFreeCADMechResultVectorProperties() {
// App::PropertyVectorList will be a list of vectors in vtk
std::map<std::string, std::string> resFCVecProp;
resFCVecProp["DisplacementVectors"] = "Displacement";
// https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=70#p296317
resFCVecProp["PS1Vector"] = "Major Principal Stress";
resFCVecProp["PS2Vector"] = "Intermediate Principal Stress";
resFCVecProp["PS3Vector"] = "Minor Principal Stress";
return resFCVecProp;
}
@@ -686,11 +690,16 @@ std::map<std::string, std::string> _getFreeCADMechResultScalarProperties() {
resFCScalProp["NodeStrainXZ"] = "Strain xz component";
resFCScalProp["NodeStrainYZ"] = "Strain yz component";
resFCScalProp["Peeq"] = "Equivalent Plastic Strain";
resFCScalProp["PrincipalMax"] = "Major Principal Stress"; // can be plotted in Paraview as THE MAJOR PRINCIPAL STRESS MAGNITUDE
resFCScalProp["PrincipalMed"] = "Intermediate Principal Stress"; // can be plotted in Paraview as THE INTERMEDIATE PRINCIPAL STRESS MAGNITUDE
resFCScalProp["PrincipalMin"] = "Minor Principal Stress"; // can be plotted in Paraview as THE MINOR PRINCIPAL STRESS MAGNITUDE
// https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=70#p296317
// resFCScalProp["PrincipalMax"] = "Major Principal Stress"; // can be plotted in Paraview as THE MAJOR PRINCIPAL STRESS MAGNITUDE
// resFCScalProp["PrincipalMed"] = "Intermediate Principal Stress"; // can be plotted in Paraview as THE INTERMEDIATE PRINCIPAL STRESS MAGNITUDE
// resFCScalProp["PrincipalMin"] = "Minor Principal Stress"; // can be plotted in Paraview as THE MINOR PRINCIPAL STRESS MAGNITUDE
resFCScalProp["StressValues"] = "von Mises Stress";
resFCScalProp["Temperature"] = "Temperature";
resFCScalProp["MohrCoulomb"] = "MohrCoulomb";
resFCScalProp["ReinforcementRatio_x"] = "ReinforcementRatio_x";
resFCScalProp["ReinforcementRatio_y"] = "ReinforcementRatio_y";
resFCScalProp["ReinforcementRatio_z"] = "ReinforcementRatio_z";
resFCScalProp["UserDefined"] = "UserDefinedMyName"; // this is empty or am I wrong ?!
resFCScalProp["MassFlowRate"] = "Mass Flow Rate";

View File

@@ -36,11 +36,13 @@ SET(FemExamples_SRCS
femexamples/__init__.py
femexamples/ccx_cantilever_std.py
femexamples/manager.py
femexamples/rc_wall_2d.py
)
SET(FemExampleMeshes_SRCS
femexamples/meshes/__init__.py
femexamples/meshes/mesh_canticcx_tetra10.py
femexamples/meshes/mesh_rc_wall_2d_tria6.py
)
SET(FemInOut_SRCS
@@ -206,6 +208,7 @@ SET(FemObjectsScripts_SRCS
femobjects/_FemElementGeometry2D.py
femobjects/_FemElementRotation1D.py
femobjects/_FemMaterial.py
femobjects/_FemMaterialReinforced.py
femobjects/_FemMaterialMechanicalNonlinear.py
femobjects/_FemMeshBoundaryLayer.py
femobjects/_FemMeshGmsh.py
@@ -286,6 +289,7 @@ SET(FemGuiScripts_SRCS
femguiobjects/_ViewProviderFemElementGeometry2D.py
femguiobjects/_ViewProviderFemElementRotation1D.py
femguiobjects/_ViewProviderFemMaterial.py
femguiobjects/_ViewProviderFemMaterialReinforced.py
femguiobjects/_ViewProviderFemMaterialMechanicalNonlinear.py
femguiobjects/_ViewProviderFemMeshBoundaryLayer.py
femguiobjects/_ViewProviderFemMeshGmsh.py

View File

@@ -401,6 +401,7 @@ SET(FemGuiPythonUI_SRCS
Resources/ui/FlowVelocity.ui
Resources/ui/InitialFlowVelocity.ui
Resources/ui/Material.ui
Resources/ui/MaterialReinforcement.ui
Resources/ui/MeshBoundaryLayer.ui
Resources/ui/MeshGmsh.ui
Resources/ui/MeshGroup.ui

View File

@@ -52,6 +52,7 @@
<file>icons/fem-material.svg</file>
<file>icons/fem-material-fluid.svg</file>
<file>icons/fem-material-nonlinear.svg</file>
<file>icons/fem-material-reinforced.svg</file>
<file>icons/fem-post-data-pipline.svg</file>
<file>icons/fem-post-filter-clip-region.svg</file>
<file>icons/fem-post-filter-clip-scalar.svg</file>

View File

@@ -0,0 +1,686 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2816"
version="1.1"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="fem-material-reinforced1.svg">
<defs
id="defs2818">
<linearGradient
inkscape:collect="always"
id="linearGradient4432">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop4434" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop4436" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4044">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4046" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4048" />
</linearGradient>
<linearGradient
id="linearGradient3681">
<stop
id="stop3697"
offset="0"
style="stop-color:#fff110;stop-opacity:1;" />
<stop
style="stop-color:#cf7008;stop-opacity:1;"
offset="1"
id="stop3685" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2824" />
<inkscape:perspective
id="perspective3622"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3622-9"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3653"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3675"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3697"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3720"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3742"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3764"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3785"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3806"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3806-3"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3835"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3614"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3614-8"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3643"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3643-3"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3672"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3672-5"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3701"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3701-8"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3746"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<pattern
patternTransform="matrix(0.67643728,-0.81829155,2.4578314,1.8844554,-26.450606,18.294947)"
id="pattern5231"
xlink:href="#Strips1_1-4"
inkscape:collect="always" />
<inkscape:perspective
id="perspective5224"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<pattern
inkscape:stockid="Stripes 1:1"
id="Strips1_1-4"
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
height="1"
width="2"
patternUnits="userSpaceOnUse"
inkscape:collect="always">
<rect
id="rect4483-4"
height="2"
width="1"
y="-0.5"
x="0"
style="fill:black;stroke:none" />
</pattern>
<inkscape:perspective
id="perspective5224-9"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<pattern
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,39.618381,8.9692804)"
id="pattern5231-4"
xlink:href="#Strips1_1-6"
inkscape:collect="always" />
<inkscape:perspective
id="perspective5224-3"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<pattern
inkscape:stockid="Stripes 1:1"
id="Strips1_1-6"
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
height="1"
width="2"
patternUnits="userSpaceOnUse"
inkscape:collect="always">
<rect
id="rect4483-0"
height="2"
width="1"
y="-0.5"
x="0"
style="fill:black;stroke:none" />
</pattern>
<pattern
patternTransform="matrix(0.66513382,-1.0631299,2.4167603,2.4482973,-49.762569,2.9546807)"
id="pattern5296"
xlink:href="#pattern5231-3"
inkscape:collect="always" />
<inkscape:perspective
id="perspective5288"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<pattern
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,-26.336284,10.887197)"
id="pattern5231-3"
xlink:href="#Strips1_1-4-3"
inkscape:collect="always" />
<pattern
inkscape:stockid="Stripes 1:1"
id="Strips1_1-4-3"
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
height="1"
width="2"
patternUnits="userSpaceOnUse"
inkscape:collect="always">
<rect
id="rect4483-4-6"
height="2"
width="1"
y="-0.5"
x="0"
style="fill:black;stroke:none" />
</pattern>
<pattern
patternTransform="matrix(0.42844886,-0.62155849,1.5567667,1.431396,27.948414,13.306456)"
id="pattern5330"
xlink:href="#Strips1_1-9"
inkscape:collect="always" />
<inkscape:perspective
id="perspective5323"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<pattern
inkscape:stockid="Stripes 1:1"
id="Strips1_1-9"
patternTransform="matrix(0.66772843,-1.0037085,2.4261878,2.3114548,3.4760987,3.534923)"
height="1"
width="2"
patternUnits="userSpaceOnUse"
inkscape:collect="always">
<rect
id="rect4483-3"
height="2"
width="1"
y="-0.5"
x="0"
style="fill:black;stroke:none" />
</pattern>
<inkscape:perspective
id="perspective5361"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective5383"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective5411"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3681"
id="linearGradient3687"
x1="37.89756"
y1="41.087898"
x2="4.0605712"
y2="40.168594"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3681"
id="linearGradient3695"
x1="31.777767"
y1="40.24213"
x2="68.442062"
y2="54.041203"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.25023482,-0.66040068,0.68751357,0.24036653,-8.7488565,43.149938)" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient12512"
id="radialGradient278"
gradientUnits="userSpaceOnUse"
cx="55"
cy="125"
fx="55"
fy="125"
r="14.375" />
<linearGradient
id="linearGradient12512">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop12513" />
<stop
style="stop-color:#fff520;stop-opacity:0.89108908;"
offset="0.50000000"
id="stop12517" />
<stop
style="stop-color:#fff300;stop-opacity:0.0000000;"
offset="1.0000000"
id="stop12514" />
</linearGradient>
<radialGradient
r="14.375"
fy="125"
fx="55"
cy="125"
cx="55"
gradientUnits="userSpaceOnUse"
id="radialGradient4017"
xlink:href="#linearGradient12512"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4044"
id="linearGradient4060"
x1="15.78776"
y1="50.394047"
x2="27.641447"
y2="39.95837"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient12512-2"
id="radialGradient278-5"
gradientUnits="userSpaceOnUse"
cx="55"
cy="125"
fx="55"
fy="125"
r="14.375" />
<linearGradient
id="linearGradient12512-2">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop12513-3" />
<stop
style="stop-color:#fff520;stop-opacity:0.89108908;"
offset="0.50000000"
id="stop12517-1" />
<stop
style="stop-color:#fff300;stop-opacity:0.0000000;"
offset="1.0000000"
id="stop12514-6" />
</linearGradient>
<radialGradient
r="14.375"
fy="125"
fx="55"
cy="125"
cx="55"
gradientUnits="userSpaceOnUse"
id="radialGradient4078"
xlink:href="#linearGradient12512-2"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3960"
id="linearGradient3966"
x1="37.758171"
y1="57.301327"
x2="21.860462"
y2="22.615412"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient3960">
<stop
style="stop-color:#c4a000;stop-opacity:1"
offset="0"
id="stop3962" />
<stop
style="stop-color:#fce94f;stop-opacity:1"
offset="1"
id="stop3964" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4432"
id="radialGradient4440"
cx="55"
cy="125"
fx="55"
fy="125"
r="20.367043"
gradientTransform="matrix(0.41658223,-0.00547178,0.00729572,0.55544286,-40.222685,-44.926056)"
gradientUnits="userSpaceOnUse" />
<linearGradient
gradientTransform="matrix(1.383847,0,0,1.383847,-144.55537,-20.287334)"
y2="23.429474"
x2="36.991264"
y1="58.615189"
x1="18.969967"
gradientUnits="userSpaceOnUse"
id="linearGradient3076-5"
xlink:href="#linearGradient3960"
inkscape:collect="always" />
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1070">
<path
style="fill:#555753;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -88.459092,0.94349885 11.448734,12.27337715 7.071068,20.05612 c 0,0 -4.242641,22.241722 -4.499771,22.884547 -0.257129,0.642824 -13.885006,11.956533 -13.885006,11.956533 l -22.755983,2.185603 -20.69894,-1.671344 -9.64237,-7.713892 z"
id="path1072"
inkscape:connector-curvature="0" />
</clipPath>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.4999999"
inkscape:cx="-5.300599"
inkscape:cy="18.864338"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:object-paths="true"
inkscape:object-nodes="true"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="1791"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:snap-grids="false"
inkscape:snap-global="false">
<inkscape:grid
type="xygrid"
id="grid3051"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata2821">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:creator>
<cc:Agent>
<dc:title>[Przemo Firszt]</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>fem-material</dc:title>
<dc:date>2015-07-28</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>FreeCAD/src/Mod/</dc:identifier>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
<dc:contributor>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g1030"
clip-path="url(#clipPath1070)"
transform="matrix(-1,0,0,1,-74.303836,-3.0089371)">
<circle
id="path4042-8"
style="fill:url(#linearGradient3076-5);fill-opacity:1;stroke:#302b00;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0"
cx="-106.30383"
cy="35.008938"
r="29" />
<g
id="g1006">
<circle
r="27"
cy="35.008938"
cx="-106.30383"
style="fill:none;stroke:#fce94f;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0"
id="path4042-0-2" />
<circle
r="29"
cy="35.008938"
cx="-106.30383"
style="fill:none;stroke:#302b00;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0"
id="path4042-3-2" />
</g>
</g>
<ellipse
cy="24.203362"
cx="-16.398699"
style="color:#000000;display:block;visibility:visible;fill:url(#radialGradient4440);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.85062206;marker:none"
id="path12511"
transform="matrix(-0.99872946,-0.05039302,-0.05039302,0.99872946,0,0)"
inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/stock_new-16.png"
inkscape:export-xdpi="33.852203"
inkscape:export-ydpi="33.852203"
rx="8"
ry="11.961311" />
<ellipse
ry="5.8596506"
rx="27.434761"
cy="-11.644531"
cx="-45.06081"
style="fill:#fce94f;stroke:#302b00;stroke-width:2.1268518;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.39999962;stroke-opacity:1"
id="path2994"
transform="matrix(-0.66077367,-0.75058521,-0.75058521,0.66077367,0,0)" />
<g
id="g929"
transform="translate(1.7844006,-0.37678835)">
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path2672"
d="M 29.13582,18.494191 42.26632,6.9348259 47.145866,12.477594 33.796524,24.229615 C 31.270776,23.145378 29.410249,21.35914 29.13582,18.494191 Z"
style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<ellipse
transform="matrix(-0.66077367,-0.75058521,-0.75058521,0.66077367,0,0)"
ry="2.3864655"
rx="3.6330051"
cy="-27.219051"
cx="-36.860275"
id="path2725"
style="opacity:1;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2727"
d="m 38.051112,16.763386 1.269735,-4.485794 -3.928998,0.919075"
style="fill:none;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path2727-5"
d="m 33.289904,21.032974 1.269732,-4.485794 -3.928998,0.919076"
style="fill:none;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path2672-0"
d="M 39.632328,28.739999 52.526725,17.388486 57.125796,22.612657 44.016493,34.153362 C 41.715452,33.03536 39.914754,31.527247 39.632328,28.739999 Z"
style="fill:#729fcf;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<ellipse
transform="matrix(-0.66077367,-0.75058521,-0.75058521,0.66077367,0,0)"
ry="2.330615"
rx="3.4292362"
cy="-27.36412"
cx="-51.272247"
id="path2725-7"
style="opacity:1;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path2727-3"
d="m 48.267466,26.904181 1.312881,-4.330186 -3.808594,0.959064"
style="fill:none;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path2727-5-4"
d="m 43.59034,31.095258 1.312882,-4.330187 -3.808597,0.959067"
style="fill:none;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<path
style="fill:none;stroke:#fce94f;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 53.432979,48.750319 C 45.75619,46.435326 23.315662,25.197958 17.744599,8.2386998"
id="path3485"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FemMaterial</class>
<widget class="QWidget" name="FemMaterial">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>396</width>
<height>448</height>
</rect>
</property>
<property name="windowTitle">
<string>FEM material</string>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_desc">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1677215</height>
</size>
</property>
<property name="title">
<string>Matrix Material</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QComboBox" name="cb_materials_m">
<item>
<property name="text">
<string>Choose</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Material</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="l_name_m">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="pb_edit_m">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Properties</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="l_description_m">
<property name="text">
<string>Description</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_desc_2">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1677215</height>
</size>
</property>
<property name="title">
<string>Reinforcement Material</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="1">
<widget class="QComboBox" name="cb_materials_r">
<item>
<property name="text">
<string>Choose</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Material</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="l_name_r">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="pb_edit_r">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Properties</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="l_description_r">
<property name="text">
<string>Description</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -87,6 +87,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
<< "FEM_MaterialSolid"
<< "FEM_MaterialFluid"
<< "FEM_MaterialMechanicalNonlinear"
<< "FEM_MaterialReinforced"
<< "FEM_MaterialEditor"
<< "Separator"
<< "FEM_ElementGeometry1D"
@@ -190,6 +191,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
*material << "FEM_MaterialSolid"
<< "FEM_MaterialFluid"
<< "FEM_MaterialMechanicalNonlinear"
<< "FEM_MaterialReinforced"
<< "FEM_MaterialEditor";
Gui::MenuItem* elec = new Gui::MenuItem;

View File

@@ -372,6 +372,21 @@ def makeMaterialMechanicalNonlinear(
return obj
def makeMaterialReinforced(
doc,
name="MaterialReinforced"
):
'''makeMaterialReinforced(document, [matrix_material], [reinforcement_material], [name]):
creates a reinforced material object'''
obj = doc.addObject("App::MaterialObjectPython", name)
from femobjects import _FemMaterialReinforced
_FemMaterialReinforced._FemMaterialReinforced(obj)
if FreeCAD.GuiUp:
from femguiobjects import _ViewProviderFemMaterialReinforced
_ViewProviderFemMaterialReinforced._ViewProviderFemMaterialReinforced(obj.ViewObject)
return obj
def makeMaterialSolid(
doc,
name="MechanicalSolidMaterial"

View File

@@ -126,7 +126,9 @@ gf()
./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"
./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"
@@ -214,7 +216,13 @@ import unittest
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_von_mises"))
import unittest
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_principal"))
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_principal_std"))
import unittest
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_principal_reinforced"))
import unittest
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_rho"))
import unittest
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_disp_abs"))

View File

@@ -665,6 +665,37 @@ class _CommandFemMaterialMechanicalNonlinear(CommandManager):
FreeCAD.ActiveDocument.recompute()
class _CommandFemMaterialReinforced(CommandManager):
"The FEM_MaterialReinforced command definition"
def __init__(self):
super(_CommandFemMaterialReinforced, self).__init__()
self.resources = {
'Pixmap': 'fem-material-reinforced',
'MenuText': QtCore.QT_TRANSLATE_NOOP(
"FEM_MaterialReinforced",
"Reinforced material (concrete)"
),
'Accel': "M, M",
'ToolTip': QtCore.QT_TRANSLATE_NOOP(
"FEM_MaterialReinforced",
"Creates a material for reinforced matrix material such as concrete"
)
}
self.is_active = 'with_analysis'
def Activated(self):
FreeCAD.ActiveDocument.openTransaction("Create Reinforced Material")
FreeCADGui.addModule("ObjectsFem")
FreeCADGui.doCommand(
"FemGui.getActiveAnalysis().addObject(ObjectsFem."
"makeMaterialReinforced(FreeCAD.ActiveDocument, 'ReinforcedMaterial'))"
)
FreeCADGui.doCommand(
"FreeCADGui.ActiveDocument.setEdit(FreeCAD.ActiveDocument.ActiveObject.Name)"
)
FreeCAD.ActiveDocument.recompute()
class _CommandFemMaterialSolid(CommandManager):
"The FEM_MaterialSolid command definition"
def __init__(self):
@@ -1296,6 +1327,10 @@ FreeCADGui.addCommand(
'FEM_MaterialMechanicalNonlinear',
_CommandFemMaterialMechanicalNonlinear()
)
FreeCADGui.addCommand(
'FEM_MaterialReinforced',
_CommandFemMaterialReinforced()
)
FreeCADGui.addCommand(
'FEM_MaterialSolid',
_CommandFemMaterialSolid()

View File

@@ -75,6 +75,7 @@ def run_all():
run_ccx_cantileverfaceload()
run_ccx_cantilevernodeload()
run_ccx_cantileverprescribeddisplacement()
run_rcwall2d()
def run_ccx_cantileverfaceload(solver=None, base_name=None):
@@ -119,6 +120,20 @@ def run_ccx_cantileverprescribeddisplacement(solver=None, base_name=None):
return doc
def run_rcwall2d(solver=None, base_name=None):
from femexamples.rc_wall_2d import setup_rcwall2d as setup
doc = setup()
if base_name is None:
base_name = 'RC_FIB_Wall_2D'
if solver is not None:
base_name += ('_' + solver)
run_analysis(doc, base_name)
return doc
'''
from femexamples.manager import *
@@ -132,4 +147,6 @@ doc = run_ccx_cantilevernodeload('calculix')
doc = run_ccx_cantilevernodeload('ccxtools')
doc = run_ccx_cantilevernodeload('z88')
doc = run_rcwall2d()
'''

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,165 @@
# ***************************************************************************
# * Copyright (c) 2019 Bernd Hahnebach <bernd@bimstatik.org> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * FreeCAD is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with FreeCAD; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import ObjectsFem
import Fem
mesh_name = 'Mesh' # needs to be Mesh to work with unit tests
def init_doc(doc=None):
if doc is None:
doc = FreeCAD.newDocument()
return doc
def setup_rcwall2d(doc=None, solver='ccxtools'):
# setup reinfoced wall in 2D
if doc is None:
doc = init_doc()
# part
from FreeCAD import Vector as vec
import Part
from Part import makeLine as ln
v1 = vec(0, -2000, 0)
v2 = vec(500, -2000, 0)
v3 = vec(500, 0, 0)
v4 = vec(3500, 0, 0)
v5 = vec(3500, -2000, 0)
v6 = vec(4000, -2000, 0)
v7 = vec(4000, 2000, 0)
v8 = vec(0, 2000, 0)
l1 = ln(v1, v2)
l2 = ln(v2, v3)
l3 = ln(v3, v4)
l4 = ln(v4, v5)
l5 = ln(v5, v6)
l6 = ln(v6, v7)
l7 = ln(v7, v8)
l8 = ln(v8, v1)
rcwall = doc.addObject("Part::Feature", "FIB_Wall")
rcwall.Shape = Part.Face(Part.Wire([l1, l2, l3, l4, l5, l6, l7, l8]))
# analysis
analysis = ObjectsFem.makeAnalysis(doc, 'Analysis')
solver
# TODO How to pass multiple solver for one analysis in one doc
if solver is None:
pass # no solver is added
elif solver is 'calculix':
solver = analysis.addObject(
ObjectsFem.makeSolverCalculix(doc, 'SolverCalculiX')
)[0]
solver.AnalysisType = 'static'
solver.GeometricalNonlinearity = 'linear'
solver.ThermoMechSteadyState = False
solver.MatrixSolverType = 'default'
solver.IterationsControlParameterTimeUse = False
elif solver is 'ccxtools':
solver = analysis.addObject(
ObjectsFem.makeSolverCalculixCcxTools(doc, 'CalculiXccxTools')
)[0]
solver.AnalysisType = 'static'
solver.GeometricalNonlinearity = 'linear'
solver.ThermoMechSteadyState = False
solver.MatrixSolverType = 'default'
solver.IterationsControlParameterTimeUse = False
solver.WorkingDir = u''
# shell thickness
thickness = analysis.addObject(
ObjectsFem.makeElementGeometry2D(doc, 0, 'ShellThickness')
)[0]
thickness.Thickness = 150.0
# material
matrixprop = {}
matrixprop['Name'] = "Concrete-EN-C35/45"
matrixprop['YoungsModulus'] = "32000 MPa"
matrixprop['PoissonRatio'] = "0.17"
matrixprop['CompressiveStrength'] = "15.75 MPa"
# make some hint on the possible angle units in material system
matrixprop['AngleOfFriction'] = "30 deg"
matrixprop['Density'] = '2500 kg/m^3'
reinfoprop = {}
reinfoprop['Name'] = "Reinforcement-FIB-B500"
reinfoprop['YieldStrength'] = "315 MPa"
# not an official FreeCAD material property
reinfoprop['ReinforcementRatio'] = "0.0"
material_reinforced = analysis.addObject(
ObjectsFem.makeMaterialReinforced(doc, 'MaterialReinforced')
)[0]
material_reinforced.Material = matrixprop
material_reinforced.Reinforcement = reinfoprop
# fixed_constraint
fixed_constraint = analysis.addObject(
ObjectsFem.makeConstraintFixed(doc, name="ConstraintFixed")
)[0]
fixed_constraint.References = [(rcwall, "Edge1"), (rcwall, "Edge5")]
# force constraint
force_constraint = doc.Analysis.addObject(
ObjectsFem.makeConstraintForce(doc, name="ConstraintForce")
)[0]
force_constraint.References = [(rcwall, "Edge7")]
force_constraint.Force = 1000000.0
force_constraint.Direction = (rcwall, ["Edge8"])
force_constraint.Reversed = False
# displacement_constraint
displacement_constraint = doc.Analysis.addObject(
ObjectsFem.makeConstraintDisplacement(doc, name="ConstraintDisplacmentPrescribed")
)[0]
displacement_constraint.References = [(rcwall, "Face1")]
displacement_constraint.zFix = True
# mesh
from femexamples.meshes.mesh_rc_wall_2d_tria6 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
print('ERROR on creating nodes')
control = create_elements(fem_mesh)
if not control:
print('ERROR on creating elements')
femmesh_obj = analysis.addObject(
doc.addObject('Fem::FemMeshObject', mesh_name)
)[0]
femmesh_obj.FemMesh = fem_mesh
doc.recompute()
return doc
'''
from femexamples import rc_wall_2d as rc
rc.setup_rcwall2d()
'''

View File

@@ -32,10 +32,11 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
from pivy import coin
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class ViewProxy(object):
"""Proxy View Provider for Pythons base constraint."""

View File

@@ -31,7 +31,8 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class _ViewProviderFemConstraintSelfWeight:

View File

@@ -33,7 +33,6 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
# for the panel
from femobjects import _FemElementFluid1D
@@ -41,6 +40,8 @@ from PySide import QtCore
from PySide import QtGui
from . import FemSelectionWidgets
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class _ViewProviderFemElementFluid1D:
"A View Provider for the FemElementFluid1D object"

View File

@@ -31,13 +31,14 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
# for the panel
from femobjects import _FemElementGeometry1D
from PySide import QtCore
from . import FemSelectionWidgets
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class _ViewProviderFemElementGeometry1D:
"A View Provider for the FemElementGeometry1D object"

View File

@@ -31,12 +31,13 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
# for the panel
from PySide import QtCore
from . import FemSelectionWidgets
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class _ViewProviderFemElementGeometry2D:
"A View Provider for the FemElementGeometry2D object"

View File

@@ -31,12 +31,13 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
# for the panel
from PySide import QtCore
from . import FemSelectionWidgets
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class _ViewProviderFemElementRotation1D:
"A View Provider for the FemElementRotation1D object"

View File

@@ -31,7 +31,6 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
# for the panel
from FreeCAD import Units
@@ -39,6 +38,9 @@ from . import FemSelectionWidgets
from PySide import QtCore
from PySide import QtGui
import sys
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
if sys.version_info.major >= 3:
unicode = str

View File

@@ -31,10 +31,11 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
from pivy import coin
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class _ViewProviderFemMaterialMechanicalNonlinear:
"A View Provider for the FemMaterialMechanicalNonlinear object"

View File

@@ -0,0 +1,502 @@
# ***************************************************************************
# * Copyright (c) 2019 Bernd Hahnebach <bernd@bimstatik.org> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
__title__ = "FreeCAD FEM material reinforced ViewProvider for the document object"
__author__ = "Bernd Hahnebach"
__url__ = "http://www.freecadweb.org"
## @package ViewProviderFemMaterialReinforced
# \ingroup FEM
# \brief FreeCAD FEM _ViewProviderFemMaterialReinforced
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
# task panel
# from . import FemSelectionWidgets
from PySide import QtCore
from PySide import QtGui
import sys
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
if sys.version_info.major >= 3:
unicode = str
class _ViewProviderFemMaterialReinforced:
"A View Provider for the FemMaterialReinfocement object"
def __init__(self, vobj):
vobj.Proxy = self
def getIcon(self):
return ":/icons/fem-material-reinforced.svg"
def attach(self, vobj):
from pivy import coin
self.ViewObject = vobj
self.Object = vobj.Object
self.standard = coin.SoGroup()
vobj.addDisplayMode(self.standard, "Default")
def getDisplayModes(self, obj):
return ["Default"]
def updateData(self, obj, prop):
return
def onChanged(self, vobj, prop):
return
def setEdit(self, vobj, mode=0):
# hide all meshes
for o in FreeCAD.ActiveDocument.Objects:
if o.isDerivedFrom("Fem::FemMeshObject"):
o.ViewObject.hide()
# hide all meshes
for o in FreeCAD.ActiveDocument.Objects:
if o.isDerivedFrom("Fem::FemMeshObject"):
o.ViewObject.hide()
# show task panel
taskd = _TaskPanelFemMaterialReinforced(self.Object)
taskd.obj = vobj.Object
FreeCADGui.Control.showDialog(taskd)
return True
def unsetEdit(self, vobj, mode=0):
FreeCADGui.Control.closeDialog()
return True
def doubleClicked(self, vobj):
guidoc = FreeCADGui.getDocument(vobj.Object.Document)
# check if another VP is in edit mode
# https://forum.freecadweb.org/viewtopic.php?t=13077#p104702
if not guidoc.getInEdit():
guidoc.setEdit(vobj.Object.Name)
else:
from PySide.QtGui import QMessageBox
message = (
'Active Task Dialog found! '
'Please close this one before opening a new one!'
)
QMessageBox.critical(None, "Error in tree view", message)
FreeCAD.Console.PrintError(message + '\n')
return True
def __getstate__(self):
return None
def __setstate__(self, state):
return None
class _TaskPanelFemMaterialReinforced:
'''The editmode TaskPanel for FemMaterialReinforced objects'''
if sys.version_info.major >= 3:
unicode = str
def __init__(self, obj):
FreeCAD.Console.PrintMessage('\n') # empty line on start task panel
self.obj = obj
# init matrix and reinforcement material
self.material_m = self.obj.Material
self.card_path_m = ''
self.has_transient_mat_m = False
self.material_r = self.obj.Reinforcement
self.card_path_r = ''
self.has_transient_mat_r = False
# mat_card is the FCMat file
# card_name is the file name of the mat_card
# card_path is the whole file path of the mat_card
# material_name is the value of the key name in FreeCAD material dictionary
# they might not match because of special letters in the material_name which are
# changed in the card_name to english standard characters
# init for collecting all mat data and icons
self.materials = {} # { card_path : FreeCAD material dict }
self.cards = {} # { card_path : card_names, ... }
self.icons = {} # { card_path : icon_path }
# parameter widget
self.parameterWidget = FreeCADGui.PySideUic.loadUi(
FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/MaterialReinforcement.ui"
)
# globals
QtCore.QObject.connect(
self.parameterWidget.cb_materials_m,
QtCore.SIGNAL("activated(int)"),
self.choose_material_m
)
QtCore.QObject.connect(
self.parameterWidget.pb_edit_m,
QtCore.SIGNAL("clicked()"),
self.edit_material_m
)
QtCore.QObject.connect(
self.parameterWidget.cb_materials_r,
QtCore.SIGNAL("activated(int)"),
self.choose_material_r
)
QtCore.QObject.connect(
self.parameterWidget.pb_edit_r,
QtCore.SIGNAL("clicked()"),
self.edit_material_r
)
# get all available materials (fill self.materials, self.cards and self.icons)
from materialtools.cardutils import import_materials as getmats
self.materials, self.cards, self.icons = getmats()
# fill the material comboboxes with material cards
self.add_cards_to_combo_boxes()
# search for exact the mat_card_m and mat_card_r in all known cards
# choose the current matrix material
self.card_path_m = self.get_material_card(self.material_m)
FreeCAD.Console.PrintLog('card_path: {}'.format(self.card_path_m))
if not self.card_path_m:
# we have not found our material in self.materials dict :-(
# we're going to add a user-defined temporary material: a document material
FreeCAD.Console.PrintMessage(
"Previously used material card cannot be found in material directories. "
"Add document material.\n"
)
self.card_path_m = '_Document_Matrix_Material'
self.materials[self.card_path_m] = self.material_m
self.parameterWidget.cb_materials_m.addItem(
QtGui.QIcon(":/icons/help-browser.svg"),
self.card_path_m,
self.card_path_m
)
index = self.parameterWidget.cb_materials_m.findData(self.card_path_m)
# print(index)
# fill input fields and set the current material in the cb widget
self.choose_material_m(index)
else:
# we found our exact material in self.materials dict :-)
FreeCAD.Console.PrintLog(
"Previously used material card was found in material directories. "
"We will use this material.\n"
)
index = self.parameterWidget.cb_materials_m.findData(self.card_path_m)
# set the current material in the cb widget
self.choose_material_m(index)
# choose the current reinforcement material
self.card_path_r = self.get_material_card(self.material_r)
FreeCAD.Console.PrintLog('card_path: {}'.format(self.card_path_r))
if not self.card_path_r:
# we have not found our material in self.materials dict :-(
# we're going to add a user-defined temporary material: a document material
FreeCAD.Console.PrintMessage(
"Previously used material card cannot be found in material directories. "
"Add document material.\n"
)
self.card_path_r = '_Document_Reinforcement_Material'
self.materials[self.card_path_r] = self.material_r
self.parameterWidget.cb_materials_r.addItem(
QtGui.QIcon(":/icons/help-browser.svg"),
self.card_path_r,
self.card_path_r
)
index = self.parameterWidget.cb_materials_r.findData(self.card_path_r)
# set the current material in the cb widget
self.choose_material_r(index)
else:
# we found our exact material in self.materials dict :-)
FreeCAD.Console.PrintLog(
"Previously used material card was found in material directories. "
"We will use this material.\n"
)
index = self.parameterWidget.cb_materials_r.findData(self.card_path_r)
# print(index)
# fill input fields and set the current material in the cb widget
self.choose_material_r(index)
# set up the form
self.form = self.parameterWidget
# leave task panel ***************************************************************************
def accept(self):
from materialtools.cardutils import check_mat_units as checkunits
if checkunits(self.material_m) is True and checkunits(self.material_r) is True:
self.obj.Material = self.material_m
self.obj.Reinforcement = self.material_r
else:
error_message = (
'Due to some wrong material quantity units in the changed '
'material data, the task panel changes where not accepted.\n'
)
FreeCAD.Console.PrintError(error_message)
QtGui.QMessageBox.critical(None, "Material data not changed", error_message)
self.recompute_and_set_back_all()
return True
def reject(self):
self.recompute_and_set_back_all()
return True
def recompute_and_set_back_all(self):
guidoc = FreeCADGui.getDocument(self.obj.Document)
guidoc.Document.recompute()
guidoc.resetEdit()
self.output_obj_mat_param()
def output_obj_mat_param(self):
self.print_mat_dict(self.obj.Material)
self.print_mat_dict(self.obj.Reinforcement)
print('\n')
def print_mat_dict(self, mat_dict):
if 'Name' in mat_dict:
print('Material: {}'.format(mat_dict['Name']))
else:
print('Matrix material: no Name')
for key in mat_dict:
print(' {}: {}'.format(key, mat_dict[key]))
# choose material card ***********************************************************************
def get_material_card(self, material):
for a_mat in self.materials:
unmatched_items = set(self.materials[a_mat].items()) ^ set(material.items())
# print(a_mat + ' --> unmatched_items = ' + str(len(unmatched_items)))
if len(unmatched_items) < 4:
FreeCAD.Console.PrintLog('{}\n'.format(unmatched_items))
if len(unmatched_items) == 0:
return a_mat
return ""
def choose_material_m(self, index):
if index < 0:
return
# get the whole card path
self.card_path_m = self.parameterWidget.cb_materials_m.itemData(index)
FreeCAD.Console.PrintMessage(
'choose_material in FEM material task panel:\n'
' {}\n'.format(self.card_path_m)
)
self.material_m = self.materials[self.card_path_m]
self.parameterWidget.cb_materials_m.setCurrentIndex(index)
gen_mat_desc = ""
gen_mat_name = ""
if 'Description' in self.material_m:
gen_mat_desc = self.material_m['Description']
if 'Name' in self.material_m:
gen_mat_name = self.material_m['Name']
self.parameterWidget.l_description_m.setText(gen_mat_desc)
self.parameterWidget.l_name_m.setText(gen_mat_name)
def choose_material_r(self, index):
if index < 0:
return
# get the whole card path
self.card_path_r = self.parameterWidget.cb_materials_r.itemData(index)
FreeCAD.Console.PrintMessage(
'choose_material in FEM material task panel:\n'
' {}\n'.format(self.card_path_r)
)
self.material_r = self.materials[self.card_path_r]
self.parameterWidget.cb_materials_r.setCurrentIndex(index)
gen_mat_desc = ""
gen_mat_name = ""
if 'Description' in self.material_r:
gen_mat_desc = self.material_r['Description']
if 'Name' in self.material_r:
gen_mat_name = self.material_r['Name']
self.parameterWidget.l_description_r.setText(gen_mat_desc)
self.parameterWidget.l_name_r.setText(gen_mat_name)
# transient material is needed if the user changed mat parameter by the mat editor
def set_transient_material_m(self):
self.card_path_m = '_Transient_Matrix_Material'
self.materials[self.card_path_m] = self.material_m # = the current matrix mat dict
index = self.parameterWidget.cb_materials_m.findData(self.card_path_m)
self.choose_material_m(index)
def add_transient_material_m(self):
self.has_transient_mat_m = True
self.card_path_m = '_Transient_Matrix_Material'
self.parameterWidget.cb_materials_m.addItem(
QtGui.QIcon(":/icons/help-browser.svg"),
self.card_path_m,
self.card_path_m
)
self.set_transient_material_m()
def set_transient_material_r(self):
self.card_path_r = '_Transient_Reinforcement_Material'
self.materials[self.card_path_r] = self.material_r # = the current reinforced mat dict
index = self.parameterWidget.cb_materials_r.findData(self.card_path_r)
self.choose_material_r(index)
def add_transient_material_r(self):
self.has_transient_mat_r = True
self.card_path_r = '_Transient_Reinforcement_Material'
self.parameterWidget.cb_materials_r.addItem(
QtGui.QIcon(":/icons/help-browser.svg"),
self.card_path_r,
self.card_path_r
)
self.set_transient_material_r()
# edit material parameter ********************************************************************
# TODO, also all mat parameter checks should be moved to material editor
# and mat parameter checks should be done on analysis precheck in according to the analysis
# should be checked if all needed parameter are defined and have all right values and units
def edit_material_m(self):
# opens the material editor to choose a material or edit material params
import MaterialEditor
if self.card_path_m not in self.cards:
FreeCAD.Console.PrintLog(
'Card path not in cards, material dict will be used to open Material Editor.\n'
)
new_material_params = MaterialEditor.editMaterial(material=self.material_m)
else:
new_material_params = MaterialEditor.editMaterial(card_path=self.card_path_m)
# material editor returns the mat_dict only, not a card_path
# if the material editor was canceled a empty dict will be returned
# do not change the self.material
# check if dict is not empty (do not use 'is True')
if new_material_params:
# check material quantity units
from materialtools.cardutils import check_mat_units as checkunits
if checkunits(new_material_params) is True:
self.material_m = new_material_params
self.card_path_m = self.get_material_card(self.material_m)
FreeCAD.Console.PrintMessage('card_path: {}\n'.format(self.card_path_m))
if not self.card_path_m:
FreeCAD.Console.PrintMessage(
"Material card chosen by the material editor "
"was not found in material directories.\n"
"Either the card does not exist or some material "
"parameter where changed in material editor.\n"
)
if self.has_transient_mat_m is False:
self.add_transient_material_m()
else:
self.set_transient_material_m()
else:
# we found our exact material in self.materials dict :-)
FreeCAD.Console.PrintLog(
"Material card chosen by the material editor "
"was found in material directories. "
"The found material card will be used.\n"
)
index = self.parameterWidget.cb_materials_m.findData(self.card_path_m)
# print(index)
# set the current material in the cb widget
self.choose_material_m(index)
else:
error_message = (
'Due to some wrong material quantity units in data passed '
'by the material editor, the material data was not changed.\n'
)
FreeCAD.Console.PrintError(error_message)
QtGui.QMessageBox.critical(None, "Material data not changed", error_message)
else:
FreeCAD.Console.PrintMessage('No changes where made by the material editor.\n')
def edit_material_r(self):
# opens the material editor to choose a material or edit material params
import MaterialEditor
if self.card_path_r not in self.cards:
FreeCAD.Console.PrintLog(
'Card path not in cards, material dict will be used to open Material Editor.\n'
)
new_material_params = MaterialEditor.editMaterial(material=self.material_r)
else:
new_material_params = MaterialEditor.editMaterial(card_path=self.card_path_r)
# material editor returns the mat_dict only, not a card_path
# if the material editor was canceled a empty dict will be returned
# do not change the self.material
# check if dict is not empty (do not use 'is True')
if new_material_params:
# check material quantity units
from materialtools.cardutils import check_mat_units as checkunits
if checkunits(new_material_params) is True:
self.material_r = new_material_params
self.card_path_r = self.get_material_card(self.material_r)
FreeCAD.Console.PrintMessage('card_path: {}\n'.format(self.card_path_r))
if not self.card_path_r:
FreeCAD.Console.PrintMessage(
"Material card chosen by the material editor "
"was not found in material directories.\n"
"Either the card does not exist or some material "
"parameter where changed in material editor.\n"
)
if self.has_transient_mat_r is False:
self.add_transient_material_r()
else:
self.set_transient_material_r()
else:
# we found our exact material in self.materials dict :-)
FreeCAD.Console.PrintLog(
"Material card chosen by the material editor "
"was found in material directories. "
"The found material card will be used.\n"
)
index = self.parameterWidget.cb_materials_r.findData(self.card_path_r)
# print(index)
# set the current material in the cb widget
self.choose_material_r(index)
else:
error_message = (
'Due to some wrong material quantity units in data passed '
'by the material editor, the material data was not changed.\n'
)
FreeCAD.Console.PrintError(error_message)
QtGui.QMessageBox.critical(None, "Material data not changed", error_message)
else:
FreeCAD.Console.PrintMessage('No changes where made by the material editor.\n')
# fill the combo box with cards **************************************************************
def add_cards_to_combo_boxes(self):
# fill comboboxes, in combo box the card name is used not the material name
self.parameterWidget.cb_materials_m.clear()
self.parameterWidget.cb_materials_r.clear()
mat_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Cards")
sort_by_resources = mat_prefs.GetBool("SortByResources", False)
card_name_list = [] # [ [card_name, card_path, icon_path], ... ]
if sort_by_resources is True:
for a_path in sorted(self.materials.keys()):
card_name_list.append([self.cards[a_path], a_path, self.icons[a_path]])
else:
card_names_tmp = {}
for path, name in self.cards.items():
card_names_tmp[name] = path
for a_name in sorted(card_names_tmp.keys()):
a_path = card_names_tmp[a_name]
card_name_list.append([a_name, a_path, self.icons[a_path]])
for mat in card_name_list:
self.parameterWidget.cb_materials_m.addItem(QtGui.QIcon(mat[2]), mat[0], mat[1])
self.parameterWidget.cb_materials_r.addItem(QtGui.QIcon(mat[2]), mat[0], mat[1])
# the whole card path is added to the combo box to make it unique
# see def choose_material:
# for assignment of self.card_path the path form the parameterWidget ist used

View File

@@ -31,12 +31,13 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
# for the panel
from PySide import QtCore
from . import FemSelectionWidgets
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class _ViewProviderFemMeshBoundaryLayer:
"A View Provider for the FemMeshBoundaryLayer object"

View File

@@ -31,12 +31,13 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
# for the panel
from PySide import QtCore
from . import FemSelectionWidgets
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class _ViewProviderFemMeshGroup:
"A View Provider for the FemMeshGroup object"

View File

@@ -31,12 +31,13 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
# for the panel
from PySide import QtCore
from . import FemSelectionWidgets
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class _ViewProviderFemMeshRegion:
"A View Provider for the FemMeshRegion object"

View File

@@ -31,10 +31,8 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import FreeCADGui
import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just returns 'FemGui'
# for the panel
import FemGui
import femresult.resulttools as resulttools
from PySide import QtCore
from PySide import QtGui
@@ -42,6 +40,8 @@ from PySide.QtCore import Qt
from PySide.QtGui import QApplication
import numpy as np
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
class _ViewProviderFemResultMechanical:
"A View Provider for the FemResultObject Python derived FemResult class"
@@ -467,6 +467,28 @@ class _TaskPanelFemResultShow:
exy = np.array(self.result_obj.NodeStrainXY)
exz = np.array(self.result_obj.NodeStrainXZ)
eyz = np.array(self.result_obj.NodeStrainYZ)
# Display of Reinforcement Ratios and Mohr Coulomb Criterion
rx = np.array(self.result_obj.ReinforcementRatio_x)
ry = np.array(self.result_obj.ReinforcementRatio_y)
rz = np.array(self.result_obj.ReinforcementRatio_z)
mc = np.array(self.result_obj.MohrCoulomb)
ps1vector = np.array(self.result_obj.PS1Vector)
s1x = np.array(ps1vector[:, 0])
s1y = np.array(ps1vector[:, 1])
s1z = np.array(ps1vector[:, 2])
ps2vector = np.array(self.result_obj.PS2Vector)
s2x = np.array(ps2vector[:, 0])
s2y = np.array(ps2vector[:, 1])
s2z = np.array(ps2vector[:, 2])
ps3vector = np.array(self.result_obj.PS1Vector)
s3x = np.array(ps3vector[:, 0])
s3y = np.array(ps3vector[:, 1])
s3z = np.array(ps3vector[:, 2])
userdefined_eq = self.form.user_def_eq.toPlainText() # Get equation to be used
UserDefinedFormula = eval(userdefined_eq).tolist()
self.result_obj.UserDefined = UserDefinedFormula
@@ -486,7 +508,8 @@ class _TaskPanelFemResultShow:
del x, y, z, T, Von, Peeq, P1, P2, P3
del sxx, syy, szz, sxy, sxz, syz
del exx, eyy, ezz, exy, exz, eyz
del MF, NP
del MF, NP, rx, ry, rz, mc
del s1x, s1y, s1z, s2x, s2y, s2z, s3x, s3y, s3z
def select_displacement_type(self, disp_type):
QApplication.setOverrideCursor(Qt.WaitCursor)
@@ -634,12 +657,13 @@ def hide_femmeshes_postpiplines():
def hide_parts_constraints():
from FemGui import getActiveAnalysis
fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General")
hide_constraints = fem_prefs.GetBool("HideConstraint", False)
if hide_constraints:
for o in FreeCAD.ActiveDocument.Objects:
if o.isDerivedFrom('Fem::FemAnalysis'):
for acnstrmesh in FemGui.getActiveAnalysis().Group:
for acnstrmesh in getActiveAnalysis().Group:
if "Constraint" in acnstrmesh.TypeId:
acnstrmesh.ViewObject.Visibility = False
break

View File

@@ -26,12 +26,11 @@
# Make mesh of pn junction in TetGen format
import FreeCAD
import Mesh
App = FreeCAD # shortcut
if FreeCAD.GuiUp:
import FreeCADGui
Gui = FreeCADGui # shortcut
# import Part
import Mesh
## \addtogroup FEM
# @{
@@ -46,14 +45,6 @@ def exportMeshToTetGenPoly(meshToExport, filePath, beVerbose=1):
f = open(filePath, 'w')
f.write("# This file was generated from FreeCAD geometry\n")
f.write("# Part 1 - node list\n")
'''
f.write("%(TotalNumOfPoints)i %(NumOfDimensions)i %(NumOfProperties)i %(BoundaryMarkerExists)i\n" % {
'TotalNumOfPoints': len(allVertices),
'NumOfDimensions': 3,
'NumOfProperties': 0,
'BoundaryMarkerExists': 0
})
'''
f.write(
"TotalNumOfPoints: {}, NumOfDimensions; {}, "
"NumOfProperties: {}, BoundaryMarkerExists: {}\n"

View File

@@ -120,19 +120,31 @@ def importFrd(
analysis_object.addObject(res_obj)
# complementary result object calculations
import femresult.resulttools as restools
import femtools.femutils as femutils
if not res_obj.MassFlowRate:
# only compact result if not Flow 1D results
# compact result object, workaround for bug 2873
# https://www.freecadweb.org/tracker/view.php?id=2873
res_obj = restools.compact_result(res_obj)
# fill DisplacementLengths
res_obj = restools.add_disp_apps(res_obj)
# fill StressValues
res_obj = restools.add_von_mises(res_obj)
# fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear
res_obj = restools.add_principal_stress(res_obj)
if res_obj.getParentGroup():
has_reinforced_mat = False
for obj in res_obj.getParentGroup().Group:
if obj.isDerivedFrom('App::MaterialObjectPython') \
and femutils.is_of_type(obj, 'Fem::MaterialReinforced'):
has_reinforced_mat = True
restools.add_principal_stress_reinforced(res_obj)
break
if has_reinforced_mat is False:
# fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear
res_obj = restools.add_principal_stress_std(res_obj)
# fill Stats
res_obj = restools.fill_femresult_stats(res_obj)
else:
error_message = (
"We have nodes but no results in frd file, "

View File

@@ -31,17 +31,15 @@ __url__ = "http://www.freecadweb.org"
import os
import FreeCAD
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtGui, QtCore
from . import importToolsFem
from . import readFenicsXML
from . import writeFenicsXML
from . import writeFenicsXDMF
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtGui, QtCore
# Template copied from importZ88Mesh.py. Thanks Bernd!
# ********* generic FreeCAD import and export methods *********

View File

@@ -484,12 +484,14 @@ def write_z88_mesh_to_file(
# z88_element_type is checked for every element
# but mixed elements are not supported up to date
n = femelement_table[element]
if z88_element_type == 2 \
or z88_element_type == 4 \
or z88_element_type == 5 \
or z88_element_type == 9 \
or z88_element_type == 13 \
or z88_element_type == 25:
if (
z88_element_type == 2
or z88_element_type == 4
or z88_element_type == 5
or z88_element_type == 9
or z88_element_type == 13
or z88_element_type == 25
):
# seg2 FreeCAD --> stab4 Z88
# N1, N2
f.write("{0} {1}\n".format(element, z88_element_type, element))

View File

@@ -201,14 +201,14 @@ def get_femnodes_ele_table(
):
'''the femnodes_ele_table contains for each node its membership in elements
{nodeID : [[eleID, NodePosition], [], ...], nodeID : [[], [], ...], ...}
stored informatation are:
stored information is:
element number, the number of nodes per element
the position of the node in the element.
The position of the node in the element is coded
as a set bit at that position in a bit array (integer)
FIXME: the number of nodes per element should be
replaced by the type of the element
but I did not know, how to get this from the mesh.
but I did not know how to get this from the mesh.
Since the femelement_table contains either
volume or face or edgemesh the femnodes_ele_table only
has either volume or face or edge elements
@@ -1799,9 +1799,9 @@ def get_anlysis_empty_references_group_elements(
aShape
):
'''get the elementIDs if the Reference shape is empty
see get_analysis_group_elements() for more informatations
see get_analysis_group_elements() for more information
on solid meshes only material objects could have an
empty reference without being something wrong!
empty reference without there being something wrong!
face meshes could have empty ShellThickness and
edge meshes could have empty BeamSection/FluidSection
'''

View File

@@ -0,0 +1,59 @@
# ***************************************************************************
# * *
# * Copyright (c) 2019 Bernd Hahnebach <bernd@bimstatik.org> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
__title__ = "FreeCAD FEM reinforced material"
__author__ = "Bernd Hahnebach"
__url__ = "http://www.freecadweb.org"
## @package FemMaterialReinforced
# \ingroup FEM
# \brief FreeCAD FEM _FemMaterialReinforced
class _FemMaterialReinforced:
"The FemMaterialReinforced object"
def __init__(self, obj):
obj.addProperty(
"App::PropertyLinkSubList",
"References",
"Material",
"List of material shapes"
)
obj.addProperty(
"App::PropertyMap",
"Reinforcement",
"Composites",
"Reinforcement material properties"
)
obj.addProperty(
"App::PropertyEnumeration",
"Category",
"Material",
"Matrix material properties"
)
obj.Category = ['Solid']
obj.Category = 'Solid'
obj.Proxy = self
self.Type = "Fem::MaterialReinforced"
def execute(self, obj):
return

View File

@@ -80,6 +80,56 @@ class _FemResultMechanical():
"List of equivalent plastic strain values",
True
)
obj.addProperty(
"App::PropertyFloatList",
"MohrCoulomb",
"NodeData",
"List of Mohr Coulomb stress values",
True
)
obj.addProperty(
"App::PropertyFloatList",
"ReinforcementRatio_x",
"NodeData",
"Reinforcement ratio x-direction",
True
)
obj.addProperty(
"App::PropertyFloatList",
"ReinforcementRatio_y",
"NodeData",
"Reinforcement ratio y-direction",
True
)
obj.addProperty(
"App::PropertyFloatList",
"ReinforcementRatio_z",
"NodeData",
"Reinforcement ratio z-direction",
True
)
obj.addProperty(
"App::PropertyVectorList",
"PS1Vector",
"NodeData",
"List of 1st Principal Stress Vectors",
True
)
obj.addProperty(
"App::PropertyVectorList",
"PS2Vector",
"NodeData",
"List of 2nd Principal Stress Vectors",
True
)
obj.addProperty(
"App::PropertyVectorList",
"PS3Vector",
"NodeData",
"List of 3rd Principal Stress Vectors",
True
)
# readonly in propertyEditor of comboView
obj.addProperty(
"App::PropertyFloatList",

View File

@@ -310,7 +310,7 @@ def add_von_mises(res_obj):
return res_obj
def add_principal_stress(res_obj):
def add_principal_stress_std(res_obj):
prinstress1 = []
prinstress2 = []
prinstress3 = []
@@ -324,7 +324,7 @@ def add_principal_stress(res_obj):
res_obj.NodeStressYZ
)
for Sxx, Syy, Szz, Sxy, Sxz, Syz in iterator:
prin1, prin2, prin3, shear = calculate_principal_stress((Sxx, Syy, Szz, Sxy, Sxz, Syz))
prin1, prin2, prin3, shear = calculate_principal_stress_std((Sxx, Syy, Szz, Sxy, Sxz, Syz))
prinstress1.append(prin1)
prinstress2.append(prin2)
prinstress3.append(prin3)
@@ -337,6 +337,165 @@ def add_principal_stress(res_obj):
return res_obj
def get_concrete_nodes(res_obj):
#
# HarryvL: determine concrete / non-concrete nodes
#
from femmesh.meshtools import get_femnodes_by_refshape
femmesh = res_obj.Mesh.FemMesh
nsr = femmesh.NodeCount # nsr number of stress results
# ic[iic]:
# ic = flag for material type; iic = node number
# ic = 0: NOT ASSIGNED
# ic = 1: ReinforcedMaterial
# ic = 2: NOT ReinforcedMaterial
ic = np.zeros(nsr)
for obj in res_obj.getParentGroup().Group:
if obj.isDerivedFrom('App::MaterialObjectPython') \
and femutils.is_of_type(obj, 'Fem::MaterialReinforced'):
print("ReinforcedMaterial")
if obj.References == []:
for iic in range(nsr):
if ic[iic] == 0:
ic[iic] = 1
else:
for ref in obj.References:
concrete_nodes = get_femnodes_by_refshape(femmesh, ref)
for cn in concrete_nodes:
ic[cn - 1] = 1
elif obj.isDerivedFrom('App::MaterialObjectPython') \
and femutils.is_of_type(obj, 'Fem::Material'):
print("NOT ReinforcedMaterial")
if obj.References == []:
for iic in range(nsr):
if ic[iic] == 0:
ic[iic] = 2
else:
for ref in obj.References:
non_concrete_nodes = get_femnodes_by_refshape(femmesh, ref)
for ncn in non_concrete_nodes:
ic[ncn - 1] = 2
return ic
def add_principal_stress_reinforced(res_obj):
#
# HarryvL: determine concrete / non-concrete nodes
#
ic = get_concrete_nodes(res_obj)
#
# calculate principal and max Shear and fill them in res_obj
#
prinstress1 = []
prinstress2 = []
prinstress3 = []
shearstress = []
ps1v = []
ps2v = []
ps3v = []
#
# HarryvL: additional arrays to hold reinforcement ratios
# and mohr coulomb stress
#
rhx = []
rhy = []
rhz = []
moc = []
# material parameter
for obj in res_obj.getParentGroup().Group:
if femutils.is_of_type(obj, 'Fem::MaterialReinforced'):
matrix_af = float(
FreeCAD.Units.Quantity(obj.Material['AngleOfFriction']).getValueAs('rad')
)
matrix_cs = float(
FreeCAD.Units.Quantity(obj.Material['CompressiveStrength']).getValueAs('MPa')
)
reinforce_yield = float(
FreeCAD.Units.Quantity(obj.Reinforcement['YieldStrength']).getValueAs('MPa')
)
# print(matrix_af)
# print(matrix_cs)
# print(reinforce_yield)
iterator = zip(
res_obj.NodeStressXX,
res_obj.NodeStressYY,
res_obj.NodeStressZZ,
res_obj.NodeStressXY,
res_obj.NodeStressXZ,
res_obj.NodeStressYZ
)
for isv, stress_tensor in enumerate(iterator):
rhox = 0.
rhoy = 0.
rhoz = 0.
mc = 0.
if ic[isv] == 1:
#
# HarryvL: for concrete scxx etc. are affected by
# reinforcement (see calculate_rho(stress_tensor)). for all other
# materials scxx etc. are the original stresses
#
rhox, rhoy, rhoz = calculate_rho(
stress_tensor,
reinforce_yield
)
prin1, prin2, prin3, shear, psv = calculate_principal_stress_reinforced(
stress_tensor
)
prinstress1.append(prin1)
prinstress2.append(prin2)
prinstress3.append(prin3)
shearstress.append(shear)
ps1v.append(psv[0])
ps2v.append(psv[1])
ps3v.append(psv[2])
#
# reinforcement ratios and mohr coulomb criterion
#
rhx.append(rhox)
rhy.append(rhoy)
rhz.append(rhoz)
if ic[isv] == 1:
mc = calculate_mohr_coulomb(prin1, prin3, matrix_af, matrix_cs)
moc.append(mc)
res_obj.PrincipalMax = prinstress1
res_obj.PrincipalMed = prinstress2
res_obj.PrincipalMin = prinstress3
res_obj.MaxShear = shearstress
#
# HarryvL: additional concrete and principal stress plot
# results for use in _ViewProviderFemResultMechanical
#
res_obj.ReinforcementRatio_x = rhx
res_obj.ReinforcementRatio_y = rhy
res_obj.ReinforcementRatio_z = rhz
res_obj.MohrCoulomb = moc
res_obj.PS1Vector = ps1v
res_obj.PS2Vector = ps2v
res_obj.PS3Vector = ps3v
FreeCAD.Console.PrintMessage(
'Added principal stress and max shear values as well as'
'reinforcment rations, Mohr Coloumb values.\n'
)
return res_obj
def compact_result(res_obj):
'''
compacts result.Mesh and appropriate result.NodeNumbers
@@ -373,7 +532,7 @@ def calculate_von_mises(stress_tensor):
return np.sqrt(1.5 * np.linalg.norm(normal - pressure)**2 + 3.0 * np.linalg.norm(shear)**2)
def calculate_principal_stress(stress_tensor):
def calculate_principal_stress_std(stress_tensor):
s11 = stress_tensor[0] # Sxx
s22 = stress_tensor[1] # Syy
s33 = stress_tensor[2] # Szz
@@ -399,6 +558,223 @@ def calculate_principal_stress(stress_tensor):
# https://forum.freecadweb.org/viewtopic.php?f=22&t=33911&start=10#p284229
def calculate_principal_stress_reinforced(stress_tensor):
#
# HarryvL - calculate principal stress vectors and values
# - for total stresses use stress_tensor[0], stress_tensor[1], stress_tensor[2]
# on the diagonal of the stress tensor
#
# difference to the original method:
# https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=90#p296539
#
s11 = stress_tensor[0] # Sxx
s22 = stress_tensor[1] # Syy
s33 = stress_tensor[2] # Szz
s12 = stress_tensor[3] # Sxy
s31 = stress_tensor[4] # Sxz
s23 = stress_tensor[5] # Syz
sigma = np.array([
[s11, s12, s31],
[s12, s22, s23],
[s31, s23, s33]
]) # https://forum.freecadweb.org/viewtopic.php?f=18&t=24637&start=10#p240408
eigenvalues, eigenvectors = np.linalg.eig(sigma)
#
# HarryvL: suppress complex eigenvalue and vectors that may occur for
# near-zero (numerical noise) stress fields
#
eigenvalues = eigenvalues.real
eigenvectors = eigenvectors.real
eigenvectors[:, 0] = eigenvalues[0] * eigenvectors[:, 0]
eigenvectors[:, 1] = eigenvalues[1] * eigenvectors[:, 1]
eigenvectors[:, 2] = eigenvalues[2] * eigenvectors[:, 2]
idx = eigenvalues.argsort()[::-1]
eigenvalues = eigenvalues[idx]
eigenvectors = eigenvectors[:, idx]
maxshear = (eigenvalues[0] - eigenvalues[2]) / 2.0
return (eigenvalues[0], eigenvalues[1], eigenvalues[2], maxshear,
tuple([tuple(row) for row in eigenvectors.T]))
def calculate_rho(stress_tensor, fy):
#
# HarryvL - Calculation of Reinforcement Ratios and
# Concrete Stresses according to http://heronjournal.nl/53-4/3.pdf
# - See post:
# https://forum.freecadweb.org/viewtopic.php?f=18&t=28821
# fy: factored yield strength of reinforcement bars
#
rmin = 1.0e9
eqmin = 14
sxx = stress_tensor[0]
syy = stress_tensor[1]
szz = stress_tensor[2]
sxy = stress_tensor[3]
syz = stress_tensor[5]
sxz = stress_tensor[4]
rhox = np.zeros(15)
rhoy = np.zeros(15)
rhoz = np.zeros(15)
# i1=sxx+syy+szz NOT USED
# i2=sxx*syy+syy*szz+szz*sxx-sxy**2-sxz**2-syz**2 NOT USED
i3 = (sxx * syy * szz + 2 * sxy * sxz * syz - sxx * syz**2
- syy * sxz**2 - szz * sxy**2)
# Solution (5)
d = (sxx * syy - sxy**2)
if d != 0.:
rhoz[0] = i3 / d / fy
# Solution (6)
d = (sxx * szz - sxz**2)
if d != 0.:
rhoy[1] = i3 / d / fy
# Solution (7)
d = (syy * szz - syz**2)
if d != 0.:
rhox[2] = i3 / d / fy
# Solution (9)
if sxx != 0.:
fc = sxz * sxy / sxx - syz
fxy = sxy**2 / sxx
fxz = sxz**2 / sxx
# Solution (9+)
rhoy[3] = syy - fxy + fc
rhoy[3] /= fy
rhoz[3] = szz - fxz + fc
rhoz[3] /= fy
# Solution (9-)
rhoy[4] = syy - fxy - fc
rhoy[4] /= fy
rhoz[4] = szz - fxz - fc
rhoz[4] /= fy
# Solution (10)
if syy != 0.:
fc = syz * sxy / syy - sxz
fxy = sxy**2 / syy
fyz = syz**2 / syy
# Solution (10+)
rhox[5] = sxx - fxy + fc
rhox[5] /= fy
rhoz[5] = szz - fyz + fc
rhoz[5] /= fy
# Solution (10-)vm
rhox[6] = sxx - fxy - fc
rhox[6] /= fy
rhoz[6] = szz - fyz - fc
rhoz[6] /= fy
# Solution (11)
if szz != 0.:
fc = sxz * syz / szz - sxy
fxz = sxz**2 / szz
fyz = syz**2 / szz
# Solution (11+)
rhox[7] = sxx - fxz + fc
rhox[7] /= fy
rhoy[7] = syy - fyz + fc
rhoy[7] /= fy
# Solution (11-)
rhox[8] = sxx - fxz - fc
rhox[8] /= fy
rhoy[8] = syy - fyz - fc
rhoy[8] /= fy
# Solution (13)
rhox[9] = (sxx + sxy + sxz) / fy
rhoy[9] = (syy + sxy + syz) / fy
rhoz[9] = (szz + sxz + syz) / fy
# Solution (14)
rhox[10] = (sxx + sxy - sxz) / fy
rhoy[10] = (syy + sxy - syz) / fy
rhoz[10] = (szz - sxz - syz) / fy
# Solution (15)
rhox[11] = (sxx - sxy - sxz) / fy
rhoy[11] = (syy - sxy + syz) / fy
rhoz[11] = (szz - sxz + syz) / fy
# Solution (16)
rhox[12] = (sxx - sxy + sxz) / fy
rhoy[12] = (syy - sxy - syz) / fy
rhoz[12] = (szz + sxz - syz) / fy
# Solution (17)
if syz != 0.:
rhox[13] = (sxx - sxy * sxz / syz) / fy
if sxz != 0.:
rhoy[13] = (syy - sxy * syz / sxz) / fy
if sxy != 0.:
rhoz[13] = (szz - sxz * syz / sxy) / fy
for ir in range(0, rhox.size):
if rhox[ir] >= -1.e-10 and rhoy[ir] >= -1.e-10 and rhoz[ir] > -1.e-10:
# Concrete Stresses
scxx = sxx - rhox[ir] * fy
scyy = syy - rhoy[ir] * fy
sczz = szz - rhoz[ir] * fy
ic1 = (scxx + scyy + sczz)
ic2 = (scxx * scyy + scyy * sczz + sczz * scxx - sxy**2
- sxz**2 - syz**2)
ic3 = (scxx * scyy * sczz + 2 * sxy * sxz * syz - scxx * syz**2
- scyy * sxz**2 - sczz * sxy**2)
if ic1 <= 1.e-6 and ic2 >= -1.e-6 and ic3 <= 1.0e-6:
rsum = rhox[ir] + rhoy[ir] + rhoz[ir]
if rsum < rmin and rsum > 0.:
rmin = rsum
eqmin = ir
return rhox[eqmin], rhoy[eqmin], rhoz[eqmin]
def calculate_mohr_coulomb(prin1, prin3, phi, fck):
#
# HarryvL - Calculation of Mohr Coulomb yield criterion to judge
# concrete curshing and shear failure
# phi: angle of internal friction
# fck: factored compressive strength of the matrix material (usually concrete)
#
coh = fck * (1 - np.sin(phi)) / 2 / np.cos(phi)
mc_stress = ((prin1 - prin3) + (prin1 + prin3) * np.sin(phi)
- 2. * coh * np.cos(phi))
if mc_stress < 0.:
mc_stress = 0.
return mc_stress
def calculate_disp_abs(displacements):
# see https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=100#p296657
return [np.linalg.norm(nd) for nd in displacements]

View File

@@ -32,8 +32,6 @@ import subprocess
import os.path
import FreeCAD
if FreeCAD.GuiUp:
from PySide import QtGui
import femtools.femutils as femutils
import feminout.importCcxFrdResults as importCcxFrdResults
import feminout.importCcxDatResults as importCcxDatResults
@@ -42,6 +40,9 @@ from .. import run
from .. import settings
from . import writer
if FreeCAD.GuiUp:
from PySide import QtGui
_inputFileName = None
@@ -184,9 +185,14 @@ class _Container(object):
# get member
# materials
self.materials_linear = self.get_several_member(
std_mats = self.get_several_member(
'Fem::Material'
)
rei_mats = self.get_several_member(
'Fem::MaterialReinforced'
)
self.materials_linear = std_mats + rei_mats
self.materials_nonlinear = self.get_several_member(
'Fem::MaterialMechanicalNonlinear'
)

View File

@@ -31,8 +31,6 @@ import subprocess
import os.path
import FreeCAD
if FreeCAD.GuiUp:
from PySide import QtGui
import femtools.femutils as femutils
import feminout.importZ88O2Results as importZ88O2Results
@@ -40,6 +38,9 @@ from .. import run
from .. import settings
from . import writer
if FreeCAD.GuiUp:
from PySide import QtGui
class Check(run.Check):

View File

@@ -29,8 +29,6 @@ import unittest
from . import utilstest as testtools
from .utilstest import fcc_print
from os.path import join
class TestFemCommon(unittest.TestCase):
fcc_print('import TestFemCommon')
@@ -59,9 +57,9 @@ class TestFemCommon(unittest.TestCase):
slab.Width = 500.00
cf = ObjectsFem.makeConstraintFixed(doc)
ref_eles = []
# FreeCAD list property seam not to support append,
# thus we need some workaround
# which is on many elements even much faster
# FreeCAD list property doesn't seem to support append,
# thus we need a workaround
# which on many elements is even much faster
for i, face in enumerate(slab.Shape.Edges):
ref_eles.append("Edge%d" % (i + 1))
cf.References = [(slab, ref_eles)]
@@ -77,11 +75,11 @@ class TestFemCommon(unittest.TestCase):
def test_pyimport_all_FEM_modules(
self
):
# we're going to try to import all python modules from FreeCAD Fem
# we're going to try to import all python modules from FreeCAD FEM
pymodules = []
# collect all Python modules in Fem
pymodules += testtools.collect_python_modules('') # Fem main dir
# collect all Python modules in FEM
pymodules += testtools.collect_python_modules('') # FEM main dir
pymodules += testtools.collect_python_modules('femexamples')
pymodules += testtools.collect_python_modules('feminout')
pymodules += testtools.collect_python_modules('femmesh')
@@ -90,8 +88,8 @@ class TestFemCommon(unittest.TestCase):
pymodules += testtools.collect_python_modules('femtest')
pymodules += testtools.collect_python_modules('femtools')
pymodules += testtools.collect_python_modules('femsolver')
# TODO test with join on windows, the use of os.path.join
# in following code seams to make problems on windws os
# TODO test with join on Windows, the use of os.path.join
# in the following code seems to create problems on Windows OS
pymodules += testtools.collect_python_modules('femsolver/elmer')
pymodules += testtools.collect_python_modules('femsolver/elmer/equations')
pymodules += testtools.collect_python_modules('femsolver/z88')

View File

@@ -82,6 +82,7 @@ class TestObjectCreate(unittest.TestCase):
analysis.addObject(ObjectsFem.makeMaterialFluid(doc))
mat = analysis.addObject(ObjectsFem.makeMaterialSolid(doc))[0]
analysis.addObject(ObjectsFem.makeMaterialMechanicalNonlinear(doc, mat))
analysis.addObject(ObjectsFem.makeMaterialReinforced(doc))
msh = analysis.addObject(ObjectsFem.makeMeshGmsh(doc))[0]
analysis.addObject(ObjectsFem.makeMeshBoundaryLayer(doc, msh))
@@ -266,6 +267,10 @@ class TestObjectType(unittest.TestCase):
'Fem::MaterialMechanicalNonlinear',
type_of_obj(ObjectsFem.makeMaterialMechanicalNonlinear(doc, materialsolid))
)
self.assertEqual(
'Fem::MaterialReinforced',
type_of_obj(ObjectsFem.makeMaterialReinforced(doc))
)
mesh = ObjectsFem.makeMeshGmsh(doc)
self.assertEqual(
'Fem::FemMeshGmsh',
@@ -330,7 +335,7 @@ class TestObjectType(unittest.TestCase):
'Fem::FemEquationElmerHeat',
type_of_obj(ObjectsFem.makeEquationHeat(doc, solverelmer))
)
# is = 43 (just copy in empty file to test)
# is = 44 tests (just copy in empty file to test)
# TODO: vtk post objs
# TODO: use different type for fluid and solid material
@@ -450,6 +455,10 @@ class TestObjectType(unittest.TestCase):
ObjectsFem.makeMaterialMechanicalNonlinear(doc, materialsolid),
'Fem::MaterialMechanicalNonlinear'
))
self.assertTrue(is_of_type(
ObjectsFem.makeMaterialReinforced(doc),
'Fem::MaterialReinforced'
))
mesh = ObjectsFem.makeMeshGmsh(doc)
self.assertTrue(is_of_type(
mesh,
@@ -516,7 +525,7 @@ class TestObjectType(unittest.TestCase):
ObjectsFem.makeEquationHeat(doc, solverelmer),
'Fem::FemEquationElmerHeat'
))
# is = 43 (just copy in empty file to test)
# is = 44 tests (just copy in empty file to test)
# ********************************************************************************************
def test_femobjects_derivedfromfem(
@@ -899,6 +908,20 @@ class TestObjectType(unittest.TestCase):
'Fem::MaterialMechanicalNonlinear'
))
# MaterialReinforced
self.assertTrue(is_derived_from(
ObjectsFem.makeMaterialReinforced(doc),
'App::DocumentObject'
))
self.assertTrue(is_derived_from(
ObjectsFem.makeMaterialReinforced(doc),
'App::MaterialObjectPython'
))
self.assertTrue(is_derived_from(
ObjectsFem.makeMaterialReinforced(doc),
'Fem::MaterialReinforced'
))
# FemMeshGmsh
self.assertTrue(is_derived_from(
mesh, 'App::DocumentObject'
@@ -1270,6 +1293,11 @@ class TestObjectType(unittest.TestCase):
materialsolid
).isDerivedFrom('Fem::FeaturePython')
)
self.assertTrue(
ObjectsFem.makeMaterialReinforced(
doc
).isDerivedFrom('App::MaterialObjectPython')
)
mesh = ObjectsFem.makeMeshGmsh(doc)
self.assertTrue(
mesh.isDerivedFrom('Fem::FemMeshObjectPython')
@@ -1356,7 +1384,7 @@ class TestObjectType(unittest.TestCase):
solverelmer
).isDerivedFrom('App::FeaturePython')
)
# is = 43 (just copy in empty file to test)
# is = 44 tests (just copy in empty file to test)
# ********************************************************************************************
def tearDown(

View File

@@ -313,11 +313,11 @@ class TestResult(unittest.TestCase):
)
# ********************************************************************************************
def test_stress_principal(
def test_stress_principal_std(
self
):
expected_principal = (-178.0076, -194.0749, -468.9075, 145.4499)
from femresult.resulttools import calculate_principal_stress as pr
from femresult.resulttools import calculate_principal_stress_std as pr
prin = pr(self.get_stress_values())
rounded_prin = (
round(prin[0], 4),
@@ -332,6 +332,102 @@ class TestResult(unittest.TestCase):
"Calculated principal stresses are not the expected values."
)
# ********************************************************************************************
def test_stress_principal_reinforced(
self
):
expected_principal = (-178.0076, -194.0749, -468.9075, 145.4499)
from femresult.resulttools import calculate_principal_stress_reinforced as prrc
prin = prrc(self.get_stress_values())
rounded_prin = (
round(prin[0], 4),
round(prin[1], 4),
round(prin[2], 4),
round(prin[3], 4))
# fcc_print(rounded_prin)
self.assertEqual(
rounded_prin,
expected_principal,
"Calculated principal reinforced stresses are not the expected values."
)
# ********************************************************************************************
def test_rho(
self
):
data = (
(
# Case1: Governing Eq.14
(2.000, -2.000, 5.000, 6.000, -4.000, 2.000),
(0.02400, 0.00400, 0.01400)
),
(
# Case2: Governing Eq.10+
(-3.000, -7.000, 0.000, 6.000, -4.000, 2.000),
(0.00886, 0.00000, 0.00571),
),
(
# Case3: Governing Eq.5
(-1.000, -7.000, 10.000, 0.000, 0.000, 5.000),
(0.00000, 0.00000, 0.02714)
),
(
# Case4: Governing Eq.13
(3.000, 0.000, 10.000, 0.000, 5.000, 0.000),
(0.01600, 0.00000, 0.03000)
),
(
# Case5: Governing Eq.11-
(10.000, 7.000, -3.000, 3.000, 1.000, -2.000),
(0.02533, 0.02133, 0.00000)
),
(
# Case6: Governing Eq.14
(4.000, -7.000, 3.000, 7.000, 0.000, -5.000),
(0.02200, 0.01000, 0.01600)
),
(
# Case7: Governing Eq.14
(8.000, -14.000, 6.000, 14.000, 0.000, -10.000),
(0.04400, 0.02000, 0.03200)
),
(
# Case8: Governing Eq.17
(1.000, 0.000, 3.000, 10.000, -8.000, 7.000),
(0.02486, 0.01750, 0.01720)
),
(
# Case9: Governing Eq.13
(0.000, 0.000, 0.000, 10.000, 8.000, 7.000),
(0.03600, 0.03400, 0.03000)
),
(
# Case10: Governing Eq.13
(15.000, 0.000, 0.000, 0.000, 0.000, 0.000),
(0.03000, 0.00000, 0.00000)
),
(
# Case11: Governing Eq.13
(0.000, 0.000, 0.000, 5.000, 0.000, 0.000),
(0.01000, 0.01000, 0.00000)
)
)
from femresult.resulttools import calculate_rho as calrho
for i, case in enumerate(data):
res = calrho(case[0], 500)
rhores = (
round(res[0], 5),
round(res[1], 5),
round(res[2], 5)
)
# fcc_print('Case{}: {}'.format(i + 1 , rhores))
self.assertEqual(
rhores, case[1],
"Calculated rho are not the expected Case{}."
.format(i + 1)
)
# ********************************************************************************************
def test_disp_abs(
self

View File

@@ -223,7 +223,10 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject):
## @var materials_linear
# list of linear materials from the analysis. Updated with update_objects
self.materials_linear = self._get_several_member('Fem::Material')
self.materials_linear = (
self._get_several_member('Fem::Material')
+ self._get_several_member('Fem::MaterialReinforced')
)
## @var materials_nonlinear
# list of nonlinear materials from the analysis. Updated with update_objects
self.materials_nonlinear = self._get_several_member('Fem::MaterialMechanicalNonlinear')
@@ -408,6 +411,47 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject):
"Thermomechanical analysis: No SpecificHeat "
"defined for at least one material.\n" # allowed to be 0.0 (in ccx)
)
if femutils.is_of_type(mat_obj, 'Fem::MaterialReinforced'):
# additional tests for reinforced materials,
# they are needed for result calculation not for ccx analysis
mat_map_m = mat_obj.Material
if 'AngleOfFriction' in mat_map_m:
# print(Units.Quantity(mat_map_m['AngleOfFriction']).Value)
if not Units.Quantity(mat_map_m['AngleOfFriction']).Value:
message += (
"Value of AngleOfFriction is set to 0.0 "
"for the matrix of a reinforced material.\n"
)
else:
message += (
"No AngleOfFriction defined for the matrix "
"of at least one reinforced material.\n"
)
if 'CompressiveStrength' in mat_map_m:
# print(Units.Quantity(mat_map_m['CompressiveStrength']).Value)
if not Units.Quantity(mat_map_m['CompressiveStrength']).Value:
message += (
"Value of CompressiveStrength is set to 0.0 "
"for the matrix of a reinforced material.\n"
)
else:
message += (
"No CompressiveStrength defined for the matrinx "
"of at least one reinforced material.\n"
)
mat_map_r = mat_obj.Reinforcement
if 'YieldStrength' in mat_map_r:
# print(Units.Quantity(mat_map_r['YieldStrength']).Value)
if not Units.Quantity(mat_map_r['YieldStrength']).Value:
message += (
"Value of YieldStrength is set to 0.0 "
"for the reinforcement of a reinforced material.\n"
)
else:
message += (
"No YieldStrength defined for the reinforcement "
"of at least one reinforced material.\n"
)
if len(self.materials_linear) == 1:
mobj = self.materials_linear[0]['Object']
if hasattr(mobj, 'References') and mobj.References:

View File

@@ -0,0 +1,20 @@
; Concrete-EN-C35_45
; (c) 2019 Bernd Hahnebach (CC-BY 3.0)
; information about the content of such cards can be found on the wiki:
; https://www.freecadweb.org/wiki/Material
; file created by FreeCAD 0.19.16886 (Git)
[General]
Name = Concrete-EN-C35/45
Description = Concrete matrix for reinforcement material examples, 0.6 x 0.75 x 35 MPa = 15.75 MPa (https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=200#p311075)
Father = Aggregate
[Mechanical]
AngleOfFriction = 30 deg
CompressiveStrength = 15.75 MPa
Density = 2500 kg/m^3
PoissonRatio = 0.17
YoungsModulus = 32000 MPa
[Cost]
ProductURL = https://en.wikipedia.org/wiki/Concrete

View File

@@ -0,0 +1,15 @@
; Reinforcement-FIB-B500
; (c) 2019 Bernd Hahnebach (CC-BY 3.0)
; information about the content of such cards can be found on the wiki:
; https://www.freecadweb.org/wiki/Material
; file created by FreeCAD 0.19.16886 (Git)
[General]
Name = Reinforcement-Harry
Description = Reinforcement inside concrete for reinforcement material examples, from fib examples, 0.84 x 0.75 x 500 MPa = 315 MPa (https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=200#p311705)
[Mechanical]
Density = 7850 kg/m^3
PoissonRatio = 0.3
YieldStrength = 315 MPa
YoungsModulus = 210000 MPa

View File

@@ -6,6 +6,7 @@ AlMgSi1F31|AlMgSi1F31|AlMgSi1F31|||||Metal|Aluminium|Aluminium|3.2315.72|DIN 172
Aluminum-6061-T6|Aluminum 6061-T6|||Precipitation-hardened, Nonferrous Aluminum alloy|||Metal|Aluminium|Aluminium||||||||2700 kg/m^3||0.33|||310 MPa||69000 MPa||167 W/m/K|||||||||||||||||||||||||https://en.wikipedia.org/wiki/6061_aluminium_alloy||
AlZn4-5Mg1F35|AlZn4,5Mg1F35|AlZn4,5Mg1F35|||||Metal|Aluminium|Aluminium|3.4335.71|DIN 1725||||||2700 kg/m^3||0.3|27000 MPa|10|350 MPa|290 MPa|70000 MPa|||0.000023 m/m/K||||||||||||||||||||||||||
CalculiX-Steel|CalculiX-Steel|||Standard steel material for CalculiX sample calculations|||Metal||||||||||7900 kg/m^3||0.3|||||210000 MPa|590 J/kg/K|43 W/m/K|0.000012 m/m/K||||||||||||||||||||||||||
Concrete-EN-C35_45|Concrete-EN-C35/45|||Concrete matrix for reinforcement material examples, 0.6 x 0.75 x 35 MPa = 15.75 MPa (https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=200#p311075)|||Aggregate||||||||30 deg|15.75 MPa|2500 kg/m^3||0.17|||||32000 MPa|||||||||||||||||||||||||||https://en.wikipedia.org/wiki/Concrete||
Concrete-Generic|Concrete|||A standard C-25 construction concrete|||Aggregate|||||||Masterformat 03 33 13||25 MPa|2400 kg/m^3||0.17|||||32000 MPa|||||||||||||||||||||||||||https://en.wikipedia.org/wiki/Concrete||
Glass-E-GlassFibre|Glass-E|||Glass Fibre|||Glass|||||||||1080 MPa|2580 kg/m^3|||||3445 MPa|||||||||||||||||||||||||||||https://en.wikipedia.org/wiki/Glass_fiber||
Glass-Generic|Glass|||Generic soda-lime glass|Normalglas|Szkło sodowe|Glass||||||||||2520 kg/m^3||0.22|||||72000 MPa|||0.000009 m/m/K||||||||||||||||||||||||https://en.wikipedia.org/wiki/Soda-lime_glass||
@@ -17,6 +18,7 @@ PLA-Generic|PLA|||Polylactic acid or polylactide (PLA, Poly) is a biodegradable
PP-Generic|Polypropylene||||||||||||http://www.matweb.com/search/DataSheet.aspx?MatGUID=a882a1c603374e278d062f106dfda95b|||10 MPa|916 kg/m^3||0.44|||79.7 MPa|32.8 MPa|1470 MPa|1920 J/kg/K|0.249 W/m/K|0.000123 m/m/K||||||||||||||||||||||||https://en.wikipedia.org/wiki/Polypropylene||
PTFE-Generic|PTFE||||||||||||http://www.matweb.com/search/datasheet.aspx?MatGUID=4d14eac958e5401a8fd152e1261b6843|||10.2 MPa|2070 kg/m^3||0.46|||34.6 MPa|20.5 MPa|564 MPa|1010 J/kg/K|0.263 W/m/K|0.000108 m/m/K||||||||||||||||||||||||https://en.wikipedia.org/wiki/Polytetrafluoroethylene||
PVC-Generic|PVC||||||||||||http://www.matweb.com/search/DataSheet.aspx?MatGUID=1f650966ec834bb8833dd4c6e3116079||||1380 kg/m^3||0.38|||50 MPa||2800 MPa|1000 J/kg/K|0.150 W/m/K|0.000075 m/m/K||||||||||||||||||||||||https://en.wikipedia.org/wiki/Polyvinyl_chloride||
Reinforcement-FIB-B500|Reinforcement-Harry|||Reinforcement inside concrete for reinforcement material examples, from fib examples, 0.84 x 0.75 x 500 MPa = 315 MPa (https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=200#p311705)|||||||||||||7850 kg/m^3||0.3||||315 MPa|210000 MPa|||||||||||||||||||||||||||||
Steel-15CrNi6|15CrNi6|||High-strength carbon steel|höchste Beanspruchung, Achsen, Wellen, Ritzel, Nocken, Kegelräder|Wysokowytrzymała stal węglowa|Metal|Case-hardened steel|Einsatzstahl|1.5919|EN 10084||||||7800 kg/m^3||0.3|81000 MPa|9|1000 MPa|680 MPa|210000 MPa|||0.000011 m/m/K||||||||||||||||||||||||||
Steel-17CrNiMo6|17CrNiMo6|17CrNiMo6|||höchste Beanspruchung, Wellen, Zahnräder||Metal|Case-hardened steel|Einsatzstahl|1.6587|EN 10084||||||7800 kg/m^3||0.3|81000 MPa|8|1150 MPa|830 MPa|210000 MPa|||0.000011 m/m/K||||||||||||||||||||||||||
Steel-1C22|1C22|C22||Case hardened alloy steel|kleiner Vergütungsdurchmesser, gut schweißbar|Stal stopowa do nawęglania|Metal|Heat-treatable steel|Vergütungsstahl|1.0402|EN 10083-1||||||7800 kg/m^3||0.3|81000 MPa|27|400 MPa|230 MPa|210000 MPa|||0.000011 m/m/K||||||||||||||||||||||||||
1 FileName Name NameDE NamePL Description DescriptionDE DescriptionPL Father KindOfMaterial KindOfMaterialDE MaterialNumber Norm ReferenceSource SourceURL StandardCode AngleOfFriction CompressiveStrength Density FractureToughness PoissonRatio ShearModulus UltimateStrain UltimateTensileStrength YieldStrength YoungsModulus SpecificHeat ThermalConductivity ThermalExpansionCoefficient Color EnvironmentalEfficiencyClass ExecutionInstructions Finish FireResistanceClass Model SoundTransmissionClass UnitsPerQuantity AmbientColor DiffuseColor EmissiveColor FragmentShader Shininess SpecularColor TexturePath TextureScaling Transparency VertexShader SectionFillPattern SectionLinewidth ViewColor ViewFillPattern ViewLinewidth ProductURL SpecificPrice Vendor
6 Aluminum-6061-T6 Aluminum 6061-T6 Precipitation-hardened, Nonferrous Aluminum alloy Metal Aluminium Aluminium 2700 kg/m^3 0.33 310 MPa 69000 MPa 167 W/m/K https://en.wikipedia.org/wiki/6061_aluminium_alloy
7 AlZn4-5Mg1F35 AlZn4,5Mg1F35 AlZn4,5Mg1F35 Metal Aluminium Aluminium 3.4335.71 DIN 1725 2700 kg/m^3 0.3 27000 MPa 10 350 MPa 290 MPa 70000 MPa 0.000023 m/m/K
8 CalculiX-Steel CalculiX-Steel Standard steel material for CalculiX sample calculations Metal 7900 kg/m^3 0.3 210000 MPa 590 J/kg/K 43 W/m/K 0.000012 m/m/K
9 Concrete-EN-C35_45 Concrete-EN-C35/45 Concrete matrix for reinforcement material examples, 0.6 x 0.75 x 35 MPa = 15.75 MPa (https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=200#p311075) Aggregate 30 deg 15.75 MPa 2500 kg/m^3 0.17 32000 MPa https://en.wikipedia.org/wiki/Concrete
10 Concrete-Generic Concrete A standard C-25 construction concrete Aggregate Masterformat 03 33 13 25 MPa 2400 kg/m^3 0.17 32000 MPa https://en.wikipedia.org/wiki/Concrete
11 Glass-E-GlassFibre Glass-E Glass Fibre Glass 1080 MPa 2580 kg/m^3 3445 MPa https://en.wikipedia.org/wiki/Glass_fiber
12 Glass-Generic Glass Generic soda-lime glass Normalglas Szkło sodowe Glass 2520 kg/m^3 0.22 72000 MPa 0.000009 m/m/K https://en.wikipedia.org/wiki/Soda-lime_glass
18 PP-Generic Polypropylene http://www.matweb.com/search/DataSheet.aspx?MatGUID=a882a1c603374e278d062f106dfda95b 10 MPa 916 kg/m^3 0.44 79.7 MPa 32.8 MPa 1470 MPa 1920 J/kg/K 0.249 W/m/K 0.000123 m/m/K https://en.wikipedia.org/wiki/Polypropylene
19 PTFE-Generic PTFE http://www.matweb.com/search/datasheet.aspx?MatGUID=4d14eac958e5401a8fd152e1261b6843 10.2 MPa 2070 kg/m^3 0.46 34.6 MPa 20.5 MPa 564 MPa 1010 J/kg/K 0.263 W/m/K 0.000108 m/m/K https://en.wikipedia.org/wiki/Polytetrafluoroethylene
20 PVC-Generic PVC http://www.matweb.com/search/DataSheet.aspx?MatGUID=1f650966ec834bb8833dd4c6e3116079 1380 kg/m^3 0.38 50 MPa 2800 MPa 1000 J/kg/K 0.150 W/m/K 0.000075 m/m/K https://en.wikipedia.org/wiki/Polyvinyl_chloride
21 Reinforcement-FIB-B500 Reinforcement-Harry Reinforcement inside concrete for reinforcement material examples, from fib examples, 0.84 x 0.75 x 500 MPa = 315 MPa (https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=200#p311705) 7850 kg/m^3 0.3 315 MPa 210000 MPa
22 Steel-15CrNi6 15CrNi6 High-strength carbon steel höchste Beanspruchung, Achsen, Wellen, Ritzel, Nocken, Kegelräder Wysokowytrzymała stal węglowa Metal Case-hardened steel Einsatzstahl 1.5919 EN 10084 7800 kg/m^3 0.3 81000 MPa 9 1000 MPa 680 MPa 210000 MPa 0.000011 m/m/K
23 Steel-17CrNiMo6 17CrNiMo6 17CrNiMo6 höchste Beanspruchung, Wellen, Zahnräder Metal Case-hardened steel Einsatzstahl 1.6587 EN 10084 7800 kg/m^3 0.3 81000 MPa 8 1150 MPa 830 MPa 210000 MPa 0.000011 m/m/K
24 Steel-1C22 1C22 C22 Case hardened alloy steel kleiner Vergütungsdurchmesser, gut schweißbar Stal stopowa do nawęglania Metal Heat-treatable steel Vergütungsstahl 1.0402 EN 10083-1 7800 kg/m^3 0.3 81000 MPa 27 400 MPa 230 MPa 210000 MPa 0.000011 m/m/K

View File

@@ -4,7 +4,7 @@
FCMAT_DIR="../"
MATERIALS_FILE=Materials
# Remove exisitng $MATERIALS_FILE.csv
# Remove existing $MATERIALS_FILE.csv
if [ -f "$MATERIALS_FILE.csv" ]
then
rm $MATERIALS_FILE.csv

View File

@@ -89,7 +89,7 @@ def decode(name):
# in the module Material.py is another implementation of reading and writing FCMat files
# this implementation uses the ConfigParser module
# in ViewProviderFemMaterial in add_cards_from_a_dir() the parser from Material.py is used
# since this mixture seams to be there for ages it should not be changed for 0.18
# since this mixture seems to have be there for ages it should not be changed for 0.18
# TODO: get rid of this mixture in FreeCAD 0.19
# Metainformation
@@ -102,7 +102,7 @@ def decode(name):
def read(filename):
"reads a FCMat file and returns a dictionary from it"
# the reader should return a dictionary in any case even if the file
# has problems, a empty dict shuld be returned un such case
# has problems, an empty dict should be returned in such case
if isinstance(filename, unicode):
if sys.version_info.major < 3:
filename = filename.encode(sys.getfilesystemencoding())
@@ -117,7 +117,7 @@ def read(filename):
for ln, line in enumerate(f):
ln += 1 # enumerate starts with 0, but we would like to have the real line number
if line.startswith('#'):
# a # is assumed to be a comment which is ignored
# a '#' is assumed to be a comment which is ignored
continue
# the use of line number is not smart for a data model
# a wrong user edit could break the file
@@ -141,7 +141,7 @@ def read(filename):
# [ is a Section
if line[0] not in ";[":
# split once on first occurrence
# a link could contain a = and thus would be split
# a link could contain a '=' and thus would be split
k = line.split("=", 1)
if len(k) == 2:
v = k[1].strip()
@@ -223,7 +223,7 @@ def write(filename, dictionary, write_group_section=True):
f.write("\n[" + s["keyname"] + "]\n")
for k, i in s.items():
if (k != "keyname" and i != '') or k == "Name":
# use only keys which are not empty and the name even if empty
# use only keys which are not empty and the name, even if empty
if sys.version_info.major >= 3:
f.write(k + " = " + i + "\n")
else:

View File

@@ -607,7 +607,8 @@ def output_value_unit_info(param, value):
def check_mat_units(mat):
known_quantities = get_known_material_quantity_parameter()
# check if the param is a Quantity according card template, than chaeck unit
# check if the param is a Quantity according to the card template
# then check unit
# print(known_quantities)
units_ok = True
for param, value in mat.items():

View File

@@ -48,6 +48,7 @@
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <BRepExtrema_DistShapeShape.hxx>
# include <BRepIntCurveSurface_Inter.hxx>
# include <TopTools_HSequenceOfShape.hxx>
# include <ShapeExtend_Explorer.hxx>
# include <GProp_GProps.hxx>
@@ -2061,17 +2062,8 @@ Base::Placement AttachEnginePoint::calculateAttachedPlacement(Base::Placement or
throw Base::ValueError("Null shape in AttachEnginePoint::calculateAttachedPlacement()!");
if (shapes[1]->IsNull())
throw Base::ValueError("Null shape in AttachEnginePoint::calculateAttachedPlacement()!");
BRepExtrema_DistShapeShape distancer (*(shapes[0]), *(shapes[1]));
if (!distancer.IsDone())
throw Base::ValueError("AttachEnginePoint::calculateAttachedPlacement: proximity calculation failed.");
if (distancer.NbSolution()>1)
Base::Console().Warning("AttachEnginePoint::calculateAttachedPlacement: proximity calculation gave %i solutions, ambiguous.\n",int(distancer.NbSolution()));
gp_Pnt p1 = distancer.PointOnShape1(1);
gp_Pnt p2 = distancer.PointOnShape2(1);
if (mmode == mm0ProximityPoint1)
BasePoint = p1;
else
BasePoint = p2;
BasePoint = getProximityPoint(mmode, *(shapes[0]), *(shapes[1]));
}break;
case mm0CenterOfMass:{
GProp_GProps gpr = AttachEngine::getInertialPropsOfShape(shapes);
@@ -2093,3 +2085,61 @@ Base::Placement AttachEnginePoint::calculateAttachedPlacement(Base::Placement or
return plm;
}
gp_Pnt AttachEnginePoint::getProximityPoint(eMapMode mmode, const TopoDS_Shape& s1, const TopoDS_Shape& s2) const
{
// #0003921: Crash when opening document with datum point intersecting line and plane
//
// BRepExtrema_DistanceSS is used inside BRepExtrema_DistShapeShape and can cause
// a crash if the input shape is an unlimited face.
// So, when the input is a face and an edge then before checking for minimum distances
// try to determine intersection points.
try {
TopoDS_Shape face, edge;
if (s1.ShapeType() == TopAbs_FACE &&
s2.ShapeType() == TopAbs_EDGE) {
face = s1;
edge = s2;
}
else if (s1.ShapeType() == TopAbs_EDGE &&
s2.ShapeType() == TopAbs_FACE) {
edge = s1;
face = s2;
}
// edge and face
if (!edge.IsNull() && !face.IsNull()) {
BRepAdaptor_Curve crv(TopoDS::Edge(edge));
BRepIntCurveSurface_Inter intCS;
intCS.Init(face, crv.Curve(), Precision::Confusion());
std::vector<gp_Pnt> points;
for (; intCS.More(); intCS.Next()) {
gp_Pnt pnt = intCS.Pnt();
points.push_back(pnt);
}
if (points.size() > 1)
Base::Console().Warning("AttachEnginePoint::calculateAttachedPlacement: proximity calculation gave %d solutions, ambiguous.\n", int(points.size()));
// if an intersection is found return the first hit
// otherwise continue with BRepExtrema_DistShapeShape
if (!points.empty())
return points.front();
}
}
catch (Standard_Failure) {
// ignore
}
BRepExtrema_DistShapeShape distancer (s1, s2);
if (!distancer.IsDone())
throw Base::ValueError("AttachEnginePoint::calculateAttachedPlacement: proximity calculation failed.");
if (distancer.NbSolution() > 1)
Base::Console().Warning("AttachEnginePoint::calculateAttachedPlacement: proximity calculation gave %i solutions, ambiguous.\n",int(distancer.NbSolution()));
gp_Pnt p1 = distancer.PointOnShape1(1);
gp_Pnt p2 = distancer.PointOnShape2(1);
if (mmode == mm0ProximityPoint1)
return p1;
else
return p2;
}

View File

@@ -456,6 +456,9 @@ public:
AttachEnginePoint();
virtual AttachEnginePoint* copy() const;
virtual Base::Placement calculateAttachedPlacement(Base::Placement origPlacement) const;
private:
gp_Pnt getProximityPoint(eMapMode mode, const TopoDS_Shape& s1, const TopoDS_Shape& s2) const;
};
//====================================================================

View File

@@ -34,7 +34,7 @@ import PathScripts.PathUtil as PathUtil
from PySide import QtCore, QtGui
# Qt tanslation handling
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)

View File

@@ -46,10 +46,10 @@ grbl_post.export(object, "/path/to/file.ncc")
# Default values for command line arguments:
OUTPUT_COMMENTS = True # default output of comments in output gCode file
OUTPUT_HEADER = True # default output header in output gCode file
OUTPUT_LINE_NUMBERS = False # default does'nt utput lines numbers in output gCode file
OUTPUT_LINE_NUMBERS = False # default doesn't output line numbers in output gCode file
SHOW_EDITOR = True # default show the resulting file dialog output in GUI
PRECISION = 3 # Default precision for metric (see http://linuxcnc.org/docs/2.7/html/gcode/overview.html#_g_code_best_practices)
TRANSLATE_DRILL_CYCLES = False # If true, G81, G82 & G83 are translated in G0/G1 moves
TRANSLATE_DRILL_CYCLES = False # If true, G81, G82 & G83 are translated in G0/G1 moves
PREAMBLE = '''G17 G90
''' # default preamble text will appear at the beginning of the gCode output file.
POSTAMBLE = '''M5

View File

@@ -45,7 +45,7 @@ class MathParser:
if self.vars.get(var) != None:
raise RuntimeError("Cannot redefine the value of " + var)
self.vars[var] = vars[var]
def getValue(self):
value = self.parseExpression()
self.skipWhitespace()
@@ -56,23 +56,23 @@ class MathParser:
"' at index " +
str(self.index))
return value
def peek(self):
return self.string[self.index:self.index + 1]
def hasNext(self):
return self.index < len(self.string)
def skipWhitespace(self):
while self.hasNext():
if self.peek() in ' \t\n\r':
self.index += 1
else:
return
def parseExpression(self):
return self.parseAddition()
def parseAddition(self):
values = [self.parseMultiplication()]
while True:
@@ -87,7 +87,7 @@ class MathParser:
else:
break
return sum(values)
def parseMultiplication(self):
values = [self.parseParenthesis()]
while True:
@@ -112,7 +112,7 @@ class MathParser:
for factor in values:
value *= factor
return value
def parseParenthesis(self):
self.skipWhitespace()
char = self.peek()
@@ -128,7 +128,7 @@ class MathParser:
return value
else:
return self.parseNegative()
def parseNegative(self):
self.skipWhitespace()
char = self.peek()
@@ -137,7 +137,7 @@ class MathParser:
return -1 * self.parseParenthesis()
else:
return self.parseValue()
def parseValue(self):
self.skipWhitespace()
char = self.peek()
@@ -145,7 +145,7 @@ class MathParser:
return self.parseNumber()
else:
return self.parseVariable()
def parseVariable(self):
self.skipWhitespace()
var = ''
@@ -156,7 +156,7 @@ class MathParser:
self.index += 1
else:
break
value = self.vars.get(var, None)
if value == None:
raise ValueError(
@@ -164,15 +164,15 @@ class MathParser:
var +
"'")
return float(value)
def parseNumber(self):
self.skipWhitespace()
strValue = ''
decimal_found = False
char = ''
while self.hasNext():
char = self.peek()
char = self.peek()
if char == '.':
if decimal_found:
raise SyntaxError(
@@ -186,7 +186,7 @@ class MathParser:
else:
break
self.index += 1
if len(strValue) == 0:
if char == '':
raise SyntaxError("Unexpected end found")
@@ -197,21 +197,21 @@ class MathParser:
" but instead I found a '" +
char +
"'. What's up with that?")
return float(strValue)
class Spreadsheet:
"""An object representing a spreadsheet. Can be used as a
FreeCAD object or as a standalone python object.
Cells of the spreadsheet can be got/set as arguments, as:
myspreadsheet = Spreadsheet()
myspreadsheet.a1 = 54
print(myspreadsheet.a1)
myspreadsheet.a2 = "My text"
myspreadsheet.b1 = "=a1*3"
print(myspreadsheet.b1)
The cell names are case-insensitive (a1 = A1)
"""
@@ -269,13 +269,13 @@ class Spreadsheet:
return self._cells[key]
else:
return self.__dict__.__getitem__(key)
def __setitem__(self, key, value):
__setattr__(self, key, value)
def __getitem__(self, key):
return __getattr__(self, key)
def __getstate__(self):
self._cells["Type"] = self.Type
if hasattr(self,"Object"):
@@ -347,7 +347,7 @@ class Spreadsheet:
return True
else:
return False
def isNumeric(self,key):
"isNumeric(cell): returns True if the given cell returns a number"
key = key.lower()
@@ -376,7 +376,7 @@ class Spreadsheet:
else:
if not nu:
# forbidden to set items at row 0
if v == "0":
if v == "0":
return False
if v.isalpha():
if not allowMoreThanOneLetter:
@@ -394,7 +394,7 @@ class Spreadsheet:
c = ''
r = ''
for ch in key:
if ch.isalpha():
if ch.isalpha():
c += ch
else:
r += ch
@@ -420,7 +420,7 @@ class Spreadsheet:
if index in [c,r]:
cells[k] = self._cells[k]
return cells
def evaluate(self,key):
"evaluate(key): evaluates the given formula"
key = key.lower()
@@ -458,7 +458,7 @@ class Spreadsheet:
co.Proxy.setCells(co,obj)
elif Draft.getType(co) == "SpreadsheetPropertyController":
co.Proxy.compute(co)
def getControlledCells(self,obj):
"returns a list of cells managed by controllers"
cells = []
@@ -499,18 +499,18 @@ class ViewProviderSpreadsheet(object):
self.editor = SpreadsheetView(vobj.Object)
addSpreadsheetView(self.editor)
return True
def unsetEdit(self,vobj,mode=0):
return False
def doubleClicked(self,vobj):
self.setEdit(vobj)
def claimChildren(self):
if hasattr(self,"Object"):
if hasattr(self.Object,"Controllers"):
return self.Object.Controllers
def __getstate__(self):
return None
@@ -532,17 +532,17 @@ class SpreadsheetController:
obj.FilterType = ["Object Type","Object Name"]
obj.DataType = ["Get Property","Count"]
obj.Direction = ["Horizontal","Vertical"]
def execute(self,obj):
pass
def __getstate__(self):
return self.Type
def __setstate__(self,state):
if state:
self.Type = state
def onChanged(self,obj,prop):
if prop == "DataType":
if obj.DataType == "Count":
@@ -659,7 +659,7 @@ class SpreadsheetPropertyController:
obj.addProperty("App::PropertyString","TargetProperty","Base","The property or constraint of the target object to control")
obj.addProperty("App::PropertyString","Cell","Base","The cell that contains the value to apply to the property")
obj.TargetType = ["Property","Constraint"]
def execute(self,obj):
pass
@@ -708,14 +708,14 @@ class SpreadsheetPropertyController:
except:
if DEBUG: print("unable to set constraint ",obj.TargetProperty, " of object ",obj.TargetObject.Name, " to ",value)
def __getstate__(self):
return self.Type
def __setstate__(self,state):
if state:
self.Type = state
def onChanged(self,obj,prop):
pass
@@ -736,7 +736,7 @@ class SpreadsheetView(QtGui.QWidget):
def __init__(self,spreadsheet=None):
from DraftTools import translate
QtGui.QWidget.__init__(self)
self.setWindowTitle(str(translate("Spreadsheet","Spreadsheet")))
self.setObjectName("Spreadsheet viewer")
self.verticalLayout = QtGui.QVBoxLayout(self)
@@ -877,7 +877,7 @@ class SpreadsheetView(QtGui.QWidget):
if content == None:
content = ""
self.lineEdit.setText(str(content))
def getEditLine(self):
"called when something has been entered in the edit line"
txt = str(self.lineEdit.text())
@@ -988,8 +988,8 @@ def makeSpreadsheet():
def makeSpreadsheetController(spreadsheet,cell=None,direction=None):
"""makeSpreadsheetController(spreadsheet,[cell,direction]): adds a
controller to the given spreadsheet. Call can be a starting cell such as "A5",
"""makeSpreadsheetController(spreadsheet,[cell,direction]): adds a
controller to the given spreadsheet. Call can be a starting cell such as "A5",
and direction can be "Horizontal" or "Vertical"."""
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","CellController")
SpreadsheetController(obj)
@@ -1006,7 +1006,7 @@ def makeSpreadsheetController(spreadsheet,cell=None,direction=None):
def makeSpreadsheetPropertyController(spreadsheet,object=None,prop=None,cell=None):
"""makeSpreadsheetPropertyController(spreadsheet,[object,prop,cell]): adds a
"""makeSpreadsheetPropertyController(spreadsheet,[object,prop,cell]): adds a
property controller, targeting the given object if any, to the given spreadsheet.
You can give a property (such as "Length" or "Proxy.Length") and a cell address
(such as "B6")."""
@@ -1092,7 +1092,7 @@ def export(exportList,filename):
return
obj = exportList[0]
if Draft.getType(obj) != "Spreadsheet":
print("Spreadhseet: The selected object is not a spreadsheet")
print("Spreadsheet: The selected object is not a spreadsheet")
return
if not obj.Proxy._cells:
print("Spreadsheet: The selected spreadsheet contains no cell")

View File

@@ -13,13 +13,13 @@ if [ "$(id -u)" != 0 ]; then
fi
echo "This script will permanently destroy and reset all state in snapd"
echo "You will loose all of your installed snaps"
echo "You will lose all of your installed snaps"
echo
echo "Type: DESTROY to remove all of your snap state"
echo
read consent
if [ "$consent" != "DESTROY" ]; then
if [ "$consent" != "DESTROY" ]; then
echo "No consent, aborting"
exit 0
fi