Skip to content

Commit

Permalink
Merge branch 'master' of ssh://git.code.sf.net/p/free-cad/code
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed Dec 31, 2013
2 parents 69521bd + 226c25f commit 9503ad0
Show file tree
Hide file tree
Showing 20 changed files with 943 additions and 76 deletions.
3 changes: 2 additions & 1 deletion src/Mod/Fem/App/CMakeLists.txt
Expand Up @@ -64,7 +64,8 @@ SOURCE_GROUP("Module" FILES ${Mod_SRCS})

SET(FemScripts_SRCS
convert2TetGen.py
FemLib.py
FemLib.py
CalculixLib.py
MechanicalAnalysis.py
MechanicalMaterial.py
)
Expand Down
104 changes: 74 additions & 30 deletions src/Mod/Fem/App/FemMeshPyImp.cpp
Expand Up @@ -181,21 +181,42 @@ PyObject* FemMeshPy::compute(PyObject *args)
PyObject* FemMeshPy::addNode(PyObject *args)
{
double x,y,z;
if (!PyArg_ParseTuple(args, "ddd",&x,&y,&z))
return 0;

try {
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
SMDS_MeshNode* node = meshDS->AddNode(x,y,z);
if (!node)
throw std::runtime_error("Failed to add node");
return Py::new_reference_to(Py::Int(node->GetID()));
int i = -1;
if (PyArg_ParseTuple(args, "ddd",&x,&y,&z)){
try {
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
SMDS_MeshNode* node = meshDS->AddNode(x,y,z);
if (!node)
throw std::runtime_error("Failed to add node");
return Py::new_reference_to(Py::Int(node->GetID()));
}
catch (const std::exception& e) {
PyErr_SetString(PyExc_Exception, e.what());
return 0;
}
}
catch (const std::exception& e) {
PyErr_SetString(PyExc_Exception, e.what());
return 0;
PyErr_Clear();

if (PyArg_ParseTuple(args, "dddi",&x,&y,&z,&i)){
try {
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
SMDS_MeshNode* node = meshDS->AddNodeWithID(x,y,z,i);
if (!node)
throw std::runtime_error("Failed to add node");
return Py::new_reference_to(Py::Int(node->GetID()));
}
catch (const std::exception& e) {
PyErr_SetString(PyExc_Exception, e.what());
return 0;
}
}
PyErr_SetString(PyExc_TypeError, "addNode() accepts:\n"
"-- addNode(x,y,z)\n"
"-- addNode(x,y,z,ElemId)\n");
return 0;

}

PyObject* FemMeshPy::addEdge(PyObject *args)
Expand Down Expand Up @@ -356,24 +377,47 @@ PyObject* FemMeshPy::addVolume(PyObject *args)
}

SMDS_MeshVolume* vol=0;
switch(Nodes.size()){
case 4:
vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3]);
if (!vol)
throw std::runtime_error("Failed to add Tet4 volume");
break;
case 8:
vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7]);
if (!vol)
throw std::runtime_error("Failed to add Tet10 volume");
break;
case 10:
vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9]);
if (!vol)
throw std::runtime_error("Failed to add Tet10 volume");
break;
if(ElementId != -1) {
switch(Nodes.size()){
case 4:
vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],ElementId);
if (!vol)
throw std::runtime_error("Failed to add Tet4 volume");
break;
case 8:
vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],ElementId);
if (!vol)
throw std::runtime_error("Failed to add Tet10 volume");
break;
case 10:
vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],ElementId);
if (!vol)
throw std::runtime_error("Failed to add Tet10 volume");
break;

default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|18] are allowed"); //unknown face type
}
}else{
switch(Nodes.size()){
case 4:
vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3]);
if (!vol)
throw std::runtime_error("Failed to add Tet4 volume");
break;
case 8:
vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7]);
if (!vol)
throw std::runtime_error("Failed to add Tet10 volume");
break;
case 10:
vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9]);
if (!vol)
throw std::runtime_error("Failed to add Tet10 volume");
break;

default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|18] are allowed"); //unknown face type
}

default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|18] are allowed"); //unknown face type
}

return Py::new_reference_to(Py::Int(vol->GetID()));
Expand Down
1 change: 1 addition & 0 deletions src/Mod/Fem/App/FemResultObject.cpp
Expand Up @@ -40,6 +40,7 @@ FemResultObject::FemResultObject()
ADD_PROPERTY_TYPE(DataType,(""), "General",Prop_None,"Type identifier of the result data");
ADD_PROPERTY_TYPE(Unit,(Base::Quantity()), "General",Prop_None,"Unit of the data");
ADD_PROPERTY_TYPE(ElementNumbers,(0), "Data",Prop_None,"Numbers of the result elements");
ADD_PROPERTY_TYPE(Mesh,(0), "General",Prop_None,"Link to the corosbonding mesh");
}

