Call FrontTrack via its python interface

This commit is contained in:
jfa 2021-12-23 13:02:29 +03:00
parent 61b08a6b20
commit 890b75c52e
4 changed files with 77 additions and 2083 deletions

File diff suppressed because it is too large Load Diff

View File

@ -53,29 +53,14 @@
#include <vector>
#include <string>
#include <list>
#include <map>
#include <iostream>
#include <fstream>
#include <TopoDS_Shape.hxx>
#include <Bnd_Box.hxx>
#include <NCollection_DataMap.hxx>
#include <TColStd_DataMapOfIntegerInteger.hxx>
#if defined WIN32
#pragma warning ( disable: 4251 )
#endif
namespace MEDCoupling {
class DataArrayDouble;
}
namespace XAO {
class Xao;
class Group;
class BrepGeometry;
}
namespace SMESHHOMARDImpl
{
@ -487,240 +472,6 @@ private:
std::list<std::string> _ListFieldInterpTSR;
};
// HOMARD/FrontTrack
class FrontTrack
{
public:
/*!
* \brief Relocate nodes to lie on geometry
* \param [in] theInputMedFile - a MED file holding a mesh including nodes that will be
* moved onto the geometry
* \param [in] theOutputMedFile - a MED file to create, that will hold a modified mesh
* \param [in] theInputNodeFiles - an array of names of files describing groups of nodes that
* will be moved onto the geometry
* \param [in] theXaoFileName - a path to a file in XAO format holding the geometry and
* the geometrical groups.
* \param [in] theIsParallel - if \c true, all processors are used to treat boundary shapes
* in parallel.
*/
void track( const std::string& theInputMedFile,
const std::string& theOutputMedFile,
const std::vector< std::string > & theInputNodeFiles,
const std::string& theXaoFileName,
bool theIsParallel=true);
};
struct FT_RealProjector;
/*!
* \brief Projector of a point to a boundary shape. Wrapper of a real projection algo
*/
class FT_Projector
{
public:
FT_Projector(const TopoDS_Shape& shape = TopoDS_Shape());
FT_Projector(const FT_Projector& other);
~FT_Projector();
// initialize with a boundary shape, compute the bounding box
void setBoundaryShape(const TopoDS_Shape& shape);
// return the boundary shape
const TopoDS_Shape& getShape() const { return _shape; }
// return the bounding box
const Bnd_Box getBoundingBox() const { return _bndBox; }
// create a real projector
void prepareForProjection();
// return true if a previously found solution can be used to speed up the projection
bool canUsePrevSolution() const;
// return true if projection is not needed
bool isPlanarBoundary() const;
// switch a mode of usage of prevSolution.
// If projection fails, to try to project without usage of prevSolution.
// By default this mode is off
void tryWithoutPrevSolution( bool toTry ) { _tryWOPrevSolution = toTry; }
// project a point to the boundary shape
bool project( const gp_Pnt& point,
const double maxDist2,
gp_Pnt& projection,
double* newSolution,
const double* prevSolution = 0);
// project a point to the boundary shape and check if the projection is within the shape boundary
bool projectAndClassify( const gp_Pnt& point,
const double maxDist2,
gp_Pnt& projection,
double* newSolution,
const double* prevSolution = 0);
// check if a point lies on the boundary shape
bool isOnShape( const gp_Pnt& point,
const double tol2,
double* newSolution,
const double* prevSolution = 0);
private:
FT_RealProjector* _realProjector;
Bnd_Box _bndBox;
TopoDS_Shape _shape;
bool _tryWOPrevSolution;
};
namespace FT_Utils
{
// Check if a file exists
bool fileExists( const std::string& path );
// Check if a file can be created/overwritten
bool canWrite( const std::string& path );
// Transform anything printable to a string
template< typename T> std::string toStr( const T& t )
{
std::ostringstream s;
s << t;
return s.str();
}
//--------------------------------------------------------------------------------------------
/*!
* \brief Return projectors by group name
*/
struct XaoGroups
{
XaoGroups( const XAO::Xao* xao );
int getProjectors( const std::string& groupName,
const int dim,
const std::vector< FT_Projector > & allProjectors,
std::vector< const FT_Projector* > & groupProjectors ) const;
private:
typedef std::multimap< std::string, XAO::Group* > TGroupByNameMap;
TGroupByNameMap _xaoGroups[ 2 ]; // by dim
};
} // namespace FT_Utils
/*!
* \brief Node group and geometry to project onto
*/
class FT_NodesOnGeom
{
public:
// read node IDs form a file and try to find a boundary sub-shape by name
void read( const std::string& nodesFile,
const FT_Utils::XaoGroups& xaoGroups,
MEDCoupling::DataArrayDouble* nodeCoords,
std::vector< FT_Projector > * allProjectorsByDim);
// chose boundary shapes by evaluating distance between nodes and shapes
//void choseShape( const std::vector< FT_Utils::ShapeAndBndBox >& shapeAndBoxList );
// project nodes to the shapes and move them to new positions
void projectAndMove();
// return true if all nodes were successfully relocated
bool isOK() const { return _OK; }
// return dimension of boundary shapes
int getShapeDim() const { return _shapeDim; }
// return nb of nodes to move
int nbNodes() const { return _nodes.size(); }
private:
// put nodes in the order for optimal projection
void putNodesInOrder();
// get node coordinates
gp_Pnt getPoint( const int nodeID );
// change node coordinates
void moveNode( const int nodeID, const gp_Pnt& xyz );
// Ids of a node to move and its 2 or 4 neighbors
struct FT_NodeToMove
{
int _nodeToMove;
std::vector< int > _neighborNodes;
double _params[2]; // parameters on shape (U or UV) found by projection
double *_nearParams; // _params of a neighbor already projected node
FT_NodeToMove(): _nearParams(0) {}
};
std::vector< std::string > _groupNames;
int _shapeDim; // dimension of boundary shapes
std::vector< FT_NodeToMove > _nodes; // ids of nodes to move and their neighbors
std::vector< FT_Projector > _projectors; // FT_Projector's initialized with boundary shapes
std::vector< FT_Projector > * _allProjectors; // FT_Projector's for all shapes of _shapeDim
MEDCoupling::DataArrayDouble* _nodeCoords;
bool _OK; // projecting is successful
// map of { FT_NodeToMove::_neighborNodes[i] } to { FT_NodeToMove* }
// this map is used to find neighbor nodes
typedef NCollection_DataMap< int, std::vector< FT_NodeToMove* > > TNodeIDToLinksMap;
TNodeIDToLinksMap _neigborsMap;
std::vector<int> _nodesOrder;
};
/*!
* \brief Container of node groups.
*/
class FT_NodeGroups
{
public:
// Load node groups from files
void read( const std::vector< std::string >& nodeFiles,
const XAO::Xao* xaoGeom,
MEDCoupling::DataArrayDouble* nodeCoords );
// return number of groups of nodes to move
int nbOfGroups() const { return _nodesOnGeom.size(); }
// Move nodes of a group in parallel mode
void operator() ( const int groupIndex ) const
{
const_cast< FT_NodeGroups* >( this )->projectAndMove( groupIndex );
}
// Project and move nodes of a given group of nodes
void projectAndMove( const int groupIndex );
// return true if all nodes were successfully relocated
bool isOK() const;
// print some statistics on node groups
void dumpStat() const;
private:
std::vector< FT_NodesOnGeom > _nodesOnGeom;
std::vector< FT_Projector > _projectors[2]; // curves and surfaces separately
};
}; // namespace SMESHHOMARDImpl
#endif

