Files
create/src/Mod/Fem/App/FemMeshPyImp.cpp
Markus Reitböck c1be416c7f Fem: use CMake to generate precompiled headers on all platforms
"Professional CMake" book suggest the following:

"Targets should build successfully with or without compiler support for precompiled headers. It
 should be considered an optimization, not a requirement. In particular, do not explicitly include a
 precompile header (e.g. stdafx.h) in the source code, let CMake force-include an automatically
 generated precompile header on the compiler command line instead. This is more portable across
 the major compilers and is likely to be easier to maintain. It will also avoid warnings being
 generated from certain code checking tools like iwyu (include what you use)."

Therefore, removed the "#include <PreCompiled.h>" from sources, also
there is no need for the "#ifdef _PreComp_" anymore
2025-09-23 00:51:00 +02:00

1986 lines
68 KiB
C++

/***************************************************************************
* Copyright (c) 2009 Jürgen Riegel <juergen.riegel@web.de> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include <Python.h>
#include <SMDSAbs_ElementType.hxx>
#include <SMDS_MeshElement.hxx>
#include <SMESHDS_Group.hxx>
#include <SMESHDS_Mesh.hxx>
#include <SMESH_Group.hxx>
#include <SMESH_Mesh.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <algorithm>
#include <stdexcept>
#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>
#include <Mod/Part/App/TopoShapeEdgePy.h>
#include <Mod/Part/App/TopoShapeFacePy.h>
#include <Mod/Part/App/TopoShapePy.h>
#include <Mod/Part/App/TopoShapeSolidPy.h>
#include <Mod/Part/App/TopoShapeVertexPy.h>
// clang-format off
// inclusion of the generated files (generated out of FemMeshPy.xml)
#include "FemMeshPy.h"
#include "FemMeshPy.cpp"
#include "HypothesisPy.h"
// clang-format on
using namespace Fem;
// returns a string which represents the object e.g. when printed in python
std::string FemMeshPy::representation() const
{
std::stringstream str;
getFemMeshPtr()->getSMesh()->Dump(str);
return str.str();
}
PyObject* FemMeshPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
{
// create a new instance of FemMeshPy and the Twin object
return new FemMeshPy(new FemMesh);
}
// constructor method
int FemMeshPy::PyInit(PyObject* args, PyObject* /*kwd*/)
{
PyObject* pcObj = nullptr;
if (!PyArg_ParseTuple(args, "|O", &pcObj)) {
return -1;
}
try {
// if no mesh is given
if (!pcObj) {
return 0;
}
if (PyObject_TypeCheck(pcObj, &(FemMeshPy::Type))) {
getFemMeshPtr()->operator=(*static_cast<FemMeshPy*>(pcObj)->getFemMeshPtr());
}
else {
PyErr_Format(PyExc_TypeError,
"Cannot create a FemMesh out of a '%s'",
pcObj->ob_type->tp_name);
return -1;
}
}
catch (const Base::Exception& e) {
e.setPyException();
return -1;
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return -1;
}
catch (const Py::Exception&) {
return -1;
}
return 0;
}
// ===== Methods ============================================================
PyObject* FemMeshPy::setShape(PyObject* args)
{
PyObject* pcObj;
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &pcObj)) {
return nullptr;
}
try {
TopoDS_Shape shape = static_cast<Part::TopoShapePy*>(pcObj)->getTopoShapePtr()->getShape();
getFemMeshPtr()->getSMesh()->ShapeToMesh(shape);
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
Py_Return;
}
PyObject* FemMeshPy::addHypothesis(PyObject* args)
{
PyObject* hyp;
PyObject* shp = nullptr;
// Since we have not a common base class for the Python binding of the
// hypotheses classes we cannot pass a certain Python type
if (!PyArg_ParseTuple(args, "O|O!", &hyp, &(Part::TopoShapePy::Type), &shp)) {
return nullptr;
}
TopoDS_Shape shape;
if (!shp) {
shape = getFemMeshPtr()->getSMesh()->GetShapeToMesh();
}
else {
shape = static_cast<Part::TopoShapePy*>(shp)->getTopoShapePtr()->getShape();
}
try {
Py::Object obj(hyp);
Fem::Hypothesis attr(obj.getAttr("this"));
SMESH_HypothesisPtr thesis = attr.extensionObject()->getHypothesis();
getFemMeshPtr()->addHypothesis(shape, thesis);
}
catch (const Py::Exception&) {
return nullptr;
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
Py_Return;
}
PyObject* FemMeshPy::setStandardHypotheses(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
try {
getFemMeshPtr()->setStandardHypotheses();
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
Py_Return;
}
PyObject* FemMeshPy::compute(PyObject* args)
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
try {
getFemMeshPtr()->compute();
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
Py_Return;
}
PyObject* FemMeshPy::addNode(PyObject* args)
{
double x, y, z;
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::Long(node->GetID()));
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
}
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::Long(node->GetID()));
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
}
PyErr_SetString(PyExc_TypeError,
"addNode() accepts:\n"
"-- addNode(x,y,z)\n"
"-- addNode(x,y,z,ElemId)\n");
return nullptr;
}
PyObject* FemMeshPy::addEdge(PyObject* args)
{
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
int n1, n2;
if (PyArg_ParseTuple(args, "ii", &n1, &n2)) {
try {
const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
if (!node1 || !node2) {
throw std::runtime_error("Failed to get node of the given indices");
}
SMDS_MeshEdge* edge = meshDS->AddEdge(node1, node2);
if (!edge) {
throw std::runtime_error("Failed to add edge");
}
return Py::new_reference_to(Py::Long(edge->GetID()));
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
}
PyErr_Clear();
PyObject* obj;
int ElementId = -1;
if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) {
Py::List list(obj);
std::vector<const SMDS_MeshNode*> Nodes;
for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
Py::Long NoNr(*it);
const SMDS_MeshNode* node = meshDS->FindNode(NoNr);
if (!node) {
throw std::runtime_error("Failed to get node of the given indices");
}
Nodes.push_back(node);
}
SMDS_MeshEdge* edge = nullptr;
if (ElementId != -1) {
switch (Nodes.size()) {
case 2:
edge = meshDS->AddEdgeWithID(Nodes[0], Nodes[1], ElementId);
if (!edge) {
throw std::runtime_error("Failed to add edge with given ElementId");
}
break;
case 3:
edge = meshDS->AddEdgeWithID(Nodes[0], Nodes[1], Nodes[2], ElementId);
if (!edge) {
throw std::runtime_error("Failed to add edge with given ElementId");
}
break;
default:
throw std::runtime_error(
"Unknown node count, [2|3] are allowed"); // unknown edge type
}
}
else {
switch (Nodes.size()) {
case 2:
edge = meshDS->AddEdge(Nodes[0], Nodes[1]);
if (!edge) {
throw std::runtime_error("Failed to add edge");
}
break;
case 3:
edge = meshDS->AddEdge(Nodes[0], Nodes[1], Nodes[2]);
if (!edge) {
throw std::runtime_error("Failed to add edge");
}
break;
default:
throw std::runtime_error(
"Unknown node count, [2|3] are allowed"); // unknown edge type
}
}
return Py::new_reference_to(Py::Long(edge->GetID()));
}
PyErr_SetString(PyExc_TypeError,
"addEdge accepts:\n"
"-- int,int\n"
"-- [2|3],[int]\n");
return nullptr;
}
PyObject* FemMeshPy::addFace(PyObject* args)
{
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
int n1, n2, n3;
if (PyArg_ParseTuple(args, "iii", &n1, &n2, &n3)) {
// old form, deprecated
try {
const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
if (!node1 || !node2 || !node3) {
throw std::runtime_error("Failed to get node of the given indices");
}
SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3);
if (!face) {
throw std::runtime_error("Failed to add face");
}
return Py::new_reference_to(Py::Long(face->GetID()));
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
}
PyErr_Clear();
PyObject* obj;
int ElementId = -1;
if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) {
Py::List list(obj);
std::vector<const SMDS_MeshNode*> Nodes;
for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
Py::Long NoNr(*it);
const SMDS_MeshNode* node = meshDS->FindNode(NoNr);
if (!node) {
throw std::runtime_error("Failed to get node of the given indices");
}
Nodes.push_back(node);
}
SMDS_MeshFace* face = nullptr;
if (ElementId != -1) {
switch (Nodes.size()) {
case 3:
face = meshDS->AddFaceWithID(Nodes[0], Nodes[1], Nodes[2], ElementId);
if (!face) {
throw std::runtime_error(
"Failed to add triangular face with given ElementId");
}
break;
case 4:
face = meshDS->AddFaceWithID(Nodes[0], Nodes[1], Nodes[2], Nodes[3], ElementId);
if (!face) {
throw std::runtime_error("Failed to add face with given ElementId");
}
break;
case 6:
face = meshDS->AddFaceWithID(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5],
ElementId);
if (!face) {
throw std::runtime_error("Failed to add face with given ElementId");
}
break;
case 8:
face = meshDS->AddFaceWithID(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5],
Nodes[6],
Nodes[7],
ElementId);
if (!face) {
throw std::runtime_error("Failed to add face with given ElementId");
}
break;
default:
throw std::runtime_error(
"Unknown node count, [3|4|6|8] are allowed"); // unknown face type
}
}
else {
switch (Nodes.size()) {
case 3:
face = meshDS->AddFace(Nodes[0], Nodes[1], Nodes[2]);
if (!face) {
throw std::runtime_error("Failed to add triangular face");
}
break;
case 4:
face = meshDS->AddFace(Nodes[0], Nodes[1], Nodes[2], Nodes[3]);
if (!face) {
throw std::runtime_error("Failed to add face");
}
break;
case 6:
face =
meshDS->AddFace(Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5]);
if (!face) {
throw std::runtime_error("Failed to add face");
}
break;
case 8:
face = meshDS->AddFace(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5],
Nodes[6],
Nodes[7]);
if (!face) {
throw std::runtime_error("Failed to add face");
}
break;
default:
throw std::runtime_error(
"Unknown node count, [4|5|6|8] are allowed"); // unknown face type
}
}
return Py::new_reference_to(Py::Long(face->GetID()));
}
PyErr_SetString(PyExc_TypeError,
"addFace accepts:\n"
"-- int,int,int\n"
"-- [3|4|6|8 int],[int]\n");
return nullptr;
}
PyObject* FemMeshPy::addQuad(PyObject* args)
{
int n1, n2, n3, n4;
if (!PyArg_ParseTuple(args, "iiii", &n1, &n2, &n3, &n4)) {
return nullptr;
}
try {
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
const SMDS_MeshNode* node4 = meshDS->FindNode(n4);
if (!node1 || !node2 || !node3 || !node4) {
throw std::runtime_error("Failed to get node of the given indices");
}
SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3, node4);
if (!face) {
throw std::runtime_error("Failed to add quad");
}
return Py::new_reference_to(Py::Long(face->GetID()));
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
}
PyObject* FemMeshPy::addVolume(PyObject* args)
{
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
int n1, n2, n3, n4;
if (PyArg_ParseTuple(args, "iiii", &n1, &n2, &n3, &n4)) {
try {
const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
const SMDS_MeshNode* node4 = meshDS->FindNode(n4);
if (!node1 || !node2 || !node3 || !node4) {
throw std::runtime_error("Failed to get node of the given indices");
}
SMDS_MeshVolume* vol = meshDS->AddVolume(node1, node2, node3, node4);
if (!vol) {
throw std::runtime_error("Failed to add volume");
}
return Py::new_reference_to(Py::Long(vol->GetID()));
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
}
PyErr_Clear();
PyObject* obj;
int ElementId = -1;
if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) {
Py::List list(obj);
std::vector<const SMDS_MeshNode*> Nodes;
for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
Py::Long NoNr(*it);
const SMDS_MeshNode* node = meshDS->FindNode(NoNr);
if (!node) {
throw std::runtime_error("Failed to get node of the given indices");
}
Nodes.push_back(node);
}
SMDS_MeshVolume* vol = nullptr;
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 with given ElementId");
}
break;
case 5:
vol = meshDS->AddVolumeWithID(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
ElementId);
if (!vol) {
throw std::runtime_error("Failed to add Pyra5 volume with given ElementId");
}
break;
case 6:
vol = meshDS->AddVolumeWithID(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5],
ElementId);
if (!vol) {
throw std::runtime_error(
"Failed to add Penta6 volume with given ElementId");
}
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 Hexa8 volume with given ElementId");
}
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 with given ElementId");
}
break;
case 13:
vol = meshDS->AddVolumeWithID(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5],
Nodes[6],
Nodes[7],
Nodes[8],
Nodes[9],
Nodes[10],
Nodes[11],
Nodes[12],
ElementId);
if (!vol) {
throw std::runtime_error(
"Failed to add Pyra13 volume with given ElementId");
}
break;
case 15:
vol = meshDS->AddVolumeWithID(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5],
Nodes[6],
Nodes[7],
Nodes[8],
Nodes[9],
Nodes[10],
Nodes[11],
Nodes[12],
Nodes[13],
Nodes[14],
ElementId);
if (!vol) {
throw std::runtime_error(
"Failed to add Penta15 volume with given ElementId");
}
break;
case 20:
vol = meshDS->AddVolumeWithID(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5],
Nodes[6],
Nodes[7],
Nodes[8],
Nodes[9],
Nodes[10],
Nodes[11],
Nodes[12],
Nodes[13],
Nodes[14],
Nodes[15],
Nodes[16],
Nodes[17],
Nodes[18],
Nodes[19],
ElementId);
if (!vol) {
throw std::runtime_error(
"Failed to add Hexa20 volume with given ElementId");
}
break;
default:
throw std::runtime_error(
"Unknown node count, [4|5|6|8|10|13|15|20] are allowed"); // unknown volume
// 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 5:
vol = meshDS->AddVolume(Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4]);
if (!vol) {
throw std::runtime_error("Failed to add Pyra5 volume");
}
break;
case 6:
vol = meshDS->AddVolume(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5]);
if (!vol) {
throw std::runtime_error("Failed to add Penta6 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 Hexa8 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;
case 13:
vol = meshDS->AddVolume(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5],
Nodes[6],
Nodes[7],
Nodes[8],
Nodes[9],
Nodes[10],
Nodes[11],
Nodes[12]);
if (!vol) {
throw std::runtime_error("Failed to add Pyra13 volume");
}
break;
case 15:
vol = meshDS->AddVolume(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5],
Nodes[6],
Nodes[7],
Nodes[8],
Nodes[9],
Nodes[10],
Nodes[11],
Nodes[12],
Nodes[13],
Nodes[14]);
if (!vol) {
throw std::runtime_error("Failed to add Penta15 volume");
}
break;
case 20:
vol = meshDS->AddVolume(Nodes[0],
Nodes[1],
Nodes[2],
Nodes[3],
Nodes[4],
Nodes[5],
Nodes[6],
Nodes[7],
Nodes[8],
Nodes[9],
Nodes[10],
Nodes[11],
Nodes[12],
Nodes[13],
Nodes[14],
Nodes[15],
Nodes[16],
Nodes[17],
Nodes[18],
Nodes[19]);
if (!vol) {
throw std::runtime_error("Failed to add Hexa20 volume");
}
break;
default:
throw std::runtime_error(
"Unknown node count, [4|5|6|8|10|13|15|20] are allowed"); // unknown volume
// type
}
}
return Py::new_reference_to(Py::Long(vol->GetID()));
}
PyErr_SetString(PyExc_TypeError,
"addVolume accepts:\n"
"-- int,int,int,int\n"
"-- [4|5|6|8|10|13|15|20 int],[int]\n");
return nullptr;
}
PyObject* FemMeshPy::addEdgeList(PyObject* args)
{
PyObject* nodesObj = nullptr;
PyObject* npObj = nullptr;
;
if (!PyArg_ParseTuple(args, "O!O!", &PyList_Type, &nodesObj, &PyList_Type, &npObj)) {
return nullptr;
}
Py::List nodesList(nodesObj);
Py::List npList(npObj);
SMESHDS_Mesh* meshDS = getFemMeshPtr()->getSMesh()->GetMeshDS();
std::vector<const SMDS_MeshNode*> nodes;
for (Py::List::iterator it = nodesList.begin(); it != nodesList.end(); ++it) {
Py::Long n(*it);
const SMDS_MeshNode* node = meshDS->FindNode(static_cast<int>(n));
if (!node) {
throw std::runtime_error("Failed to get node of the given indices");
}
nodes.push_back(node);
}
std::vector<const SMDS_MeshNode*>::iterator nodeIt = nodes.begin();
SMDS_MeshEdge* edge = nullptr;
Py::List result;
int np = 0;
for (Py::List::iterator it = npList.begin(); it != npList.end(); ++it, nodeIt += np) {
np = Py::Long(*it);
std::vector<const SMDS_MeshNode*> nodesElem(nodeIt, nodeIt + np);
switch (np) {
case 2:
edge = meshDS->AddEdge(nodesElem[0], nodesElem[1]);
break;
case 3:
edge = meshDS->AddEdge(nodesElem[0], nodesElem[1], nodesElem[2]);
break;
default:
PyErr_SetString(PyExc_TypeError, "Unknown node count, [2|3] are allowed");
return nullptr;
}
if (edge) {
result.append(Py::Long(edge->GetID()));
}
else {
PyErr_SetString(PyExc_TypeError, "Failed to add edge");
return nullptr;
}
}
return Py::new_reference_to(result);
}
PyObject* FemMeshPy::addFaceList(PyObject* args)
{
PyObject* nodesObj = nullptr;
PyObject* npObj = nullptr;
;
if (!PyArg_ParseTuple(args, "O!O!", &PyList_Type, &nodesObj, &PyList_Type, &npObj)) {
return nullptr;
}
Py::List nodesList(nodesObj);
Py::List npList(npObj);
SMESHDS_Mesh* meshDS = getFemMeshPtr()->getSMesh()->GetMeshDS();
std::vector<const SMDS_MeshNode*> nodes;
for (Py::List::iterator it = nodesList.begin(); it != nodesList.end(); ++it) {
Py::Long n(*it);
const SMDS_MeshNode* node = meshDS->FindNode(static_cast<int>(n));
if (!node) {
throw std::runtime_error("Failed to get node of the given indices");
}
nodes.push_back(node);
}
std::vector<const SMDS_MeshNode*>::iterator nodeIt = nodes.begin();
SMDS_MeshFace* face = nullptr;
Py::List result;
int np = 0;
for (Py::List::iterator it = npList.begin(); it != npList.end(); ++it, nodeIt += np) {
np = Py::Long(*it);
std::vector<const SMDS_MeshNode*> nodesElem(nodeIt, nodeIt + np);
switch (np) {
case 3:
face = meshDS->AddFace(nodesElem[0], nodesElem[1], nodesElem[2]);
break;
case 4:
face = meshDS->AddFace(nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3]);
break;
case 6:
face = meshDS->AddFace(nodesElem[0],
nodesElem[1],
nodesElem[2],
nodesElem[3],
nodesElem[4],
nodesElem[5]);
break;
case 8:
face = meshDS->AddFace(nodesElem[0],
nodesElem[1],
nodesElem[2],
nodesElem[3],
nodesElem[4],
nodesElem[5],
nodesElem[6],
nodesElem[7]);
break;
default:
PyErr_SetString(PyExc_TypeError, "Unknown node count, [3|4|6|8] are allowed");
return nullptr;
}
if (face) {
result.append(Py::Long(face->GetID()));
}
else {
PyErr_SetString(PyExc_TypeError, "Failed to add face");
return nullptr;
}
}
return Py::new_reference_to(result);
}
PyObject* FemMeshPy::addVolumeList(PyObject* args)
{
PyObject* nodesObj = nullptr;
PyObject* npObj = nullptr;
;
if (!PyArg_ParseTuple(args, "O!O!", &PyList_Type, &nodesObj, &PyList_Type, &npObj)) {
return nullptr;
}
Py::List nodesList(nodesObj);
Py::List npList(npObj);
SMESHDS_Mesh* meshDS = getFemMeshPtr()->getSMesh()->GetMeshDS();
std::vector<const SMDS_MeshNode*> nodes;
for (Py::List::iterator it = nodesList.begin(); it != nodesList.end(); ++it) {
Py::Long n(*it);
const SMDS_MeshNode* node = meshDS->FindNode(static_cast<int>(n));
if (!node) {
throw std::runtime_error("Failed to get node of the given indices");
}
nodes.push_back(node);
}
std::vector<const SMDS_MeshNode*>::iterator nodeIt = nodes.begin();
SMDS_MeshVolume* vol = nullptr;
Py::List result;
int np = 0;
for (Py::List::iterator it = npList.begin(); it != npList.end(); ++it, nodeIt += np) {
np = Py::Long(*it);
std::vector<const SMDS_MeshNode*> nodesElem(nodeIt, nodeIt + np);
switch (np) {
case 4:
vol = meshDS->AddVolume(nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3]);
break;
case 5:
vol = meshDS->AddVolume(nodesElem[0],
nodesElem[1],
nodesElem[2],
nodesElem[3],
nodesElem[4]);
break;
case 6:
vol = meshDS->AddVolume(nodesElem[0],
nodesElem[1],
nodesElem[2],
nodesElem[3],
nodesElem[4],
nodesElem[5]);
break;
case 8:
vol = meshDS->AddVolume(nodesElem[0],
nodesElem[1],
nodesElem[2],
nodesElem[3],
nodesElem[4],
nodesElem[5],
nodesElem[6],
nodesElem[7]);
break;
case 10:
vol = meshDS->AddVolume(nodesElem[0],
nodesElem[1],
nodesElem[2],
nodesElem[3],
nodesElem[4],
nodesElem[5],
nodesElem[6],
nodesElem[7],
nodesElem[8],
nodesElem[9]);
break;
case 13:
vol = meshDS->AddVolume(nodesElem[0],
nodesElem[1],
nodesElem[2],
nodesElem[3],
nodesElem[4],
nodesElem[5],
nodesElem[6],
nodesElem[7],
nodesElem[8],
nodesElem[9],
nodesElem[10],
nodesElem[11],
nodesElem[12]);
break;
case 15:
vol = meshDS->AddVolume(nodesElem[0],
nodesElem[1],
nodesElem[2],
nodesElem[3],
nodesElem[4],
nodesElem[5],
nodesElem[6],
nodesElem[7],
nodesElem[8],
nodesElem[9],
nodesElem[10],
nodesElem[11],
nodesElem[12],
nodesElem[13],
nodesElem[14]);
break;
case 20:
vol = meshDS->AddVolume(nodesElem[0],
nodesElem[1],
nodesElem[2],
nodesElem[3],
nodesElem[4],
nodesElem[5],
nodesElem[6],
nodesElem[7],
nodesElem[8],
nodesElem[9],
nodesElem[10],
nodesElem[11],
nodesElem[12],
nodesElem[13],
nodesElem[14],
nodesElem[15],
nodesElem[16],
nodesElem[17],
nodesElem[18],
nodesElem[19]);
break;
default:
PyErr_SetString(PyExc_TypeError,
"Unknown node count, [4|5|6|8|10|13|15|20] are allowed");
return nullptr;
}
if (vol) {
result.append(Py::Long(vol->GetID()));
}
else {
PyErr_SetString(PyExc_TypeError, "Failed to add face");
return nullptr;
}
}
return Py::new_reference_to(result);
}
PyObject* FemMeshPy::copy(PyObject* args) const
{
if (!PyArg_ParseTuple(args, "")) {
return nullptr;
}
const FemMesh& mesh = *getFemMeshPtr();
return new FemMeshPy(new FemMesh(mesh));
}
PyObject* FemMeshPy::read(PyObject* args)
{
char* Name;
if (!PyArg_ParseTuple(args, "et", "utf-8", &Name)) {
return nullptr;
}
std::string EncodedName = std::string(Name);
PyMem_Free(Name);
try {
getFemMeshPtr()->read(EncodedName.c_str());
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
Py_Return;
}
PyObject* FemMeshPy::write(PyObject* args) const
{
char* Name;
if (!PyArg_ParseTuple(args, "et", "utf-8", &Name)) {
return nullptr;
}
std::string EncodedName = std::string(Name);
PyMem_Free(Name);
try {
getFemMeshPtr()->write(EncodedName.c_str());
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
Py_Return;
}
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) const
{
char* Name;
int elemParam;
PyObject* 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,
itVol->second,
itFace->second,
itEdge->second);
}
catch (const std::exception& e) {
PyErr_SetString(Base::PyExc_FC_GeneralError, e.what());
return nullptr;
}
Py_Return;
}
PyObject* FemMeshPy::setTransform(PyObject* args)
{
PyObject* ptr;
if (!PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type), &ptr)) {
return nullptr;
}
Base::Placement* placement = static_cast<Base::PlacementPy*>(ptr)->getPlacementPtr();
Base::Matrix4D mat = placement->toMatrix();
getFemMeshPtr()->transformGeometry(mat);
Py_Return;
}
PyObject* FemMeshPy::getFacesByFace(PyObject* args) const
{
PyObject* pW;
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeFacePy::Type), &pW)) {
return nullptr;
}
try {
const TopoDS_Shape& sh =
static_cast<Part::TopoShapeFacePy*>(pW)->getTopoShapePtr()->getShape();
if (sh.IsNull()) {
PyErr_SetString(PyExc_ValueError, "Face is empty");
return nullptr;
}
const TopoDS_Face& fc = TopoDS::Face(sh);
Py::List ret;
std::list<int> resultSet = getFemMeshPtr()->getFacesByFace(fc);
for (std::list<int>::const_iterator it = resultSet.begin(); it != resultSet.end(); ++it) {
ret.append(Py::Long(*it));
}
return Py::new_reference_to(ret);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
}
PyObject* FemMeshPy::getEdgesByEdge(PyObject* args) const
{
PyObject* pW;
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeEdgePy::Type), &pW)) {
return nullptr;
}
try {
const TopoDS_Shape& sh =
static_cast<Part::TopoShapeEdgePy*>(pW)->getTopoShapePtr()->getShape();
if (sh.IsNull()) {
PyErr_SetString(PyExc_ValueError, "Edge is empty");
return nullptr;
}
const TopoDS_Edge& fc = TopoDS::Edge(sh);
Py::List ret;
std::list<int> resultSet = getFemMeshPtr()->getEdgesByEdge(fc);
for (std::list<int>::const_iterator it = resultSet.begin(); it != resultSet.end(); ++it) {
ret.append(Py::Long(*it));
}
return Py::new_reference_to(ret);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
}
PyObject* FemMeshPy::getVolumesByFace(PyObject* args) const
{
PyObject* pW;
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeFacePy::Type), &pW)) {
return nullptr;
}
try {
const TopoDS_Shape& sh =
static_cast<Part::TopoShapeFacePy*>(pW)->getTopoShapePtr()->getShape();
if (sh.IsNull()) {
PyErr_SetString(PyExc_ValueError, "Face is empty");
return nullptr;
}
const TopoDS_Face& fc = TopoDS::Face(sh);
Py::List ret;
std::list<std::pair<int, int>> resultSet = getFemMeshPtr()->getVolumesByFace(fc);
for (std::list<std::pair<int, int>>::const_iterator it = resultSet.begin();
it != resultSet.end();
++it) {
Py::Tuple vol_face(2);
vol_face.setItem(0, Py::Long(it->first));
vol_face.setItem(1, Py::Long(it->second));
ret.append(vol_face);
}
return Py::new_reference_to(ret);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
}
PyObject* FemMeshPy::getccxVolumesByFace(PyObject* args) const
{
PyObject* pW;
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeFacePy::Type), &pW)) {
return nullptr;
}
try {
const TopoDS_Shape& sh =
static_cast<Part::TopoShapeFacePy*>(pW)->getTopoShapePtr()->getShape();
if (sh.IsNull()) {
PyErr_SetString(PyExc_ValueError, "Face is empty");
return nullptr;
}
const TopoDS_Face& fc = TopoDS::Face(sh);
Py::List ret;
std::map<int, int> resultSet = getFemMeshPtr()->getccxVolumesByFace(fc);
for (std::map<int, int>::const_iterator it = resultSet.begin(); it != resultSet.end();
++it) {
Py::Tuple vol_face(2);
vol_face.setItem(0, Py::Long(it->first));
vol_face.setItem(1, Py::Long(it->second));
ret.append(vol_face);
}
return Py::new_reference_to(ret);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
}
PyObject* FemMeshPy::getNodeById(PyObject* args) const
{
int id;
if (!PyArg_ParseTuple(args, "i", &id)) {
return nullptr;
}
Base::Matrix4D Mtrx = getFemMeshPtr()->getTransform();
const SMDS_MeshNode* aNode = getFemMeshPtr()->getSMesh()->GetMeshDS()->FindNode(id);
if (aNode) {
Base::Vector3d vec(aNode->X(), aNode->Y(), aNode->Z());
vec = Mtrx * vec;
return new Base::VectorPy(vec);
}
else {
PyErr_SetString(PyExc_ValueError, "No valid node ID");
return nullptr;
}
}
PyObject* FemMeshPy::getNodesBySolid(PyObject* args) const
{
PyObject* pW;
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeSolidPy::Type), &pW)) {
return nullptr;
}
try {
const TopoDS_Shape& sh =
static_cast<Part::TopoShapeSolidPy*>(pW)->getTopoShapePtr()->getShape();
const TopoDS_Solid& fc = TopoDS::Solid(sh);
if (sh.IsNull()) {
PyErr_SetString(PyExc_ValueError, "Solid is empty");
return nullptr;
}
Py::List ret;
std::set<int> resultSet = getFemMeshPtr()->getNodesBySolid(fc);
for (int it : resultSet) {
ret.append(Py::Long(it));
}
return Py::new_reference_to(ret);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
}
PyObject* FemMeshPy::getNodesByFace(PyObject* args) const
{
PyObject* pW;
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeFacePy::Type), &pW)) {
return nullptr;
}
try {
const TopoDS_Shape& sh =
static_cast<Part::TopoShapeFacePy*>(pW)->getTopoShapePtr()->getShape();
const TopoDS_Face& fc = TopoDS::Face(sh);
if (sh.IsNull()) {
PyErr_SetString(PyExc_ValueError, "Face is empty");
return nullptr;
}
Py::List ret;
std::set<int> resultSet = getFemMeshPtr()->getNodesByFace(fc);
for (int it : resultSet) {
ret.append(Py::Long(it));
}
return Py::new_reference_to(ret);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
}
PyObject* FemMeshPy::getNodesByEdge(PyObject* args) const
{
PyObject* pW;
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeEdgePy::Type), &pW)) {
return nullptr;
}
try {
const TopoDS_Shape& sh =
static_cast<Part::TopoShapeEdgePy*>(pW)->getTopoShapePtr()->getShape();
const TopoDS_Edge& fc = TopoDS::Edge(sh);
if (sh.IsNull()) {
PyErr_SetString(PyExc_ValueError, "Edge is empty");
return nullptr;
}
Py::List ret;
std::set<int> resultSet = getFemMeshPtr()->getNodesByEdge(fc);
for (int it : resultSet) {
ret.append(Py::Long(it));
}
return Py::new_reference_to(ret);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
}
PyObject* FemMeshPy::getNodesByVertex(PyObject* args) const
{
PyObject* pW;
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeVertexPy::Type), &pW)) {
return nullptr;
}
try {
const TopoDS_Shape& sh =
static_cast<Part::TopoShapeVertexPy*>(pW)->getTopoShapePtr()->getShape();
const TopoDS_Vertex& fc = TopoDS::Vertex(sh);
if (sh.IsNull()) {
PyErr_SetString(PyExc_ValueError, "Vertex is empty");
return nullptr;
}
Py::List ret;
std::set<int> resultSet = getFemMeshPtr()->getNodesByVertex(fc);
for (int it : resultSet) {
ret.append(Py::Long(it));
}
return Py::new_reference_to(ret);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
}
PyObject* FemMeshPy::getElementNodes(PyObject* args) const
{
int id;
if (!PyArg_ParseTuple(args, "i", &id)) {
return nullptr;
}
try {
std::list<int> resultSet = getFemMeshPtr()->getElementNodes(id);
Py::Tuple ret(resultSet.size());
int index = 0;
for (std::list<int>::const_iterator it = resultSet.begin(); it != resultSet.end(); ++it) {
ret.setItem(index++, Py::Long(*it));
}
return Py::new_reference_to(ret);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
}
using pairStrElemType = std::pair<std::string, SMDSAbs_ElementType>;
const std::vector<pairStrElemType> vecTypeName = {
{"All", SMDSAbs_All},
{"Node", SMDSAbs_Node},
{"Edge", SMDSAbs_Edge},
{"Face", SMDSAbs_Face},
{"Volume", SMDSAbs_Volume},
{"0DElement", SMDSAbs_0DElement},
{"Ball", SMDSAbs_Ball},
};
PyObject* FemMeshPy::getNodeElements(PyObject* args) const
{
int id;
const char* typeStr = "All";
if (!PyArg_ParseTuple(args, "i|s", &id, &typeStr)) {
return nullptr;
}
auto it = std::find_if(vecTypeName.begin(), vecTypeName.end(), [=](const pairStrElemType& x) {
return x.first == typeStr;
});
if (it == vecTypeName.end()) {
PyErr_SetString(PyExc_ValueError, "Invalid element type");
return nullptr;
}
SMDSAbs_ElementType elemType = it->second;
std::list<int> elemList = getFemMeshPtr()->getNodeElements(id, elemType);
Py::Tuple result(elemList.size());
int index = 0;
for (int it : elemList) {
result.setItem(index++, Py::Long(it));
}
return Py::new_reference_to(result);
}
PyObject* FemMeshPy::getGroupName(PyObject* args) const
{
int id;
if (!PyArg_ParseTuple(args, "i", &id)) {
return nullptr;
}
SMESH_Group* group = getFemMeshPtr()->getSMesh()->GetGroup(id);
if (!group) {
PyErr_SetString(PyExc_ValueError, "No group for given id");
return nullptr;
}
return PyUnicode_FromString(group->GetName());
}
PyObject* FemMeshPy::getGroupElementType(PyObject* args) const
{
int id;
if (!PyArg_ParseTuple(args, "i", &id)) {
return nullptr;
}
SMESH_Group* group = getFemMeshPtr()->getSMesh()->GetGroup(id);
if (!group) {
PyErr_SetString(PyExc_ValueError, "No group for given id");
return nullptr;
}
SMDSAbs_ElementType elemType = group->GetGroupDS()->GetType();
auto it = std::find_if(vecTypeName.begin(), vecTypeName.end(), [=](const pairStrElemType& x) {
return x.second == elemType;
});
const char* typeStr = it != vecTypeName.end() ? it->first.c_str() : "Unknown";
return PyUnicode_FromString(typeStr);
}
PyObject* FemMeshPy::getGroupElements(PyObject* args) const
{
int id;
if (!PyArg_ParseTuple(args, "i", &id)) {
return nullptr;
}
SMESH_Group* group = getFemMeshPtr()->getSMesh()->GetGroup(id);
if (!group) {
PyErr_SetString(PyExc_ValueError, "No group for given id");
return nullptr;
}
std::set<int> ids;
SMDS_ElemIteratorPtr aElemIter = group->GetGroupDS()->GetElements();
while (aElemIter->more()) {
const SMDS_MeshElement* aElement = aElemIter->next();
ids.insert(aElement->GetID());
}
Py::Tuple tuple(ids.size());
int index = 0;
for (int it : ids) {
tuple.setItem(index++, Py::Long(it));
}
return Py::new_reference_to(tuple);
}
/*
Add Groups and elements to these.
*/
PyObject* FemMeshPy::addGroup(PyObject* args) const
{
// get name and typestring from arguments
char* Name;
char* typeString;
int theId = -1;
if (!PyArg_ParseTuple(args, "etet|i", "utf-8", &Name, "utf-8", &typeString, &theId)) {
return nullptr;
}
std::string EncodedName = std::string(Name);
PyMem_Free(Name);
std::string EncodedTypeString = std::string(typeString);
PyMem_Free(typeString);
int retId = -1;
try {
retId = getFemMeshPtr()->addGroup(EncodedTypeString, EncodedName, theId);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
std::cout << "Added Group: Name: \'" << EncodedName << "\' Type: \'" << EncodedTypeString
<< "\' id: " << retId << std::endl;
return PyLong_FromLong(retId);
}
PyObject* FemMeshPy::addGroupElements(PyObject* args) const
{
int id;
// the second object should be a list
// see
// https://stackoverflow.com/questions/22458298/extending-python-with-c-pass-a-list-to-pyarg-parsetuple
PyObject* pList;
PyObject* pItem;
Py_ssize_t n;
if (!PyArg_ParseTuple(args, "iO!", &id, &PyList_Type, &pList)) {
PyErr_SetString(PyExc_TypeError, "AddGroupElements: 2nd Parameter must be a list.");
return nullptr;
}
std::set<Py_ssize_t> ids;
n = PyList_Size(pList);
std::cout << "AddGroupElements: num elements: " << n << " sizeof: " << sizeof(n) << std::endl;
for (Py_ssize_t i = 0; i < n; i++) {
pItem = PyList_GetItem(pList, i);
if (!PyLong_Check(pItem)) {
PyErr_SetString(PyExc_TypeError, "AddGroupElements: List items must be integers.");
return nullptr;
}
ids.insert(PyLong_AsSsize_t(pItem));
// Py_ssize_t transparently handles maximum array lengths on 32bit and 64bit machines
// See: https://www.python.org/dev/peps/pep-0353/
}
// Downcast Py_ssize_t to int to be compatible with SMESH functions
std::set<int> int_ids;
for (Py_ssize_t it : ids) {
int_ids.insert(Py_SAFE_DOWNCAST(it, Py_ssize_t, int));
}
try {
getFemMeshPtr()->addGroupElements(id, int_ids);
}
catch (Standard_Failure& e) {
PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString());
return nullptr;
}
Py_Return;
}
PyObject* FemMeshPy::removeGroup(PyObject* args) const
{
int theId;
if (!PyArg_ParseTuple(args, "i", &theId)) {
return nullptr;
}
return PyBool_FromLong((long)(getFemMeshPtr()->removeGroup(theId)));
}
PyObject* FemMeshPy::getElementType(PyObject* args) const
{
int id;
if (!PyArg_ParseTuple(args, "i", &id)) {
return nullptr;
}
// An element ...
SMDSAbs_ElementType elemType = getFemMeshPtr()->getSMesh()->GetElementType(id, true);
// ... or a node
if (elemType == SMDSAbs_All) {
elemType = getFemMeshPtr()->getSMesh()->GetElementType(id, false);
}
auto it =
std::find_if(vecTypeName.begin() + 1, vecTypeName.end(), [=](const pairStrElemType& x) {
return x.second == elemType;
});
const char* typeStr = it != vecTypeName.end() ? it->first.c_str() : nullptr;
if (!typeStr) {
PyErr_SetString(PyExc_ValueError, "No node or element for given id");
return nullptr;
}
return PyUnicode_FromString(typeStr);
}
PyObject* FemMeshPy::getIdByElementType(PyObject* args) const
{
const char* typeStr;
if (!PyArg_ParseTuple(args, "s", &typeStr)) {
return nullptr;
}
auto it = std::find_if(vecTypeName.begin(), vecTypeName.end(), [=](const pairStrElemType& x) {
return x.first == typeStr;
});
if (it == vecTypeName.end()) {
PyErr_SetString(PyExc_ValueError, "Invalid element type");
return nullptr;
}
SMDSAbs_ElementType elemType = it->second;
std::set<int> ids;
SMDS_ElemIteratorPtr aElemIter =
getFemMeshPtr()->getSMesh()->GetMeshDS()->elementsIterator(elemType);
while (aElemIter->more()) {
const SMDS_MeshElement* aElem = aElemIter->next();
ids.insert(aElem->GetID());
}
Py::Tuple tuple(ids.size());
int index = 0;
for (int it : ids) {
tuple.setItem(index++, Py::Long(it));
}
return Py::new_reference_to(tuple);
}
// ===== Attributes ============================================================
Py::Dict FemMeshPy::getNodes() const
{
// int count = getFemMeshPtr()->getSMesh()->GetMeshDS()->NbNodes();
// Py::Tuple tup(count);
Py::Dict dict;
// get the actual transform of the FemMesh
Base::Matrix4D Mtrx = getFemMeshPtr()->getTransform();
SMDS_NodeIteratorPtr aNodeIter = getFemMeshPtr()->getSMesh()->GetMeshDS()->nodesIterator();
while (aNodeIter->more()) {
const SMDS_MeshNode* aNode = aNodeIter->next();
Base::Vector3d vec(aNode->X(), aNode->Y(), aNode->Z());
// Apply the matrix to hold the BoundBox in absolute space.
vec = Mtrx * vec;
int id = aNode->GetID();
dict[Py::Long(id)] = Py::asObject(new Base::VectorPy(vec));
}
return dict;
}
Py::Long FemMeshPy::getNodeCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbNodes());
}
Py::Tuple FemMeshPy::getEdges() const
{
std::set<int> ids;
SMDS_EdgeIteratorPtr aEdgeIter = getFemMeshPtr()->getSMesh()->GetMeshDS()->edgesIterator();
while (aEdgeIter->more()) {
const SMDS_MeshEdge* aEdge = aEdgeIter->next();
ids.insert(aEdge->GetID());
}
Py::Tuple tuple(ids.size());
int index = 0;
for (int it : ids) {
tuple.setItem(index++, Py::Long(it));
}
return tuple;
}
Py::Tuple FemMeshPy::getEdgesOnly() const
{
std::set<int> resultSet = getFemMeshPtr()->getEdgesOnly();
Py::Tuple tuple(resultSet.size());
int index = 0;
for (int it : resultSet) {
tuple.setItem(index++, Py::Long(it));
}
return tuple;
}
Py::Long FemMeshPy::getEdgeCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbEdges());
}
Py::Tuple FemMeshPy::getFaces() const
{
std::set<int> ids;
SMDS_FaceIteratorPtr aFaceIter = getFemMeshPtr()->getSMesh()->GetMeshDS()->facesIterator();
while (aFaceIter->more()) {
const SMDS_MeshFace* aFace = aFaceIter->next();
ids.insert(aFace->GetID());
}
Py::Tuple tuple(ids.size());
int index = 0;
for (int it : ids) {
tuple.setItem(index++, Py::Long(it));
}
return tuple;
}
Py::Tuple FemMeshPy::getFacesOnly() const
{
std::set<int> resultSet = getFemMeshPtr()->getFacesOnly();
Py::Tuple tuple(resultSet.size());
int index = 0;
for (int it : resultSet) {
tuple.setItem(index++, Py::Long(it));
}
return tuple;
}
Py::Long FemMeshPy::getFaceCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbFaces());
}
Py::Long FemMeshPy::getTriangleCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbTriangles());
}
Py::Long FemMeshPy::getQuadrangleCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbQuadrangles());
}
Py::Long FemMeshPy::getPolygonCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbPolygons());
}
Py::Tuple FemMeshPy::getVolumes() const
{
std::set<int> ids;
SMDS_VolumeIteratorPtr aVolIter = getFemMeshPtr()->getSMesh()->GetMeshDS()->volumesIterator();
while (aVolIter->more()) {
const SMDS_MeshVolume* aVol = aVolIter->next();
ids.insert(aVol->GetID());
}
Py::Tuple tuple(ids.size());
int index = 0;
for (int it : ids) {
tuple.setItem(index++, Py::Long(it));
}
return tuple;
}
Py::Long FemMeshPy::getVolumeCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbVolumes());
}
Py::Long FemMeshPy::getTetraCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbTetras());
}
Py::Long FemMeshPy::getHexaCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbHexas());
}
Py::Long FemMeshPy::getPyramidCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbPyramids());
}
Py::Long FemMeshPy::getPrismCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbPrisms());
}
Py::Long FemMeshPy::getPolyhedronCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbPolyhedrons());
}
Py::Long FemMeshPy::getSubMeshCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbSubMesh());
}
Py::Long FemMeshPy::getGroupCount() const
{
return Py::Long(getFemMeshPtr()->getSMesh()->NbGroup());
}
Py::Tuple FemMeshPy::getGroups() const
{
std::list<int> groupIDs = getFemMeshPtr()->getSMesh()->GetGroupIds();
Py::Tuple tuple(groupIDs.size());
int index = 0;
for (int it : groupIDs) {
tuple.setItem(index++, Py::Long(it));
}
return tuple;
}
Py::Object FemMeshPy::getVolume() const
{
return Py::asObject(new Base::QuantityPy(new Base::Quantity(getFemMeshPtr()->getVolume())));
}
// ===== custom attributes ============================================================
PyObject* FemMeshPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}
int FemMeshPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}