FemResultObject::~FemResultObject()
Expand Down
9 changes: 6 additions & 3 deletions src/Mod/Fem/App/FemResultObject.h
Expand Up @@ -48,10 +48,13 @@ class AppFemExport FemResultObject : public App::DocumentObject
App::PropertyQuantity Unit;
/// List of element numbers in this result object
App::PropertyIntegerList ElementNumbers;
/// Link to the corosbonding mesh
App::PropertyLink Mesh;

/// returns the type name of the ViewProvider
//virtual const char* getViewProviderName(void) const {
// return "FemGui::ViewProviderFemSet";
//}
virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderResult";
}
virtual App::DocumentObjectExecReturn *execute(void) {
return App::DocumentObject::StdReturn;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Fem/App/FemResultValue.cpp
Expand Up @@ -32,7 +32,7 @@
using namespace Fem;
using namespace App;

PROPERTY_SOURCE(Fem::FemResultValue, App::DocumentObject)
PROPERTY_SOURCE(Fem::FemResultValue, Fem::FemResultObject)


FemResultValue::FemResultValue()
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Fem/App/FemResultVector.cpp
Expand Up @@ -32,7 +32,7 @@
using namespace Fem;
using namespace App;

PROPERTY_SOURCE(Fem::FemResultVector, App::DocumentObject)
PROPERTY_SOURCE(Fem::FemResultVector, Fem::FemResultObject)


FemResultVector::FemResultVector()
Expand Down
179 changes: 148 additions & 31 deletions src/Mod/Fem/CalculixLib.py
@@ -1,5 +1,6 @@
#***************************************************************************
#* *
#* Copyright (c) 2013 - Joachim Zettler *
#* Copyright (c) 2013 - Juergen Riegel <FreeCAD@juergen-riegel.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
Expand All @@ -21,42 +22,158 @@
#***************************************************************************


import FreeCAD,os
from math import pow,sqrt

__title__="FreeCAD Calculix library"
__author__ = "Juergen Riegel "
__url__ = "http://www.freecadweb.org"

if open.__module__ == '__builtin__':
pyopen = open # because we'll redefine open below

# read a calculix result file and extract the nodes, displacement vectores and stress values.
def readResult(frd_input) :
input = open(frd_input,"r")
nodes_x = []
nodes_y = []
nodes_z = []
disp_x = []
disp_y = []
disp_z = []
displaced_nodes_x = []
displaced_nodes_y = []
displaced_nodes_z = []
input = pyopen(frd_input,"r")
nodes = {}
disp = {}
stress = {}
elements = {}

disp_found = False
nodes_found = True
nodes_found = False
stress_found = False
elements_found = False
elem = -1
while True:
line=input.readline()
if not line: break
#first lets extract the node and coordinate information from the results file
if nodes_found and (line[1:3] == "-1"):
nodes_x.append(float(line[13:25]))
nodes_y.append(float(line[25:37]))
nodes_z.append(float(line[37:49]))
#Check if we found displacement section
if line[5:9] == "DISP":
disp_found = True
#we found a displacement line in the frd file
if disp_found and (line[1:3] == "-1"):
disp_x.append(float(line[13:25]))
disp_y.append(float(line[25:37]))
disp_z.append(float(line[37:49]))
#Check for the end of a section
if line[1:3] == "-3":
#the section with the displacements and the nodes ended
disp_found = False
nodes_found = False
line=input.readline()
if not line: break
#Check if we found nodes section
if line[4:6] == "2C":
nodes_found = True
#first lets extract the node and coordinate information from the results file
if nodes_found and (line[1:3] == "-1"):
elem = int(line[4:13])
nodes_x = float(line[13:25])
nodes_y = float(line[25:37])
nodes_z = float(line[37:49])
nodes[elem] = FreeCAD.Vector(nodes_x,nodes_y,nodes_z)
#Check if we found nodes section
if line[4:6] == "3C":
elements_found = True
#first lets extract element number
if elements_found and (line[1:3] == "-1"):
elem = int(line[4:13])
#then the 10 id's for the Tet10 element
if elements_found and (line[1:3] == "-2"):
node_id_2 = int(line[3:13])
node_id_1 = int(line[13:23])
node_id_3 = int(line[23:33])
node_id_4 = int(line[33:43])
node_id_5 = int(line[43:53])
node_id_7 = int(line[53:63])
node_id_6 = int(line[63:73])
node_id_9 = int(line[73:83])
node_id_8 = int(line[83:93])
node_id_10 = int(line[93:103])
elements[elem] = (node_id_1,node_id_2,node_id_3,node_id_4,node_id_5,node_id_6,node_id_7,node_id_8,node_id_9,node_id_10)
#Check if we found displacement section
if line[5:9] == "DISP":
disp_found = True
#we found a displacement line in the frd file
if disp_found and (line[1:3] == "-1"):
elem = int(line[4:13])
disp_x = float(line[13:25])
disp_y = float(line[25:37])
disp_z = float(line[37:49])
disp[elem] = FreeCAD.Vector(disp_x,disp_y,disp_z)
if line[5:11] == "STRESS":
stress_found = True
#we found a displacement line in the frd file
if stress_found and (line[1:3] == "-1"):
elem = int(line[4:13])
stress_1 = float(line[13:25])
stress_2 = float(line[25:37])
stress_3 = float(line[37:49])
stress_4 = float(line[49:61])
stress_5 = float(line[61:73])
stress_6 = float(line[73:85])
stress[elem] = (stress_1,stress_2,stress_3,stress_4,stress_5,stress_6)
#Check for the end of a section
if line[1:3] == "-3":
#the section with the displacements and the nodes ended
disp_found = False
nodes_found = False
stress_found = False
elements_found = False

input.close()
FreeCAD.Console.PrintLog('Read Calculix result: ' + `len(nodes)` + ' Nodes, ' + `len(disp)` + ' Displacements and ' + `len(stress)` + ' Stress values\n')

return {'Nodes':nodes,'Tet10Elem':elements,'Displacement':disp,'Stress':stress}


def importFrd(filename):
m = readResult(filename);
MeshObject = None
if(len(m) > 0):
import Fem
AnalysisName = os.path.splitext(os.path.basename(filename))[0]
AnalysisObject = FreeCAD.ActiveDocument.addObject('Fem::FemAnalysis','Analysis')
AnalysisObject.Label = AnalysisName
if(m.has_key('Tet10Elem') and m.has_key('Nodes') ):
mesh = Fem.FemMesh()
nds = m['Nodes']
for i in nds:
n = nds[i]
mesh.addNode(n[0],n[1],n[2],i)
elms = m['Tet10Elem']
for i in elms:
e = elms[i]
mesh.addVolume([e[0],e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8],e[9]],i)

