#include "Utils_CorbaException.hxx"
#include "utilities.h"
+#include "MEDMEM_EnsightMeshDriver.hxx"
#include <string>
#include <deque>
#include <map>
#include <TCollection_AsciiString.hxx>
#include <TColStd_SequenceOfAsciiString.hxx>
#include <HDFascii.hxx>
-#include "SALOMEDS_Tool.hxx"
using namespace std;
- Filter_Gen_i* Filter_Gen_i::_FILTERGen = NULL;
+using namespace SALOME_FILTER;
+Filter_Gen_i* Filter_Gen_i::_FILTERGen = NULL;
//=============================================================================
/*!
PortableServer::ObjectId * contId,
const char *instanceName,
const char *interfaceName) :
- Engines_Component_i(orb, poa, contId, instanceName, interfaceName)
+ Engines_Component_i(orb, poa, contId, instanceName, interfaceName),_med(NULL),_newMed(NULL),_mesh(NULL),_newMesh(NULL),_myGradient(NULL),_myDField(NULL),_myIField(NULL),_criteria(NULL),_map(NULL)
{
MESSAGE("activate object");
_thisObj = this ;
ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
_NS->init_orb( _orb ) ;
- //_myFilterI = 0;
_FILTERGen = this;
}
Filter_Gen_i::~Filter_Gen_i()
{
MESSAGE("Filter_Gen_i::~Filter_Gen_i");
+
+ // destruction of gradient field
+ if(_myGradient)
+ delete _myGradient;
+
+ // destruction of support of reference field: reference field is destroyed
+ // by destruction of med object
+ if(_myIField)
+ delete _myIField->getSupport();
+ if(_myDField)
+ delete _myDField->getSupport();
+
+ // destruction of criteria: support and field
+ if(_criteria){
+ delete _criteria->getSupport();
+ delete _criteria;
+ }
+
+ if(_map)
+ delete [] _map;
+ if(_med)
+ delete _med;
+ if(_newMed)
+ delete _newMed;
+}
+
+void Filter_Gen_i::loadMED(const char* inMedFile)
+{
+ SCRUTE(inMedFile);
+ _file = inMedFile;
+ _med = new ::MED(MED_DRIVER,_file);
+}
+
+void Filter_Gen_i::unloadMED()
+{
+ MESSAGE("unloadMED called");
+ // destruction of gradient field
+ if(_myGradient){
+ delete _myGradient;
+ _myGradient=NULL;
+ }
+
+ // destruction of support of reference field: reference field is destroyed
+ // by destruction of med object
+ if(_myIField){
+ delete _myIField->getSupport();
+ _myIField=NULL;
+ }
+ if(_myDField){
+ delete _myDField->getSupport();
+ _myDField=NULL;
+ }
+
+ // destruction of criteria: support and field
+ if(_criteria){
+ delete _criteria->getSupport();
+ delete _criteria;
+ _criteria=NULL;
+ }
+
+ if(_med){
+ delete _med;
+ _med=NULL;
+ }
+}
+
+StrSeq* Filter_Gen_i::getMeshNames()
+{
+ StrSeq *seq = new StrSeq();
+ deque<string> deq = _med->getMeshNames();
+ seq->length(deq.size());
+ for(int i=0;i<deq.size();i++)
+ (*seq)[i] = deq[i].c_str();
+ return seq;
+}
+
+StrSeq * Filter_Gen_i::getFieldNames()
+{
+ StrSeq *seq = new StrSeq();
+ deque<string> deq = _med->getFieldNames();
+ seq->length(deq.size());
+ for(int i=0;i<deq.size();i++)
+ (*seq)[i] = deq[i].c_str();
+ return seq;
+}
+
+CORBA::Long Filter_Gen_i::getMeshDimension(const char* meshName)
+{
+ return _med->getMesh(meshName)->getMeshDimension();
+}
+
+CORBA::Long Filter_Gen_i::getFieldEntity(const char* fieldName,CORBA::Long dt,CORBA::Long it)
+{
+ return _med->getField(fieldName,dt,it)->getSupport()->getEntity();
+}
+
+CORBA::Boolean Filter_Gen_i::fieldIsOnAllElements(const char* fieldName,CORBA::Long dt,CORBA::Long it)
+{
+ return _med->getField(fieldName,dt,it)->getSupport()->isOnAllElements();
+}
+
+DTITSeq* Filter_Gen_i::getFieldIteration(const char* fieldName)
+{
+ DTITSeq *seq = new DTITSeq();
+ deque<DT_IT_> deq = _med->getFieldIteration(fieldName);
+ seq->length(deq.size());
+ for(int i=0;i<deq.size();i++){
+ (*seq)[i].dt = deq[i].dt;
+ (*seq)[i].it = deq[i].it;
+ }
+ return seq;
+}
+
+char* Filter_Gen_i::getMeshName(const char* fieldName,CORBA::Long dt,CORBA::Long it)
+{
+ return (char*)(_med->getField(fieldName,dt,it)->getSupport()->getMesh()->getName().c_str());
+}
+
+void Filter_Gen_i::readReferenceField(const char* meshName, const char* fieldName, CORBA::Long ts)
+{
+ // read of input mesh
+ _mesh = _med->getMesh(meshName);
+ _mesh->read();
+
+ // read of input field
+ deque<DT_IT_> myIteration = _med->getFieldIteration (fieldName);
+ MEDMEM::FIELD_* field = _med->getField(fieldName,myIteration[ts].dt,myIteration[ts].it);
+ if (dynamic_cast<MEDMEM::FIELD<double>*>(field)){
+ _myDField = (MEDMEM::FIELD<double>*)field;
+ _myDField->read();
+ _myIField = NULL;
+ }
+ else{
+ _myIField = (MEDMEM::FIELD<int>*)field;
+ _myIField->read();
+ _myDField = NULL;
+ }
+}
+
+void Filter_Gen_i::buildGradient() throw(SALOME_FILTER::FILTER_Gen::FilterError)
+{
+ if(!_myGradient){
+ FIELD<double> * gradient;
+ try{
+ if(_myDField)
+ gradient = _myDField->buildGradient();
+ else
+ gradient = _myIField->buildGradient();
+ _myGradient = gradient->buildNorm2Field();
+ delete gradient;
+ }
+ catch(MEDEXCEPTION& Mex){
+ MESSAGE("SALOME_Exception: Can't calculate gradient");
+ throw SALOME_FILTER::FILTER_Gen::FilterError("Can't calculate gradient");
+ }
+ }
+}
+
+void Filter_Gen_i::getMinMax(CORBA::Double& imin, CORBA::Double& imax,ref_func rf)
+{
+ double min, max;
+
+ switch(rf){
+ case F_FIELD:
+ if (_myDField)
+ _myDField->getMinMax(min,max);
+ else{
+ int xmin, xmax;
+ _myIField->getMinMax(xmin,xmax);
+ min = (double)xmin;
+ max = (double)xmax;
+ }
+ break;
+ case F_GRAD:
+ _myGradient->getMinMax(min,max);
+ break;
+ }
+ imin = min;
+ imax = max;
+}
+
+LongSeq* Filter_Gen_i::getHistogram(CORBA::Long size,ref_func rf)
+{
+ int mysize = size;
+ vector<int> myh;
+
+ switch(rf){
+ case F_FIELD:
+ if (_myDField)
+ myh = _myDField->getHistogram(mysize);
+ else
+ myh = _myIField->getHistogram(mysize);
+ break;
+ case F_GRAD:
+ myh = _myGradient->getHistogram(mysize);
+ break;
+ }
+
+ LongSeq *seq = new LongSeq();
+ seq->length(myh.size());
+ for(int i=0;i<myh.size();i++)
+ (*seq)[i] = myh[i];
+ return seq;
+}
+
+void Filter_Gen_i::generateCriteria(CORBA::Long nbthresh,CORBA::Double fthresh,CORBA::Double sthresh,CORBA::Boolean areaFlag,ref_func rf) throw(SALOME_FILTER::FILTER_Gen::FilterError)
+{
+ double val, min, max;
+ bool isGVal;
+ MED_EN::medEntityMesh typ;
+
+ try{
+ if(_myDField)
+ typ = _myDField->getSupport()->getEntity();
+ else
+ typ = _myIField->getSupport()->getEntity();
+
+ // create support on nodes
+ SUPPORT *sup = new SUPPORT(_mesh,"Support",MED_NODE);
+
+ // create integer field on nodes
+ _criteria = new FIELD<int>(sup,1);
+
+ _criteria->setName("Criteria");
+
+ // read number of nodes
+ int NumberOf = sup->getNumberOfElements(MED_ALL_ELEMENTS);
+
+ for (int i=1; i<NumberOf+1; i++){
+
+ // if reference field is on elements get reference field on nodes
+ switch(typ){
+ case MED_CELL:
+ throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on cells");
+ break;
+ case MED_FACE:
+ throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on faces");
+ break;
+ case MED_EDGE:
+ throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on edges");
+ break;
+ case MED_NODE:
+ // read reference field value
+ switch(rf){
+ case F_FIELD:
+ if(_myDField)
+ val = _myDField->getValueIJ(i,1);
+ else
+ val = (double)_myIField->getValueIJ(i,1);
+ break;
+ case F_GRAD:
+ val = _myGradient->getValueIJ(i,1);
+ break;
+ }
+ break;
+ case MED_ALL_ENTITIES:
+ throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on all entities");
+ break;
+ }
+
+ // set criteria field value
+ if( nbthresh == 1 ){
+ if( areaFlag )
+ if( val >= fthresh ) isGVal = true;
+ else isGVal = false;
+ else
+ if( val <= fthresh ) isGVal = true;
+ else isGVal = false;
+ }
+ else{
+ min = fthresh;
+ max = sthresh;
+ if(sthresh < fthresh){
+ min = sthresh;
+ max = fthresh;
+ }
+ if( areaFlag )
+ if( (val <= min) || (val >= max) ) isGVal = true;
+ else isGVal = false;
+ else
+ if( (val >= min) && (val <= max) ) isGVal = true;
+ else isGVal = false;
+ }
+ if( isGVal )
+ _criteria->setValueIJ(i,1,1);
+ else
+ _criteria->setValueIJ(i,1,0);
+ }
+ }
+ catch(SALOME_Exception& ex){
+ throw SALOME_FILTER::FILTER_Gen::FilterError(ex.what());
+ }
+}
+
+void Filter_Gen_i::createEnsightInputFiles() throw(SALOME_FILTER::FILTER_Gen::FilterError)
+{
+ try{
+ // call ensight driver MED to generate input ensight mesh ,
+ // input ensight boundary mesh and input criteria ensight field for filtoo
+ MESSAGE("Create ensight mesh");
+ ENSIGHT_MESH_WRONLY_DRIVER myMeshDriver("/tmp/input.case",_mesh);
+ myMeshDriver.open();
+ myMeshDriver.write();
+ myMeshDriver.close();
+
+ MESSAGE("Create ensight field");
+ ENSIGHT_FIELD_WRONLY_DRIVER<int> myFieldDriver("/tmp/input.case",_criteria);
+ myFieldDriver.open();
+ myFieldDriver.write();
+ myFieldDriver.close();
+ }
+ catch(SALOME_Exception& ex){
+ throw SALOME_FILTER::FILTER_Gen::FilterError(ex.what());
+ }
+}
+
+void Filter_Gen_i::filtering() throw(SALOME_FILTER::FILTER_Gen::FilterError)
+{
+ string command;
+
+ MESSAGE("call filtoo");
+ // send filtoo command
+ command = "cd /tmp;filtoo -s -m 1 -f input -o output > /tmp/filter.log";
+ MESSAGE(command);
+ int status = system(command.c_str());
+ if(status != 0)
+ throw SALOME_FILTER::FILTER_Gen::FilterError("filtoo error");
+
+ // destroy filtoo input files
+ command = "cd /tmp;rm -f input.*";
+ MESSAGE(command);
+ system(command.c_str());
+
+}
+
+void Filter_Gen_i::projectFieldsOnDecimateMesh() throw(SALOME_FILTER::FILTER_Gen::FilterError)
+{
+ string command;
+
+ // read of new mesh in ensight file
+ MESH* myMesh = new MESH();
+ ENSIGHT_MESH_RDONLY_DRIVER myEnsightMeshDriver("/tmp/output.case", myMesh) ;
+ myMesh->addDriver(ENSIGHT_DRIVER,"/tmp/output.case","myMesh",MED_EN::MED_LECT);
+ myMesh->read() ;
+
+ // have to call ensight driver MED to generate output MED file from filtoo output
+ _newMed = new ::MED();
+ _newMed->addMesh(myMesh);
+
+ // get new mesh name
+ deque<string> meshesNames = _newMed->getMeshNames();
+ int numberOfMeshes = meshesNames.size();
+ if( numberOfMeshes != 1)
+ throw SALOME_FILTER::FILTER_Gen::FilterError("Unvalid number of meshes in filtoo output");
+
+ // new mesh generated by filtoo
+ _newMesh = _newMed->getMesh(meshesNames[0]);
+
+ // create support on nodes on all new mesh
+ SUPPORT *newSup = new SUPPORT(_newMesh,"Support",MED_NODE);
+
+ // read the id of nodes of output mesh, in input mesh
+ readMapping();
+
+ // read connectivity of new mesh to get neighbour node of created node
+ _connL = _newMesh->getConnectivityLength(MED_FULL_INTERLACE,MED_NODAL,MED_CELL,MED_ALL_ELEMENTS);
+ _conn = _newMesh->getConnectivity(MED_FULL_INTERLACE,MED_NODAL,MED_CELL,MED_ALL_ELEMENTS);
+ _connI = _newMesh->getConnectivityIndex(MED_NODAL,MED_CELL);
+
+ // read number of nodes on new mesh
+ int numberOfNodes = newSup->getNumberOfElements(MED_ALL_ELEMENTS);
+ int numberOfComponents;
+
+ deque<string> fieldsNames = _med->getFieldNames();
+ int numberOfFields = fieldsNames.size();
+
+ try{
+
+ // loop on fields
+ for (int i=0; i<numberOfFields; i++){
+
+ // is the input field the reference field?
+ bool isReferenceField= false;
+ if(_myDField){
+ if( strcmp(_myDField->getName().c_str(),fieldsNames[i].c_str()) == 0)
+ isReferenceField = true;
+ }
+ else
+ if( strcmp(_myIField->getName().c_str(),fieldsNames[i].c_str()) == 0)
+ isReferenceField = true;
+
+ deque<DT_IT_> myIteration = _med->getFieldIteration (fieldsNames[i]);
+ string meshName = _med->getField(fieldsNames[i],myIteration[0].dt,myIteration[0].it)->getSupport()->getMesh()->getName();
+
+ // we process only fields on input mesh
+ if( strcmp(meshName.c_str(),_mesh->getName().c_str()) == 0){
+
+ // loop on time steps
+ int numberOfIteration = myIteration.size();
+ for(int j=0;j<numberOfIteration;j++){
+
+ // select input field
+ MEDMEM::FIELD_* field = _med->getField(fieldsNames[i],myIteration[j].dt,myIteration[j].it);
+
+ // if field not on nodes, take following field
+ if( field->getSupport()->getEntity() != MED_NODE )
+ break;
+
+ FIELD<double> *myDField = NULL;
+ FIELD<double> *newDField = NULL;
+ FIELD<int> *myIField = NULL;
+ FIELD<int> *newIField = NULL;
+
+ if (dynamic_cast<MEDMEM::FIELD<double>*>(field)){
+ if(!isReferenceField){
+ // read input field on input file
+ myDField = new FIELD<double>(MEDMEM::MED_DRIVER,_file,fieldsNames[i],myIteration[j].dt,myIteration[j].it);
+ }
+ else{
+ myDField = _myDField;
+ }
+ // create new output field
+ newDField = new FIELD<double>(newSup,field->getNumberOfComponents());
+ newDField->setName(myDField->getName());
+ newDField->setIterationNumber(myIteration[j].dt);
+ newDField->setOrderNumber(myIteration[j].it);
+ newDField->setTime(myDField->getTime());
+ }
+ else{
+ if(!isReferenceField)
+ // read input field on input file
+ myIField = new FIELD<int>(MEDMEM::MED_DRIVER,_file,fieldsNames[i],myIteration[j].dt,myIteration[j].it);
+ else
+ myIField = _myIField;
+ // create new output field
+ newIField = new FIELD<int>(newSup,field->getNumberOfComponents());
+ newIField->setName(myIField->getName());
+ newIField->setIterationNumber(myIteration[j].dt);
+ newIField->setOrderNumber(myIteration[j].it);
+ newIField->setTime(myIField->getTime());
+ }
+ numberOfComponents = field->getNumberOfComponents();
+
+ // loop on nodes on new field
+ for (int k=1; k<=numberOfNodes; k++){
+ // read number of nodes on input field
+ int l = getNodeNumber(k);
+ double dval;
+ int ival;
+
+ for(int c=1;c<=numberOfComponents;c++){
+ // read value on input field
+ if(myDField)
+ dval = myDField->getValueIJ(l,c);
+ else
+ ival = myIField->getValueIJ(l,c);
+
+ // write value on new field
+ if(newDField){
+ newDField->setValueIJ(k,c,dval);
+ }
+ else
+ newIField->setValueIJ(k,c,ival);
+ }
+
+ }
+ if(newDField)
+ _newMed->addField(newDField);
+ else
+ _newMed->addField(newIField);
+
+ // Destroy input field if not reference field
+ if(!isReferenceField)
+ if(myDField){
+ delete myDField->getSupport();
+ delete myDField;
+ }
+ else{
+ delete myIField->getSupport();
+ delete myIField;
+ }
+
+ }
+ }
+ }
+ }
+ catch(SALOME_Exception){
+ throw SALOME_FILTER::FILTER_Gen::FilterError("Unvalid decimate mlesh created by filtoo");
+ }
+
+ // destroy filtoo output files
+ command = "cd /tmp;rm -f output.*";
+ MESSAGE(command);
+ system(command.c_str());
+
+}
+
+void Filter_Gen_i::readMapping()
+{
+ double tmp;
+ string firstline;
+ ifstream mapFile("/tmp/output.renum");
+
+ // read first line of file
+ getline(mapFile, firstline);
+
+ // read number of vertices to map
+ string::size_type pos = firstline.find(":");
+ istringstream iss(firstline.substr(pos+1));
+ iss >> _nbvmap;
+
+ // read each vertices in array
+ _map = new int[_nbvmap];
+
+ for(int i=0;i<_nbvmap;i++){
+ mapFile >> tmp;
+ _map[i] = (int)tmp;
+ }
+
+}
+
+int Filter_Gen_i::getNodeNumber(int num)
+{
+ int oldnum = _map[num-1];
+
+ // if new node get neighbour node
+ if(oldnum == 0)
+ oldnum = _map[getNeighbourVertex(num)-1];
+
+ return oldnum;
}
+int Filter_Gen_i::getNeighbourVertex(int num) throw(SALOME_Exception)
+{
+ int nnum;
+ int numberOfElements = _newMesh->getNumberOfElements(MED_CELL,MED_ALL_ELEMENTS);
+
+ int index;
+ // get index of created node in connectivity array
+ for(index=0;index<_connL;index++){
+ if(_conn[index] == num){
+
+ // get index of element which contain created node
+ int i;
+ for(i=1;i<=numberOfElements;i++)
+ if(_connI[i] > index)
+ break;
+
+ // search neighbour node which are in old mesh
+ for(int j=_connI[i-1];j<_connI[i];j++){
+ nnum = _conn[j-1];
+ if( _map[nnum-1] != 0)
+ break;
+ }
+
+ // if neighbour node in old mesh: go out loop, else continue
+ if(_map[nnum-1]!=0)
+ break;
+ }
+ }
+
+ // if no neighbour node in old mesh: throw exception
+ if(_map[nnum-1]==0)
+ throw SALOME_Exception("None of the neighbour node are in old mesh!!");
+
+ return nnum;
+}
+
+void Filter_Gen_i::createMedOutputFile(const char *outMedFile)
+{
+ int id;
+
+ MESSAGE("Create MED mesh: "<<outMedFile);
+ id = _newMed->addDriver(MED_DRIVER,outMedFile,MED_EN::MED_ECRI);
+ _newMed->write(id);
+}
+
+
+//=============================================================================
+/*!
+ * C factory, accessible with dlsym, after dlopen
+ */
+//=============================================================================
+
+extern "C"
+{
+ PortableServer::ObjectId * FILTEREngine_factory(
+ CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa,
+ PortableServer::ObjectId * contId,
+ const char *instanceName,
+ const char *interfaceName)
+ {
+ MESSAGE("PortableServer::ObjectId * FilterEngine_factory()");
+ SCRUTE(interfaceName);
+ Filter_Gen_i * myFilter_Gen
+ = new Filter_Gen_i(orb, poa, contId, instanceName, interfaceName);
+ return myFilter_Gen->getId() ;
+ }
+}