Salome HOME
This commit was generated by cvs2git to create tag 'V4_1_0a1'.
[modules/filter.git] / src / FILTER / Filter_Gen_i.cxx
index 34be897408e635fb890a3a347c6ed0180765bb40..175af67e05818e4105828ec10c338ecc6cf8700b 100755 (executable)
@@ -33,6 +33,7 @@
 #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;
 
 //=============================================================================
 /*!
@@ -67,7 +68,7 @@ Filter_Gen_i:: Filter_Gen_i(CORBA::ORB_ptr orb,
                                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 ;
@@ -79,7 +80,6 @@ Filter_Gen_i:: Filter_Gen_i(CORBA::ORB_ptr orb,
   ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
   _NS->init_orb( _orb ) ;
 
-  //_myFilterI = 0;
   _FILTERGen = this;
 }
 
@@ -92,5 +92,603 @@ Filter_Gen_i:: Filter_Gen_i(CORBA::ORB_ptr orb,
 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() ;
+  }
+}