MeshObject = FreeCAD.ActiveDocument.addObject('Fem::FemMeshObject','ResultMesh')
MeshObject.FemMesh = mesh
AnalysisObject.Member = AnalysisObject.Member + [MeshObject]

if(m.has_key('Displacement')):
disp = m['Displacement']
o = FreeCAD.ActiveDocument.addObject('Fem::FemResultVector','Displacement')
o.Values = disp.values()
o.ElementNumbers = disp.keys()
if(MeshObject):
o.Mesh = MeshObject
AnalysisObject.Member = AnalysisObject.Member + [o]
if(m.has_key('Stress')):
stress = m['Stress']
o = FreeCAD.ActiveDocument.addObject('Fem::FemResultValue','MisesStress')
mstress = []
for i in stress.values():
# van mises stress (http://en.wikipedia.org/wiki/Von_Mises_yield_criterion)
mstress.append( sqrt( pow( i[0] - i[1] ,2) + pow( i[1] - i[2] ,2) + pow( i[2] - i[0] ,2) + 6 * (pow(i[3],2)+pow(i[4],2)+pow(i[5],2) ) ) )

o.Values = mstress
o.ElementNumbers = stress.keys()
if(MeshObject):
o.Mesh = MeshObject
AnalysisObject.Member = AnalysisObject.Member + [o]
if(FreeCAD.GuiUp):
import FemGui
FemGui.setActiveAnalysis(AnalysisObject)

def insert(filename,docname):
"called when freecad wants to import a file"
try:
doc = FreeCAD.getDocument(docname)
except:
doc = FreeCAD.newDocument(docname)
FreeCAD.ActiveDocument = doc

importFrd(filename)

def open(filename):
"called when freecad opens a file"
docname = os.path.splitext(os.path.basename(filename))[0]
insert(filename,docname)


2 changes: 2 additions & 0 deletions src/Mod/Fem/Gui/AppFemGui.cpp
Expand Up @@ -45,6 +45,7 @@
#include "ViewProviderFemConstraintForce.h"
#include "ViewProviderFemConstraintGear.h"
#include "ViewProviderFemConstraintPulley.h"
#include "ViewProviderResult.h"
#include "Workbench.h"
//#include "resources/qrc_Fem.cpp"

Expand Down Expand Up @@ -94,6 +95,7 @@ void FemGuiExport initFemGui()
FemGui::ViewProviderFemConstraintForce ::init();
FemGui::ViewProviderFemConstraintGear ::init();
FemGui::ViewProviderFemConstraintPulley ::init();
FemGui::ViewProviderResult ::init();

Base::Interpreter().loadModule("MechanicalAnalysis");
Base::Interpreter().loadModule("MechanicalMaterial");
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/Fem/Gui/CMakeLists.txt
Expand Up @@ -133,6 +133,8 @@ SET(FemGui_SRCS_ViewProvider
ViewProviderFemConstraintGear.h
ViewProviderFemConstraintPulley.cpp
ViewProviderFemConstraintPulley.h
ViewProviderResult.cpp
ViewProviderResult.h
)
SOURCE_GROUP("ViewProvider" FILES ${FemGui_SRCS_ViewProvider})

Expand Down

0 comments on commit 9503ad0

Please sign in to comment.