View File

@ -423,7 +423,7 @@ bool SMESHGUI_HomardAdaptDlg::PushOnApply()
if (anOutMed.isEmpty()) {
// store in working directory and with default name
QString aWorkingDir = myAdvOpt->workingDirectoryLineEdit->text().trimmed();
QFileInfo aFileInfo (QDir(aWorkingDir), "Uniform_01_R.med");
QFileInfo aFileInfo (QDir(aWorkingDir), "Uniform_R.med");
anOutMed = aFileInfo.absoluteFilePath();
// show it
myArgs->mySelectOutMedFileLineEdit->setText(anOutMed);
@ -437,7 +437,7 @@ bool SMESHGUI_HomardAdaptDlg::PushOnApply()
else {
// Set file name without path for it to be created in current directory
// (it will be iteration's dir, and it will be destroyed after)
aMeshFileOUT = "Uniform_01_R.med";
aMeshFileOUT = "Uniform_R.med";
}
myHomardGen->SetMeshFileOUT(aMeshFileOUT.c_str());
@ -561,8 +561,7 @@ void SMESHGUI_HomardAdaptDlg::selectionChanged()
myArgs->myInBrowserObject->setText(aMeshName);
// Out mesh name default value
// TODO: add some suffix? "_R" or "_UnifRefin", or "_Uniform_01_R"
myArgs->myOutMeshNameLineEdit->setText(aMeshName);
myArgs->myOutMeshNameLineEdit->setText(aMeshName + "_Uniform_R");
// Output med file default value
// Construct it from Input mesh name and working directory
@ -572,9 +571,9 @@ void SMESHGUI_HomardAdaptDlg::selectionChanged()
}
else {
QString aWorkingDir = myAdvOpt->workingDirectoryLineEdit->text().trimmed();
QFileInfo aFileInfo (QDir(aWorkingDir), aMeshName + QString("_Uniform_01_R.med"));
QFileInfo aFileInfo (QDir(aWorkingDir), aMeshName + QString("_Uniform_R.med"));
for (int ii = 1; aFileInfo.exists(); ii++) {
QString anUniqueName = QString("%1_Uniform_01_R_%2.med").arg(aMeshName).arg(ii);
QString anUniqueName = QString("%1_Uniform_R_%2.med").arg(aMeshName).arg(ii);
aFileInfo.setFile(QDir(aWorkingDir), anUniqueName);
}
myArgs->mySelectOutMedFileLineEdit->setText(aFileInfo.absoluteFilePath());
@ -601,9 +600,8 @@ void SMESHGUI_HomardAdaptDlg::SetFileName()
myArgs->mySelectInMedFileLineEdit->setText(fileName);
// Out mesh name default value
// TODO: add some suffix? "_R" or "_UnifRefin", or "_Uniform_01_R"
QString aMeshName = SMESH_HOMARD_QT_COMMUN::LireNomMaillage(fileName);
myArgs->myOutMeshNameLineEdit->setText(aMeshName);
myArgs->myOutMeshNameLineEdit->setText(aMeshName + "_Uniform_R");
// Output med file default value
// Construct it from Input med file name and path
@ -613,9 +611,9 @@ void SMESHGUI_HomardAdaptDlg::SetFileName()
if (lastdot != std::string::npos)
fname = fname.substr(0, lastdot);
QString fileNameOut = fname.c_str();
QFileInfo aFileInfo (fileNameOut + QString("_Uniform_01_R.med"));
QFileInfo aFileInfo (fileNameOut + QString("_Uniform_R.med"));
for (int ii = 1; aFileInfo.exists(); ii++) {
QString anUniqueName = QString("%1_Uniform_01_R_%2.med").arg(fileNameOut).arg(ii);
QString anUniqueName = QString("%1_Uniform_R_%2.med").arg(fileNameOut).arg(ii);
aFileInfo.setFile(anUniqueName);
}
myArgs->mySelectOutMedFileLineEdit->setText(aFileInfo.absoluteFilePath());

View File

@ -34,6 +34,10 @@
#include "SALOME_LifeCycleCORBA.hxx"
#include "SALOMEconfig.h"
// Have to be included before std headers
#include <Python.h>
#include <structmember.h>
#include <vector>
#include <cmath>
#include <cstdlib>
@ -453,7 +457,7 @@ SMESHHOMARD::extrema* HOMARD_Cas_i::GetBoundingBox()
std::vector<double> LesExtremes = myHomardCas->GetBoundingBox();
ASSERT(LesExtremes.size() == 10);
aResult->length(10);
for (int i = 0; i < (int)LesExtremes.size(); i++) {
for (unsigned int i = 0; i < LesExtremes.size(); i++) {
aResult[i] = LesExtremes[i];
}
return aResult._retn();
@ -470,7 +474,7 @@ void HOMARD_Cas_i::SetGroups(const SMESHHOMARD::ListGroupType& ListGroup)
{
ASSERT(myHomardCas);
std::list<std::string> ListString;
for (int i = 0; i < ListGroup.length(); i++)
for (unsigned int i = 0; i < ListGroup.length(); i++)
{
ListString.push_back(std::string(ListGroup[i]));
}
@ -957,6 +961,7 @@ HOMARD_Gen_i::HOMARD_Gen_i() : SALOME::GenericObj_i(SMESH_Gen_i::GetPOA()),
//=============================================================================
HOMARD_Gen_i::~HOMARD_Gen_i()
{
MESSAGE ("HOMARD_Gen_i::~HOMARD_Gen_i()");
if (!myCase->_is_nil()) {
CleanCase();
}
@ -1005,7 +1010,7 @@ CORBA::Long HOMARD_Gen_i::DeleteIteration(int numIter)
MESSAGE ("DeleteIteration : numIter = " << numIter);
if (numIter == 0) {
if (!CORBA::is_nil(myIteration1)) DeleteIteration(1);
if (CORBA::is_nil(myIteration1))
myIteration0 = SMESHHOMARD::HOMARD_Iteration::_nil();
}
else {
@ -1088,18 +1093,28 @@ void HOMARD_Gen_i::AssociateCaseIter(int numIter, const char* labelIter)
throw SALOME::SALOME_Exception(es);
}
SMESHHOMARD::HOMARD_Iteration_var myIteration;
if (numIter == 0) myIteration = myIteration0;
else myIteration = myIteration1;
if (CORBA::is_nil(myIteration)) {
if (numIter == 0) {
if (CORBA::is_nil(myIteration0)) {
SALOME::ExceptionStruct es;
es.type = SALOME::BAD_PARAM;
es.text = "Invalid iteration";
throw SALOME::SALOME_Exception(es);
}
myCase->AddIteration(myIteration->GetName());
myIteration->SetCaseName("Case_1");
myCase->AddIteration(myIteration0->GetName());
myIteration0->SetCaseName("Case_1");
}
else {
if (CORBA::is_nil(myIteration1)) {
SALOME::ExceptionStruct es;
es.type = SALOME::BAD_PARAM;
es.text = "Invalid iteration";
throw SALOME::SALOME_Exception(es);
}
myCase->AddIteration(myIteration1->GetName());
myIteration1->SetCaseName("Case_1");
}
}
//=============================================================================
@ -1261,7 +1276,7 @@ SMESHHOMARD::HOMARD_Cas_ptr HOMARD_Gen_i::CreateCaseOnMesh (const char* MeshName
SMESHHOMARD::extrema_var aSeq = new SMESHHOMARD::extrema();
if (LesExtremes.size() != 10) { return 0; }
aSeq->length(10);
for (int i = 0; i < LesExtremes.size(); i++)
for (unsigned int i = 0; i < LesExtremes.size(); i++)
aSeq[i] = LesExtremes[i];
myCase->SetBoundingBox(aSeq);
// Les groupes
@ -1343,7 +1358,7 @@ SMESHHOMARD::HOMARD_Cas_ptr HOMARD_Gen_i::CreateCase(const char* MeshName,
SMESHHOMARD::extrema_var aSeq = new SMESHHOMARD::extrema();
if (LesExtremes.size() != 10) { return 0; }
aSeq->length(10);
for (int i = 0; i < LesExtremes.size(); i++)
for (unsigned int i = 0; i < LesExtremes.size(); i++)
aSeq[i] = LesExtremes[i];
myCase->SetBoundingBox(aSeq);
// Les groupes
@ -1857,11 +1872,12 @@ void HOMARD_Gen_i::CleanCase()
}
// Delete all boundaries
std::map<std::string, SMESHHOMARD::HOMARD_Boundary_var>::const_iterator it_boundary;
for (it_boundary = _mesBoundarys.begin();
it_boundary != _mesBoundarys.end(); ++it_boundary) {
DeleteBoundary((*it_boundary).first.c_str());
}
//std::map<std::string, SMESHHOMARD::HOMARD_Boundary_var>::const_iterator it_boundary;
//for (it_boundary = _mesBoundarys.begin();
// it_boundary != _mesBoundarys.end(); ++it_boundary) {
// DeleteBoundary((*it_boundary).first.c_str());
//}
_mesBoundarys.clear();
// Delete iteration
DeleteIteration(1);
@ -1877,6 +1893,7 @@ void HOMARD_Gen_i::CleanCase()
if (!_CaseOnMedFile && !_TmpMeshFile.empty()) {
SMESH_File aFile (_TmpMeshFile, false);
if (aFile.exists()) aFile.remove();
_TmpMeshFile = "";
}
_SmeshMesh = SMESH::SMESH_Mesh::_nil();
}
@ -1904,14 +1921,7 @@ CORBA::Long HOMARD_Gen_i::ComputeAdap(SMESHHOMARD::HOMARD_Cas_var myCase,
ASSERT(!CORBA::is_nil(myHypothesis));
// B. L'iteration parent
//const char* nomIterationParent = myIteration->GetIterParentName();
SMESHHOMARD::HOMARD_Iteration_var myIterationParent = myIteration0;
ASSERT(!CORBA::is_nil(myIterationParent));
// Si l'iteration parent n'est pas calculee, on le fait (recursivite amont)
//if (myIterationParent->GetState() == 1) {
// int codret = Compute(nomIterationParent);
// if (codret != 0) VERIFICATION("Pb au calcul de l'iteration precedente" == 0);
//}
ASSERT(!CORBA::is_nil(myIteration0));
// C. Le sous-répertoire de l'iteration precedente
char* DirComputePa = ComputeDirPaManagement(myCase, myIteration);
@ -1923,9 +1933,9 @@ CORBA::Long HOMARD_Gen_i::ComputeAdap(SMESHHOMARD::HOMARD_Cas_var myCase,
MESSAGE (". ConfType = " << ConfType);
// D.3. Le maillage de depart
const char* NomMeshParent = myIterationParent->GetMeshName();
const char* NomMeshParent = myIteration0->GetMeshName();
MESSAGE (". NomMeshParent = " << NomMeshParent);
const char* MeshFileParent = myIterationParent->GetMeshFile();
const char* MeshFileParent = myIteration0->GetMeshFile();
MESSAGE (". MeshFileParent = " << MeshFileParent);
// D.4. Le maillage associe a l'iteration
@ -2072,10 +2082,28 @@ CORBA::Long HOMARD_Gen_i::ComputeCAO(SMESHHOMARD::HOMARD_Cas_var myCase,
// C. Lancement des projections
MESSAGE (". Lancement des projections");
// TODO?
SMESHHOMARDImpl::FrontTrack* myFrontTrack = new SMESHHOMARDImpl::FrontTrack();
myFrontTrack->track(theInputMedFile, theOutputMedFile,
theInputNodeFiles, theXaoFileName, theIsParallel);
assert(Py_IsInitialized());
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
PyRun_SimpleString("from FrontTrack import FrontTrack");
// FrontTrack().track( fic_med_brut, fic_med_new, l_fr, xao_file )
std::string pyCommand ("FrontTrack().track( \"");
pyCommand += theInputMedFile + "\", \"" + theOutputMedFile + "\", [";
for (int i = 0; i < icpt; i++) {
if (i > 0) pyCommand += ", ";
pyCommand += "\"";
pyCommand += theInputNodeFiles[i];
pyCommand += "\"";
}
pyCommand += "], \"" + theXaoFileName + "\", False )";
MESSAGE (". Lancement des projections: pyCommand = " << pyCommand);
PyRun_SimpleString(pyCommand.c_str());
PyGILState_Release(gstate);
//SMESHHOMARDImpl::FrontTrack* myFrontTrack = new SMESHHOMARDImpl::FrontTrack();
//myFrontTrack->track(theInputMedFile, theOutputMedFile,
// theInputNodeFiles, theXaoFileName, theIsParallel);
// D. Transfert des coordonnées modifiées dans le fichier historique de HOMARD
// On lance une exécution spéciale de HOMARD en attendant
@ -2367,7 +2395,8 @@ char* HOMARD_Gen_i::ComputeDirManagement(SMESHHOMARD::HOMARD_Cas_var myCase,
//=============================================================================
// Calcul d'une iteration : gestion du répertoire de calcul de l'iteration parent
//=============================================================================
char* HOMARD_Gen_i::ComputeDirPaManagement(SMESHHOMARD::HOMARD_Cas_var myCase, SMESHHOMARD::HOMARD_Iteration_var myIteration)
char* HOMARD_Gen_i::ComputeDirPaManagement(SMESHHOMARD::HOMARD_Cas_var myCase,
SMESHHOMARD::HOMARD_Iteration_var myIteration)
{
MESSAGE ("ComputeDirPaManagement : répertoires pour le calcul");
// Le répertoire du cas
@ -2376,8 +2405,7 @@ char* HOMARD_Gen_i::ComputeDirPaManagement(SMESHHOMARD::HOMARD_Cas_var myCase, S
// Le sous-répertoire de l'iteration precedente
SMESHHOMARD::HOMARD_Iteration_var myIterationParent = myIteration0;
const char* nomDirItPa = myIterationParent->GetDirNameLoc();
const char* nomDirItPa = myIteration0->GetDirNameLoc();
std::stringstream DirComputePa;
DirComputePa << nomDirCase << "/" << nomDirItPa;
MESSAGE(". nomDirItPa = " << nomDirItPa);
@ -2671,6 +2699,8 @@ void HOMARD_Gen_i::PythonDump()
for (it_boundary = _mesBoundarys.begin();
it_boundary != _mesBoundarys.end(); ++it_boundary) {
SMESHHOMARD::HOMARD_Boundary_var maBoundary = (*it_boundary).second;
//MESSAGE ("PythonDump of boundary " << (*it_boundary).first <<
// " : " << maBoundary->GetDumpPython());
pd << maBoundary->GetDumpPython();
}