Merge pull request #13464 from marioalexis84/fem-ccx_element_types

Fem: Add element types to ABAQUS writer
This commit is contained in:
Chris Hennes
2024-04-22 11:05:26 -05:00
committed by GitHub
6 changed files with 379 additions and 249 deletions

View File

@@ -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>>;

View File

@@ -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:

View File

@@ -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">

View File

@@ -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());

View File

@@ -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)

View File

@@ -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")