Merge pull request #13464 from marioalexis84/fem-ccx_element_types
Fem: Add element types to ABAQUS writer
This commit is contained in:
@@ -1929,7 +1929,12 @@ void FemMesh::read(const char* FileName)
|
||||
}
|
||||
}
|
||||
|
||||
void FemMesh::writeABAQUS(const std::string& Filename, int elemParam, bool groupParam) const
|
||||
void FemMesh::writeABAQUS(const std::string& Filename,
|
||||
int elemParam,
|
||||
bool groupParam,
|
||||
ABAQUS_VolumeVariant volVariant,
|
||||
ABAQUS_FaceVariant faceVariant,
|
||||
ABAQUS_EdgeVariant edgeVariant) const
|
||||
{
|
||||
/*
|
||||
* elemParam:
|
||||
@@ -1940,121 +1945,220 @@ void FemMesh::writeABAQUS(const std::string& Filename, int elemParam, bool group
|
||||
* groupParam:
|
||||
* true = write group data
|
||||
* false = do not write group data
|
||||
|
||||
* volVariant, faceVariant, edgeVariant:
|
||||
* Element type according to availability in CalculiX
|
||||
*/
|
||||
|
||||
static std::map<std::string, std::vector<int>> elemOrderMap;
|
||||
static std::map<int, std::string> edgeTypeMap;
|
||||
static std::map<int, std::string> faceTypeMap;
|
||||
static std::map<int, std::string> volTypeMap;
|
||||
if (elemOrderMap.empty()) {
|
||||
// node order fits with node order in importCcxFrdResults.py module to import
|
||||
// CalculiX result meshes
|
||||
std::map<std::string, std::string> variants;
|
||||
|
||||
// dimension 1
|
||||
//
|
||||
// seg2 FreeCAD --> CalculiX B31
|
||||
// N1, N2
|
||||
std::vector<int> b31 = boost::assign::list_of(0)(1);
|
||||
//
|
||||
// seg3 FreeCAD --> CalculiX B32
|
||||
// N1, N3, N2
|
||||
std::vector<int> b32 = boost::assign::list_of(0)(2)(1);
|
||||
// volume elements
|
||||
variants["Tetra4"] = "C3D4";
|
||||
variants["Penta6"] = "C3D6";
|
||||
variants["Hexa8"] = "C3D8";
|
||||
variants["Tetra10"] = "C3D10";
|
||||
variants["Penta15"] = "C3D15";
|
||||
variants["Hexa20"] = "C3D20";
|
||||
|
||||
elemOrderMap.insert(std::make_pair("B31", b31));
|
||||
edgeTypeMap.insert(std::make_pair(elemOrderMap["B31"].size(), "B31"));
|
||||
elemOrderMap.insert(std::make_pair("B32", b32));
|
||||
edgeTypeMap.insert(std::make_pair(elemOrderMap["B32"].size(), "B32"));
|
||||
|
||||
// dimension 2
|
||||
//
|
||||
// tria3 FreeCAD --> S3 CalculiX
|
||||
// N1, N2, N3
|
||||
std::vector<int> s3 = boost::assign::list_of(0)(1)(2);
|
||||
//
|
||||
// tria6 FreeCAD --> S6 CalculiX
|
||||
// N1, N2, N3, N4, N5, N6
|
||||
std::vector<int> s6 = boost::assign::list_of(0)(1)(2)(3)(4)(5);
|
||||
//
|
||||
// quad4 FreeCAD --> S4 CalculiX
|
||||
// N1, N2, N3, N4
|
||||
std::vector<int> s4 = boost::assign::list_of(0)(1)(2)(3);
|
||||
//
|
||||
// quad8 FreeCAD --> S8 CalculiX
|
||||
// N1, N2, N3, N4, N5, N6, N7, N8
|
||||
std::vector<int> s8 = boost::assign::list_of(0)(1)(2)(3)(4)(5)(6)(7);
|
||||
|
||||
elemOrderMap.insert(std::make_pair("S3", s3));
|
||||
faceTypeMap.insert(std::make_pair(elemOrderMap["S3"].size(), "S3"));
|
||||
elemOrderMap.insert(std::make_pair("S6", s6));
|
||||
faceTypeMap.insert(std::make_pair(elemOrderMap["S6"].size(), "S6"));
|
||||
elemOrderMap.insert(std::make_pair("S4", s4));
|
||||
faceTypeMap.insert(std::make_pair(elemOrderMap["S4"].size(), "S4"));
|
||||
elemOrderMap.insert(std::make_pair("S8", s8));
|
||||
faceTypeMap.insert(std::make_pair(elemOrderMap["S8"].size(), "S8"));
|
||||
|
||||
// dimension 3
|
||||
//
|
||||
// tetras
|
||||
// master 0.14 release
|
||||
// changed to this in August 2013, committed by juergen (jriedel)
|
||||
// https://github.com/FreeCAD/FreeCAD/commit/af56b324b9566b20f3b6e7880c29354c1dbe7a99
|
||||
// std::vector<int> c3d4 = boost::assign::list_of(0)(3)(1)(2);
|
||||
// std::vector<int> c3d10 = boost::assign::list_of(0)(2)(1)(3)(6)(5)(4)(7)(9)(8);
|
||||
|
||||
// since master 0.15
|
||||
// added by werner (wmayer) March 2015,
|
||||
// https://forum.freecad.org/viewtopic.php?f=18&t=10110&start=10#p81681
|
||||
// https://github.com/FreeCAD/FreeCAD/commit/5d159f5cf352a93b1aff4fb7b82e8b747ee4f35b
|
||||
// https://github.com/FreeCAD/FreeCAD/commit/b007bd19e4e4608caa4cdad350a9f480287fac6b
|
||||
// tetra4 FreeCAD --> C3D4 CalculiX
|
||||
// N2, N1, N3, N4
|
||||
std::vector<int> c3d4 = boost::assign::list_of(1)(0)(2)(3);
|
||||
// tetra10: FreeCAD --> C3D10 CalculiX
|
||||
// N2, N1, N3, N4, N5, N7, N6, N9, N8, N10
|
||||
std::vector<int> c3d10 = boost::assign::list_of(1)(0)(2)(3)(4)(6)(5)(8)(7)(9);
|
||||
|
||||
// tetra node order for the system which is used for hexa8, hexa20, penta6 and penda15
|
||||
// be careful with activating because of method getccxVolumesByFace())
|
||||
// tetra4 FreeCAD --> C3D4 CalculiX
|
||||
// N2, N3, N4, N1
|
||||
// std::vector<int> c3d4 = boost::assign::list_of(1)(2)(3)(0);
|
||||
//
|
||||
// tetra10: FreeCAD --> C3D10 CalculiX
|
||||
// N2, N3, N4, N1, N6, N10, N9, N5, N7, N8
|
||||
// std::vector<int> c3d10 = boost::assign::list_of(1)(2)(3)(0)(5)(9)(8)(4)(6)(7);
|
||||
|
||||
// hexa8 FreeCAD --> C3D8 CalculiX
|
||||
// N6, N7, N8, N5, N2, N3, N4, N1
|
||||
std::vector<int> c3d8 = boost::assign::list_of(5)(6)(7)(4)(1)(2)(3)(0);
|
||||
//
|
||||
// hexa20 FreeCAD --> C3D20 CalculiX
|
||||
// N6, N7, N8, N5, N2, N3, N4, N1, N14, N15, N16, N13, N10, N11, N12, N9, N18, N19, N20, N17
|
||||
std::vector<int> c3d20 = boost::assign::list_of(5)(6)(7)(4)(1)(2)(3)(0)(13)(14)(15)(12)(9)(
|
||||
10)(11)(8)(17)(18)(19)(16);
|
||||
//
|
||||
// penta6 FreeCAD --> C3D6 CalculiX
|
||||
// N5, N6, N4, N2, N3, N1
|
||||
std::vector<int> c3d6 = boost::assign::list_of(4)(5)(3)(1)(2)(0);
|
||||
//
|
||||
// penta15 FreeCAD --> C3D15 CalculiX
|
||||
// N5, N6, N4, N2, N3, N1, N11, N12, N10, N8, N9, N7, N14, N15, N13
|
||||
std::vector<int> c3d15 =
|
||||
boost::assign::list_of(4)(5)(3)(1)(2)(0)(10)(11)(9)(7)(8)(6)(13)(14)(12);
|
||||
|
||||
elemOrderMap.insert(std::make_pair("C3D4", c3d4));
|
||||
volTypeMap.insert(std::make_pair(elemOrderMap["C3D4"].size(), "C3D4"));
|
||||
elemOrderMap.insert(std::make_pair("C3D10", c3d10));
|
||||
volTypeMap.insert(std::make_pair(elemOrderMap["C3D10"].size(), "C3D10"));
|
||||
elemOrderMap.insert(std::make_pair("C3D8", c3d8));
|
||||
volTypeMap.insert(std::make_pair(elemOrderMap["C3D8"].size(), "C3D8"));
|
||||
elemOrderMap.insert(std::make_pair("C3D20", c3d20));
|
||||
volTypeMap.insert(std::make_pair(elemOrderMap["C3D20"].size(), "C3D20"));
|
||||
elemOrderMap.insert(std::make_pair("C3D6", c3d6));
|
||||
volTypeMap.insert(std::make_pair(elemOrderMap["C3D6"].size(), "C3D6"));
|
||||
elemOrderMap.insert(std::make_pair("C3D15", c3d15));
|
||||
volTypeMap.insert(std::make_pair(elemOrderMap["C3D15"].size(), "C3D15"));
|
||||
switch (volVariant) {
|
||||
case ABAQUS_VolumeVariant::Standard:
|
||||
break;
|
||||
case ABAQUS_VolumeVariant::Reduced:
|
||||
variants["Hexa8"] = "C3D8R";
|
||||
variants["Hexa20"] = "C3D20R";
|
||||
break;
|
||||
case ABAQUS_VolumeVariant::Incompatible:
|
||||
variants["Hexa8"] = "C3D8I";
|
||||
break;
|
||||
case ABAQUS_VolumeVariant::Modified:
|
||||
variants["Tetra10"] = "C3D10T";
|
||||
break;
|
||||
case ABAQUS_VolumeVariant::Fluid:
|
||||
variants["Tetra4"] = "F3D4";
|
||||
variants["Penta6"] = "F3D6";
|
||||
variants["Hexa8"] = "F3D8";
|
||||
break;
|
||||
}
|
||||
|
||||
// face elements
|
||||
switch (faceVariant) {
|
||||
case ABAQUS_FaceVariant::Shell:
|
||||
variants["Tria3"] = "S3";
|
||||
variants["Quad4"] = "S4";
|
||||
variants["Tria6"] = "S6";
|
||||
variants["Quad8"] = "S8";
|
||||
break;
|
||||
case ABAQUS_FaceVariant::Shell_Reduced:
|
||||
variants["Tria3"] = "S3";
|
||||
variants["Quad4"] = "S4R";
|
||||
variants["Tria6"] = "S6";
|
||||
variants["Quad8"] = "S8R";
|
||||
break;
|
||||
case ABAQUS_FaceVariant::Membrane:
|
||||
variants["Tria3"] = "M3D3";
|
||||
variants["Quad4"] = "M3D4";
|
||||
variants["Tria6"] = "M3D6";
|
||||
variants["Quad8"] = "M3D8";
|
||||
break;
|
||||
case ABAQUS_FaceVariant::Membrane_Reduced:
|
||||
variants["Tria3"] = "M3D3";
|
||||
variants["Quad4"] = "M3D4R";
|
||||
variants["Tria6"] = "M3D6";
|
||||
variants["Quad8"] = "M3D8R";
|
||||
break;
|
||||
case ABAQUS_FaceVariant::Stress:
|
||||
variants["Tria3"] = "CPS3";
|
||||
variants["Quad4"] = "CPS4";
|
||||
variants["Tria6"] = "CPS6";
|
||||
variants["Quad8"] = "CPS8";
|
||||
break;
|
||||
case ABAQUS_FaceVariant::Stress_Reduced:
|
||||
variants["Tria3"] = "CPS3";
|
||||
variants["Quad4"] = "CPS4R";
|
||||
variants["Tria6"] = "CPS6";
|
||||
variants["Quad8"] = "CPS8R";
|
||||
break;
|
||||
case ABAQUS_FaceVariant::Strain:
|
||||
variants["Tria3"] = "CPE3";
|
||||
variants["Quad4"] = "CPE4";
|
||||
variants["Tria6"] = "CPE6";
|
||||
variants["Quad8"] = "CPE8";
|
||||
break;
|
||||
case ABAQUS_FaceVariant::Strain_Reduced:
|
||||
variants["Tria3"] = "CPE3";
|
||||
variants["Quad4"] = "CPE4R";
|
||||
variants["Tria6"] = "CPE6";
|
||||
variants["Quad8"] = "CPE8R";
|
||||
break;
|
||||
case ABAQUS_FaceVariant::Axisymmetric:
|
||||
variants["Tria3"] = "CAX3";
|
||||
variants["Quad4"] = "CAX4";
|
||||
variants["Tria6"] = "CAX6";
|
||||
variants["Quad8"] = "CAX8";
|
||||
break;
|
||||
case ABAQUS_FaceVariant::Axisymmetric_Reduced:
|
||||
variants["Tria3"] = "CAX3";
|
||||
variants["Quad4"] = "CAX4R";
|
||||
variants["Tria6"] = "CAX6";
|
||||
variants["Quad8"] = "CAX8R";
|
||||
break;
|
||||
}
|
||||
|
||||
// edge elements
|
||||
switch (edgeVariant) {
|
||||
case ABAQUS_EdgeVariant::Beam:
|
||||
variants["Seg2"] = "B31";
|
||||
variants["Seg3"] = "B32";
|
||||
break;
|
||||
case ABAQUS_EdgeVariant::Beam_Reduced:
|
||||
variants["Seg2"] = "B31R";
|
||||
variants["Seg3"] = "B32R";
|
||||
break;
|
||||
case ABAQUS_EdgeVariant::Truss:
|
||||
variants["Seg2"] = "T3D2";
|
||||
variants["Seg3"] = "T3D3";
|
||||
break;
|
||||
case ABAQUS_EdgeVariant::Network:
|
||||
variants["Seg2"] = "B31";
|
||||
variants["Seg3"] = "D";
|
||||
break;
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<int>> elemOrderMap;
|
||||
std::map<int, std::string> edgeTypeMap;
|
||||
std::map<int, std::string> faceTypeMap;
|
||||
std::map<int, std::string> volTypeMap;
|
||||
|
||||
|
||||
// node order fits with node order in importCcxFrdResults.py module to import
|
||||
// CalculiX result meshes
|
||||
|
||||
// dimension 1
|
||||
//
|
||||
// seg2 FreeCAD --> B31, B31R, T3D2 CalculiX
|
||||
// N1, N2
|
||||
std::vector<int> seg2 = boost::assign::list_of(0)(1);
|
||||
//
|
||||
// seg3 FreeCAD --> B32, B32R, T3D3 D CalculiX
|
||||
// N1, N3, N2
|
||||
std::vector<int> seg3 = boost::assign::list_of(0)(2)(1);
|
||||
|
||||
elemOrderMap.insert(std::make_pair(variants["Seg2"], seg2));
|
||||
edgeTypeMap.insert(std::make_pair(seg2.size(), variants["Seg2"]));
|
||||
elemOrderMap.insert(std::make_pair(variants["Seg3"], seg3));
|
||||
edgeTypeMap.insert(std::make_pair(seg3.size(), variants["Seg3"]));
|
||||
|
||||
// dimension 2
|
||||
//
|
||||
// tria3 FreeCAD --> S3, M3D3, CPS3, CPE3, CAX3 CalculiX
|
||||
// N1, N2, N3
|
||||
std::vector<int> tria3 = boost::assign::list_of(0)(1)(2);
|
||||
//
|
||||
// tria6 FreeCAD --> S6 M3D6, CPS6, CPE6, CAX6 CalculiX
|
||||
// N1, N2, N3, N4, N5, N6
|
||||
std::vector<int> tria6 = boost::assign::list_of(0)(1)(2)(3)(4)(5);
|
||||
//
|
||||
// quad4 FreeCAD --> S4, S4R, M3D4, M3D4R, CPS4, CPS4R, CPE4, CPE4R, CAX4, CAX4R CalculiX
|
||||
// N1, N2, N3, N4
|
||||
std::vector<int> quad4 = boost::assign::list_of(0)(1)(2)(3);
|
||||
//
|
||||
// quad8 FreeCAD --> S8, S8R, M3D8, M3D8R, CPS8, CPS8R, CPE8, CPE8R, CAX8, CAX8R CalculiX
|
||||
// N1, N2, N3, N4, N5, N6, N7, N8
|
||||
std::vector<int> quad8 = boost::assign::list_of(0)(1)(2)(3)(4)(5)(6)(7);
|
||||
|
||||
elemOrderMap.insert(std::make_pair(variants["Tria3"], tria3));
|
||||
faceTypeMap.insert(std::make_pair(tria3.size(), variants["Tria3"]));
|
||||
elemOrderMap.insert(std::make_pair(variants["Tria6"], tria6));
|
||||
faceTypeMap.insert(std::make_pair(tria6.size(), variants["Tria6"]));
|
||||
elemOrderMap.insert(std::make_pair(variants["Quad4"], quad4));
|
||||
faceTypeMap.insert(std::make_pair(quad4.size(), variants["Quad4"]));
|
||||
elemOrderMap.insert(std::make_pair(variants["Quad8"], quad8));
|
||||
faceTypeMap.insert(std::make_pair(quad8.size(), variants["Quad8"]));
|
||||
|
||||
|
||||
// dimension 3
|
||||
//
|
||||
// tetra4 FreeCAD --> C3D4, F3D4 CalculiX
|
||||
// N2, N1, N3, N4
|
||||
std::vector<int> tetra4 = boost::assign::list_of(1)(0)(2)(3);
|
||||
// tetra10: FreeCAD --> C3D10, C3D10T CalculiX
|
||||
// N2, N1, N3, N4, N5, N7, N6, N9, N8, N10
|
||||
std::vector<int> tetra10 = boost::assign::list_of(1)(0)(2)(3)(4)(6)(5)(8)(7)(9);
|
||||
|
||||
// tetra node order for the system which is used for hexa8, hexa20, penta6 and penta15
|
||||
// be careful with activating because of method getccxVolumesByFace())
|
||||
// hexa8 FreeCAD --> C3D8, C3D8R, C3D8I, F3D8 CalculiX
|
||||
// N6, N7, N8, N5, N2, N3, N4, N1
|
||||
std::vector<int> hexa8 = boost::assign::list_of(5)(6)(7)(4)(1)(2)(3)(0);
|
||||
//
|
||||
// hexa20 FreeCAD --> C3D20, C3D20R CalculiX
|
||||
// N6, N7, N8, N5, N2, N3, N4, N1, N14, N15, N16, N13, N10, N11, N12, N9, N18, N19, N20, N17
|
||||
std::vector<int> hexa20 = boost::assign::list_of(5)(6)(7)(4)(1)(2)(3)(0)(13)(14)(15)(12)(9)(10)(
|
||||
11)(8)(17)(18)(19)(16);
|
||||
//
|
||||
// penta6 FreeCAD --> C3D6, F3D6 CalculiX
|
||||
// N5, N6, N4, N2, N3, N1
|
||||
std::vector<int> penta6 = boost::assign::list_of(4)(5)(3)(1)(2)(0);
|
||||
//
|
||||
// penta15 FreeCAD --> C3D15 CalculiX
|
||||
// N5, N6, N4, N2, N3, N1, N11, N12, N10, N8, N9, N7, N14, N15, N13
|
||||
std::vector<int> penta15 =
|
||||
boost::assign::list_of(4)(5)(3)(1)(2)(0)(10)(11)(9)(7)(8)(6)(13)(14)(12);
|
||||
|
||||
elemOrderMap.insert(std::make_pair(variants["Tetra4"], tetra4));
|
||||
volTypeMap.insert(std::make_pair(tetra4.size(), variants["Tetra4"]));
|
||||
elemOrderMap.insert(std::make_pair(variants["Tetra10"], tetra10));
|
||||
volTypeMap.insert(std::make_pair(tetra10.size(), variants["Tetra10"]));
|
||||
elemOrderMap.insert(std::make_pair(variants["Hexa8"], hexa8));
|
||||
volTypeMap.insert(std::make_pair(hexa8.size(), variants["Hexa8"]));
|
||||
elemOrderMap.insert(std::make_pair(variants["Hexa20"], hexa20));
|
||||
volTypeMap.insert(std::make_pair(hexa20.size(), variants["Hexa20"]));
|
||||
elemOrderMap.insert(std::make_pair(variants["Penta6"], penta6));
|
||||
volTypeMap.insert(std::make_pair(penta6.size(), variants["Penta6"]));
|
||||
elemOrderMap.insert(std::make_pair(variants["Penta15"], penta15));
|
||||
volTypeMap.insert(std::make_pair(penta15.size(), variants["Penta15"]));
|
||||
|
||||
|
||||
// get all data --> Extract Nodes and Elements of the current SMESH datastructure
|
||||
using VertexMap = std::map<int, Base::Vector3d>;
|
||||
using NodesMap = std::map<int, std::vector<int>>;
|
||||
|
||||
@@ -47,6 +47,35 @@ class TopoDS_Solid;
|
||||
namespace Fem
|
||||
{
|
||||
|
||||
enum class ABAQUS_VolumeVariant
|
||||
{
|
||||
Standard,
|
||||
Reduced,
|
||||
Incompatible,
|
||||
Modified,
|
||||
Fluid
|
||||
};
|
||||
enum class ABAQUS_FaceVariant
|
||||
{
|
||||
Shell,
|
||||
Shell_Reduced,
|
||||
Membrane,
|
||||
Membrane_Reduced,
|
||||
Stress,
|
||||
Stress_Reduced,
|
||||
Strain,
|
||||
Strain_Reduced,
|
||||
Axisymmetric,
|
||||
Axisymmetric_Reduced
|
||||
};
|
||||
enum class ABAQUS_EdgeVariant
|
||||
{
|
||||
Beam,
|
||||
Beam_Reduced,
|
||||
Truss,
|
||||
Network
|
||||
};
|
||||
|
||||
using SMESH_HypothesisPtr = std::shared_ptr<SMESH_Hypothesis>;
|
||||
|
||||
/** The representation of a FemMesh
|
||||
@@ -172,7 +201,12 @@ public:
|
||||
/// import from files
|
||||
void read(const char* FileName);
|
||||
void write(const char* FileName) const;
|
||||
void writeABAQUS(const std::string& Filename, int elemParam, bool groupParam) const;
|
||||
void writeABAQUS(const std::string& Filename,
|
||||
int elemParam,
|
||||
bool groupParam,
|
||||
ABAQUS_VolumeVariant volVariant = ABAQUS_VolumeVariant::Standard,
|
||||
ABAQUS_FaceVariant faceVariant = ABAQUS_FaceVariant::Shell,
|
||||
ABAQUS_EdgeVariant edgeVariant = ABAQUS_EdgeVariant::Beam) const;
|
||||
void writeZ88(const std::string& FileName) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -74,13 +74,40 @@
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="writeABAQUS" Const="true">
|
||||
<Methode Name="writeABAQUS" Const="true" Keyword="true">
|
||||
<Documentation>
|
||||
<UserDocu>Write out as ABAQUS inp
|
||||
writeABAQUS(file, int elemParam, bool groupParam)
|
||||
elemParam: 0 = all elements, 1 = highest elements only, 2 = FEM elements only (only edges not belonging to faces and faces not belonging to volumes)
|
||||
groupParam: true = write group data, false = do not write group data
|
||||
</UserDocu>
|
||||
volVariant: Volume elements
|
||||
"standard": Tetra4 -> C3D4, Penta6 -> C3D6, Hexa8 -> C3D8, Tetra10 -> C3D10, Penta15 -> C3D15, Hexa20 -> C3D20
|
||||
"reduced": Hexa8 -> C3D8R, Hexa20 -> C3D20R
|
||||
"incompatible": Hexa8 -> C3D8I
|
||||
"modified": Tetra10 -> C3D10T
|
||||
"fluid": Tetra4 -> F3D4, Penta6 -> F3D6, Hexa8 -> F3D8
|
||||
|
||||
faceVariant: Face elements
|
||||
"shell": Tria3 -> S3, Quad4 -> S4, Tria6 -> S6, Quad8 -> S8
|
||||
"shell reduced": Tria3 -> S3, Quad4 -> S4R, Tria6 -> S6, Quad8 -> S8R
|
||||
"membrane": Tria3 -> M3D3, Quad4 -> M3D4, Tria6 -> M3D6, Quad8 -> M3D8
|
||||
"membrane reduced": Tria3 -> M3D3, Quad4 -> M3D4R, Tria6 -> M3D6, Quad8 -> M3D8R
|
||||
"stress": Tria3 -> CPS3, Quad4 -> CPS4, Tria6 -> CPS6, Quad8 -> CPS8
|
||||
"stress reduced": Tria3 -> CPS3, Quad4 -> CPS4R, Tria6 -> CPS6, Quad8 -> CPS8R
|
||||
"strain": Tria3 -> CPE3, Quad4 -> CPE4, Tria6 -> CPE6, Quad8 -> CPE8
|
||||
"strain reduced": Tria3 -> CPE3, Quad4 -> CPE4R, Tria6 -> CPE6, Quad8 -> CPE8R
|
||||
"axisymmetric": Tria3 -> CAX3, Quad4 -> CAX4, Tria6 -> CAX6, Quad8 -> CAX8
|
||||
"axisymmetric reduced": Tria3 -> CAX3, Quad4 -> CAX4R, Tria6 -> CAX6, Quad8 -> CAX8R
|
||||
|
||||
edgeVariant: Edge elements
|
||||
"beam": Seg2 -> B31, Seg3 -> B32
|
||||
"beam reduced": Seg2 -> B31R, Seg3 -> B32R
|
||||
"truss": Seg2 -> T3D2, eg3 -> T3D3
|
||||
"network": Seg3 -> D
|
||||
|
||||
Elements are selected according to CalculiX availability.
|
||||
For example if volume variant "modified" is selected, Tetra10 mesh
|
||||
elements are assigned to C3D10T and remain elements uses "standard"</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="setTransform">
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "Mod/Fem/App/FemMesh.h"
|
||||
#include <Base/PlacementPy.h>
|
||||
#include <Base/PyWrapParseTupleAndKeywords.h>
|
||||
#include <Base/QuantityPy.h>
|
||||
#include <Base/VectorPy.h>
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
@@ -856,20 +857,88 @@ PyObject* FemMeshPy::write(PyObject* args)
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* FemMeshPy::writeABAQUS(PyObject* args)
|
||||
namespace
|
||||
{
|
||||
|
||||
std::map<std::string, ABAQUS_VolumeVariant> volVariantPyMap = {
|
||||
{"standard", ABAQUS_VolumeVariant::Standard},
|
||||
{"reduced", ABAQUS_VolumeVariant::Reduced},
|
||||
{"incompatible", ABAQUS_VolumeVariant::Incompatible},
|
||||
{"modified", ABAQUS_VolumeVariant::Modified},
|
||||
{"fluid", ABAQUS_VolumeVariant::Fluid}};
|
||||
|
||||
std::map<std::string, ABAQUS_FaceVariant> faceVariantPyMap = {
|
||||
{"shell", ABAQUS_FaceVariant::Shell},
|
||||
{"shell reduced", ABAQUS_FaceVariant::Shell_Reduced},
|
||||
{"membrane", ABAQUS_FaceVariant::Membrane},
|
||||
{"membrane reduced", ABAQUS_FaceVariant::Membrane_Reduced},
|
||||
{"stress", ABAQUS_FaceVariant::Stress},
|
||||
{"stress reduced", ABAQUS_FaceVariant::Stress_Reduced},
|
||||
{"strain", ABAQUS_FaceVariant::Strain},
|
||||
{"strain reduced", ABAQUS_FaceVariant::Strain_Reduced},
|
||||
{"axisymmetric", ABAQUS_FaceVariant::Axisymmetric},
|
||||
{"axisymmetric reduced", ABAQUS_FaceVariant::Axisymmetric_Reduced}};
|
||||
|
||||
std::map<std::string, ABAQUS_EdgeVariant> edgeVariantPyMap = {
|
||||
{"beam", ABAQUS_EdgeVariant::Beam},
|
||||
{"beam reduced", ABAQUS_EdgeVariant::Beam_Reduced},
|
||||
{"truss", ABAQUS_EdgeVariant::Truss},
|
||||
{"network", ABAQUS_EdgeVariant::Network}};
|
||||
|
||||
} // namespace
|
||||
|
||||
PyObject* FemMeshPy::writeABAQUS(PyObject* args, PyObject* kwd)
|
||||
{
|
||||
char* Name;
|
||||
int elemParam;
|
||||
PyObject* groupParam;
|
||||
if (!PyArg_ParseTuple(args, "etiO!", "utf-8", &Name, &elemParam, &PyBool_Type, &groupParam)) {
|
||||
const char* volVariant = "standard";
|
||||
const char* faceVariant = "shell";
|
||||
const char* edgeVariant = "beam";
|
||||
|
||||
const std::array<const char*, 7> kwlist {"fileName",
|
||||
"elemParam",
|
||||
"groupParam",
|
||||
"volVariant",
|
||||
"faceVariant",
|
||||
"edgeVariant",
|
||||
nullptr};
|
||||
|
||||
if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
||||
kwd,
|
||||
"etiO!|sss",
|
||||
kwlist,
|
||||
"utf-8",
|
||||
&Name,
|
||||
&elemParam,
|
||||
&PyBool_Type,
|
||||
&groupParam,
|
||||
&volVariant,
|
||||
&faceVariant,
|
||||
&edgeVariant)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string EncodedName = std::string(Name);
|
||||
PyMem_Free(Name);
|
||||
bool grpParam = Base::asBoolean(groupParam);
|
||||
auto itVol = volVariantPyMap.find(volVariant);
|
||||
auto itFace = faceVariantPyMap.find(faceVariant);
|
||||
auto itEdge = edgeVariantPyMap.find(edgeVariant);
|
||||
|
||||
if (itVol == volVariantPyMap.end() || itFace == faceVariantPyMap.end()
|
||||
|| itEdge == edgeVariantPyMap.end()) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid variant value");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try {
|
||||
getFemMeshPtr()->writeABAQUS(EncodedName.c_str(), elemParam, grpParam);
|
||||
getFemMeshPtr()->writeABAQUS(EncodedName.c_str(),
|
||||
elemParam,
|
||||
grpParam,
|
||||
itVol->second,
|
||||
itFace->second,
|
||||
itEdge->second);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
|
||||
|
||||
@@ -2343,24 +2343,6 @@ def get_three_non_colinear_nodes(
|
||||
return [node_1, node_2, node_3]
|
||||
|
||||
|
||||
# ************************************************************************************************
|
||||
def write_D_network_element_to_inputfile(
|
||||
fileName
|
||||
):
|
||||
# replace B32 elements with D elements for fluid section
|
||||
f = open(fileName, "r+")
|
||||
lines = f.readlines()
|
||||
f.seek(0)
|
||||
for line in lines:
|
||||
if line.find("B32") == -1:
|
||||
f.write(line)
|
||||
else:
|
||||
dummy = line.replace("B32", "D")
|
||||
f.write(dummy)
|
||||
f.truncate()
|
||||
f.close()
|
||||
|
||||
|
||||
# ************************************************************************************************
|
||||
def use_correct_fluidinout_ele_def(
|
||||
FluidInletoutlet_ele,
|
||||
@@ -2505,85 +2487,6 @@ def compact_mesh(
|
||||
# may be return another value if the mesh was compacted, just check last map entries
|
||||
return (new_mesh, node_map, elem_map)
|
||||
|
||||
# ************************************************************************************************
|
||||
def beam_reduced_integration(
|
||||
fileName
|
||||
):
|
||||
# replace B3x elements with B3xR elements
|
||||
f = open(fileName, "r+")
|
||||
lines = f.readlines()
|
||||
f.seek(0)
|
||||
for line in lines:
|
||||
if line.find("B32") != -1:
|
||||
line = line.replace("B32", "B32R")
|
||||
if line.find("B31") != -1:
|
||||
line = line.replace("B31", "B31R")
|
||||
f.write(line)
|
||||
|
||||
f.truncate()
|
||||
f.close()
|
||||
|
||||
def plane_stress(
|
||||
fileName
|
||||
):
|
||||
# replace shell elements with plane stress elements
|
||||
f = open(fileName, "r+")
|
||||
lines = f.readlines()
|
||||
f.seek(0)
|
||||
for line in lines:
|
||||
if line.find("S3") != -1:
|
||||
line = line.replace("S3", "CPS3")
|
||||
if line.find("S6") != -1:
|
||||
line = line.replace("S6", "CPS6")
|
||||
if line.find("S4") != -1:
|
||||
line = line.replace("S4", "CPS4")
|
||||
if line.find("S8") != -1:
|
||||
line = line.replace("S8", "CPS8")
|
||||
f.write(line)
|
||||
|
||||
f.truncate()
|
||||
f.close()
|
||||
def plane_strain(
|
||||
fileName
|
||||
):
|
||||
# replace shell elements with plane strain elements
|
||||
f = open(fileName, "r+")
|
||||
lines = f.readlines()
|
||||
f.seek(0)
|
||||
for line in lines:
|
||||
if line.find("S3") != -1:
|
||||
line = line.replace("S3", "CPE3")
|
||||
if line.find("S6") != -1:
|
||||
line = line.replace("S6", "CPE6")
|
||||
if line.find("S4") != -1:
|
||||
line = line.replace("S4", "CPE4")
|
||||
if line.find("S8") != -1:
|
||||
line = line.replace("S8", "CPE8")
|
||||
f.write(line)
|
||||
|
||||
f.truncate()
|
||||
f.close()
|
||||
def axisymmetric(
|
||||
fileName
|
||||
):
|
||||
# replace shell elements with axisymmetric elements
|
||||
f = open(fileName, "r+")
|
||||
lines = f.readlines()
|
||||
f.seek(0)
|
||||
for line in lines:
|
||||
if line.find("S3") != -1:
|
||||
line = line.replace("S3", "CAX3")
|
||||
if line.find("S6") != -1:
|
||||
line = line.replace("S6", "CAX6")
|
||||
if line.find("S4") != -1:
|
||||
line = line.replace("S4", "CAX4")
|
||||
if line.find("S8") != -1:
|
||||
line = line.replace("S8", "CAX8")
|
||||
f.write(line)
|
||||
|
||||
f.truncate()
|
||||
f.close()
|
||||
|
||||
# ************************************************************************************************
|
||||
def sub_shape_at_global_placement(obj, sub_name):
|
||||
sub_sh = obj.getSubObject(sub_name)
|
||||
|
||||
@@ -36,7 +36,27 @@ def write_mesh(ccxwriter):
|
||||
|
||||
element_param = 1 # highest element order only
|
||||
group_param = False # do not write mesh group data
|
||||
if ccxwriter.split_inpfile is True:
|
||||
|
||||
# Use reduced integration beam elements if this option is enabled in ccx solver settings
|
||||
vol_variant = "standard"
|
||||
edge_variant = "beam"
|
||||
if ccxwriter.solver_obj.BeamReducedIntegration:
|
||||
edge_variant = "beam reduced"
|
||||
# Check to see if fluid sections are in analysis and use D network element type
|
||||
if ccxwriter.member.geos_fluidsection:
|
||||
edge_variant = "network"
|
||||
|
||||
# Use 2D elements if model space is not set to 3D
|
||||
if ccxwriter.solver_obj.ModelSpace == "3D":
|
||||
face_variant = "shell"
|
||||
elif ccxwriter.solver_obj.ModelSpace == "plane stress":
|
||||
face_variant = "stress"
|
||||
elif ccxwriter.solver_obj.ModelSpace == "plane strain":
|
||||
face_variant = "strain"
|
||||
elif ccxwriter.solver_obj.ModelSpace == "axisymmetric":
|
||||
face_variant = "axisymmetric"
|
||||
|
||||
if ccxwriter.split_inpfile:
|
||||
write_name = "femesh"
|
||||
file_name_split = ccxwriter.mesh_name + "_" + write_name + ".inp"
|
||||
ccxwriter.femmesh_file = join(ccxwriter.dir_name, file_name_split)
|
||||
@@ -44,25 +64,12 @@ def write_mesh(ccxwriter):
|
||||
ccxwriter.femmesh.writeABAQUS(
|
||||
ccxwriter.femmesh_file,
|
||||
element_param,
|
||||
group_param
|
||||
group_param,
|
||||
volVariant=vol_variant,
|
||||
faceVariant=face_variant,
|
||||
edgeVariant=edge_variant
|
||||
)
|
||||
|
||||
# Check to see if fluid sections are in analysis and use D network element type
|
||||
if ccxwriter.member.geos_fluidsection:
|
||||
meshtools.write_D_network_element_to_inputfile(ccxwriter.femmesh_file)
|
||||
|
||||
# Use reduced integration beam elements if this option is enabled in ccx solver settings
|
||||
if ccxwriter.solver_obj.BeamReducedIntegration:
|
||||
meshtools.beam_reduced_integration(ccxwriter.femmesh_file)
|
||||
|
||||
# Use 2D elements if model space is not set to 3D
|
||||
if ccxwriter.solver_obj.ModelSpace == "plane stress":
|
||||
meshtools.plane_stress(ccxwriter.femmesh_file)
|
||||
if ccxwriter.solver_obj.ModelSpace == "plane strain":
|
||||
meshtools.plane_strain(ccxwriter.femmesh_file)
|
||||
if ccxwriter.solver_obj.ModelSpace == "axisymmetric":
|
||||
meshtools.axisymmetric(ccxwriter.femmesh_file)
|
||||
|
||||
inpfile = codecs.open(ccxwriter.file_name, "w", encoding="utf-8")
|
||||
inpfile.write("{}\n".format(59 * "*"))
|
||||
inpfile.write("** {}\n".format(write_name))
|
||||
@@ -73,26 +80,12 @@ def write_mesh(ccxwriter):
|
||||
ccxwriter.femmesh.writeABAQUS(
|
||||
ccxwriter.femmesh_file,
|
||||
element_param,
|
||||
group_param
|
||||
group_param,
|
||||
volVariant=vol_variant,
|
||||
faceVariant=face_variant,
|
||||
edgeVariant=edge_variant
|
||||
)
|
||||
|
||||
# Check to see if fluid sections are in analysis and use D network element type
|
||||
if ccxwriter.member.geos_fluidsection:
|
||||
# inpfile is closed
|
||||
meshtools.write_D_network_element_to_inputfile(ccxwriter.femmesh_file)
|
||||
|
||||
# Use reduced integration beam elements if this option is enabled in ccx solver settings
|
||||
if ccxwriter.solver_obj.BeamReducedIntegration:
|
||||
meshtools.beam_reduced_integration(ccxwriter.femmesh_file)
|
||||
|
||||
# Use 2D elements if model space is not set to 3D
|
||||
if ccxwriter.solver_obj.ModelSpace == "plane stress":
|
||||
meshtools.plane_stress(ccxwriter.femmesh_file)
|
||||
if ccxwriter.solver_obj.ModelSpace == "plane strain":
|
||||
meshtools.plane_strain(ccxwriter.femmesh_file)
|
||||
if ccxwriter.solver_obj.ModelSpace == "axisymmetric":
|
||||
meshtools.axisymmetric(ccxwriter.femmesh_file)
|
||||
|
||||
# reopen file with "append" to add all the rest
|
||||
inpfile = codecs.open(ccxwriter.femmesh_file, "a", encoding="utf-8")
|
||||
inpfile.write("\n\n")
|
||||
|
||||
Reference in New Issue
Block a user