1 // FILTER FILTER : implemetation of FILTER idl descriptions
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // File : Filter_Gen_i.cxx
25 // Author : Paul RASCLE, EDF
29 #include "Filter_Gen_i.hxx"
31 #include "Utils_SINGLETON.hxx"
33 #include "Utils_CorbaException.hxx"
34 #include "utilities.h"
36 #include "MEDMEM_EnsightMeshDriver.hxx"
41 #include <TCollection_AsciiString.hxx>
42 #include <TColStd_SequenceOfAsciiString.hxx>
43 #include <HDFascii.hxx>
46 using namespace SALOME_FILTER;
47 Filter_Gen_i* Filter_Gen_i::_FILTERGen = NULL;
49 //=============================================================================
51 * default constructor: not for use
53 //=============================================================================
55 Filter_Gen_i::Filter_Gen_i()
57 MESSAGE("Filter_Gen_i::Filter_Gen_i");
60 //=============================================================================
62 * standard constructor
64 //=============================================================================
66 Filter_Gen_i:: Filter_Gen_i(CORBA::ORB_ptr orb,
67 PortableServer::POA_ptr poa,
68 PortableServer::ObjectId * contId,
69 const char *instanceName,
70 const char *interfaceName) :
71 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)
73 MESSAGE("activate object");
75 _id = _poa->activate_object(_thisObj);
78 // get an NamingService interface
79 _NS = SINGLETON_<SALOME_NamingService>::Instance() ;
80 ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
81 _NS->init_orb( _orb ) ;
86 //=============================================================================
88 * default destructor: not for use
90 //=============================================================================
92 Filter_Gen_i::~Filter_Gen_i()
94 MESSAGE("Filter_Gen_i::~Filter_Gen_i");
96 // destruction of gradient field
100 // destruction of support of reference field: reference field is destroyed
101 // by destruction of med object
103 delete _myIField->getSupport();
105 delete _myDField->getSupport();
107 // destruction of criteria: support and field
109 delete _criteria->getSupport();
121 void Filter_Gen_i::loadMED(const char* inMedFile)
125 _med = new ::MED(MED_DRIVER,_file);
128 void Filter_Gen_i::unloadMED()
130 MESSAGE("unloadMED called");
131 // destruction of gradient field
137 // destruction of support of reference field: reference field is destroyed
138 // by destruction of med object
140 delete _myIField->getSupport();
144 delete _myDField->getSupport();
148 // destruction of criteria: support and field
150 delete _criteria->getSupport();
161 StrSeq* Filter_Gen_i::getMeshNames()
163 StrSeq *seq = new StrSeq();
164 deque<string> deq = _med->getMeshNames();
165 seq->length(deq.size());
166 for(int i=0;i<deq.size();i++)
167 (*seq)[i] = deq[i].c_str();
171 StrSeq * Filter_Gen_i::getFieldNames()
173 StrSeq *seq = new StrSeq();
174 deque<string> deq = _med->getFieldNames();
175 seq->length(deq.size());
176 for(int i=0;i<deq.size();i++)
177 (*seq)[i] = deq[i].c_str();
181 CORBA::Long Filter_Gen_i::getMeshDimension(const char* meshName)
183 return _med->getMesh(meshName)->getMeshDimension();
186 CORBA::Long Filter_Gen_i::getFieldEntity(const char* fieldName,CORBA::Long dt,CORBA::Long it)
188 return _med->getField(fieldName,dt,it)->getSupport()->getEntity();
191 CORBA::Boolean Filter_Gen_i::fieldIsOnAllElements(const char* fieldName,CORBA::Long dt,CORBA::Long it)
193 return _med->getField(fieldName,dt,it)->getSupport()->isOnAllElements();
196 DTITSeq* Filter_Gen_i::getFieldIteration(const char* fieldName)
198 DTITSeq *seq = new DTITSeq();
199 deque<DT_IT_> deq = _med->getFieldIteration(fieldName);
200 seq->length(deq.size());
201 for(int i=0;i<deq.size();i++){
202 (*seq)[i].dt = deq[i].dt;
203 (*seq)[i].it = deq[i].it;
208 char* Filter_Gen_i::getMeshName(const char* fieldName,CORBA::Long dt,CORBA::Long it)
210 return (char*)(_med->getField(fieldName,dt,it)->getSupport()->getMesh()->getName().c_str());
213 void Filter_Gen_i::readReferenceField(const char* meshName, const char* fieldName, CORBA::Long ts)
215 // read of input mesh
216 _mesh = _med->getMesh(meshName);
219 // read of input field
220 deque<DT_IT_> myIteration = _med->getFieldIteration (fieldName);
221 MEDMEM::FIELD_* field = _med->getField(fieldName,myIteration[ts].dt,myIteration[ts].it);
222 if (dynamic_cast<MEDMEM::FIELD<double>*>(field)){
223 _myDField = (MEDMEM::FIELD<double>*)field;
228 _myIField = (MEDMEM::FIELD<int>*)field;
234 void Filter_Gen_i::buildGradient() throw(SALOME_FILTER::FILTER_Gen::FilterError)
237 FIELD<double> * gradient;
240 gradient = _myDField->buildGradient();
242 gradient = _myIField->buildGradient();
243 _myGradient = gradient->buildNorm2Field();
246 catch(MEDEXCEPTION& Mex){
247 MESSAGE("SALOME_Exception: Can't calculate gradient");
248 throw SALOME_FILTER::FILTER_Gen::FilterError("Can't calculate gradient");
253 void Filter_Gen_i::getMinMax(CORBA::Double& imin, CORBA::Double& imax,ref_func rf)
260 _myDField->getMinMax(min,max);
263 _myIField->getMinMax(xmin,xmax);
269 _myGradient->getMinMax(min,max);
276 LongSeq* Filter_Gen_i::getHistogram(CORBA::Long size,ref_func rf)
284 myh = _myDField->getHistogram(mysize);
286 myh = _myIField->getHistogram(mysize);
289 myh = _myGradient->getHistogram(mysize);
293 LongSeq *seq = new LongSeq();
294 seq->length(myh.size());
295 for(int i=0;i<myh.size();i++)
300 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)
302 double val, min, max;
304 MED_EN::medEntityMesh typ;
307 typ = _myDField->getSupport()->getEntity();
309 typ = _myIField->getSupport()->getEntity();
311 // create support on nodes
312 SUPPORT *sup = new SUPPORT(_mesh,"Support",MED_NODE);
314 // create integer field on nodes
315 _criteria = new FIELD<int>(sup,1);
317 _criteria->setName("Criteria");
319 // read number of nodes
320 int NumberOf = sup->getNumberOfElements(MED_ALL_ELEMENTS);
322 for (int i=1; i<NumberOf+1; i++){
324 // if reference field is on elements get reference field on nodes
327 throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on cells");
330 throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on faces");
333 throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on edges");
336 // read reference field value
340 val = _myDField->getValueIJ(i,1);
342 val = (double)_myIField->getValueIJ(i,1);
345 val = _myGradient->getValueIJ(i,1);
349 case MED_ALL_ENTITIES:
350 throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on all entities");
354 // set criteria field value
357 if( val >= fthresh ) isGVal = true;
360 if( val <= fthresh ) isGVal = true;
366 if(sthresh < fthresh){
371 if( (val <= min) || (val >= max) ) isGVal = true;
374 if( (val >= min) && (val <= max) ) isGVal = true;
378 _criteria->setValueIJ(i,1,1);
380 _criteria->setValueIJ(i,1,0);
384 void Filter_Gen_i::createEnsightInputFiles()
386 MESSAGE("Calculate boundary");
387 // generate MED boundary of geometry
388 SUPPORT *supB = _mesh->getBoundaryElements(MED_FACE);
390 // call ensight driver MED to generate input ensight mesh ,
391 // input ensight boundary mesh and input criteria ensight field for filtoo
392 MESSAGE("Create ensight mesh");
393 ENSIGHT_MESH_WRONLY_DRIVER myMeshDriver("/tmp/input.case",_mesh);
394 myMeshDriver.addSupport(supB);
396 myMeshDriver.write();
397 myMeshDriver.close();
399 MESSAGE("Create ensight field");
400 ENSIGHT_FIELD_WRONLY_DRIVER<int> myFieldDriver("/tmp/input.case",_criteria);
401 myFieldDriver.open();
402 myFieldDriver.write();
403 myFieldDriver.close();
406 void Filter_Gen_i::filtering()
410 MESSAGE("call filtoo");
411 // send filtoo command
412 command = "cd /tmp;filtoo -f input -o output > /tmp/filter.log";
414 system(command.c_str());
416 // destroy filtoo input files
417 command = "cd /tmp;rm -f input.*";
419 system(command.c_str());
423 void Filter_Gen_i::projectFieldsOnDecimateMesh() throw(SALOME_FILTER::FILTER_Gen::FilterError)
427 // read of new mesh in ensight file
428 MESH* myMesh = new MESH();
429 ENSIGHT_MESH_RDONLY_DRIVER myEnsightMeshDriver("/tmp/output.case", myMesh) ;
430 myMesh->addDriver(ENSIGHT_DRIVER,"/tmp/output.case","myMesh",MED_EN::MED_LECT);
433 // have to call ensight driver MED to generate output MED file from filtoo output
434 _newMed = new ::MED();
435 _newMed->addMesh(myMesh);
438 deque<string> meshesNames = _newMed->getMeshNames();
439 int numberOfMeshes = meshesNames.size();
440 if( numberOfMeshes != 1)
441 throw SALOME_FILTER::FILTER_Gen::FilterError("Unvalid number of meshes in filtoo output");
443 // new mesh generated by filtoo
444 _newMesh = _newMed->getMesh(meshesNames[0]);
446 // create support on nodes on all new mesh
447 SUPPORT *newSup = new SUPPORT(_newMesh,"Support",MED_NODE);
449 // read the id of nodes of output mesh, in input mesh
452 // read connectivity of new mesh to get neighbour node of created node
453 _connL = _newMesh->getConnectivityLength(MED_FULL_INTERLACE,MED_NODAL,MED_CELL,MED_ALL_ELEMENTS);
454 _conn = _newMesh->getConnectivity(MED_FULL_INTERLACE,MED_NODAL,MED_CELL,MED_ALL_ELEMENTS);
455 _connI = _newMesh->getConnectivityIndex(MED_NODAL,MED_CELL);
457 // read number of nodes on new mesh
458 int numberOfNodes = newSup->getNumberOfElements(MED_ALL_ELEMENTS);
459 int numberOfComponents;
461 deque<string> fieldsNames = _med->getFieldNames();
462 int numberOfFields = fieldsNames.size();
467 for (int i=0; i<numberOfFields; i++){
469 // is the input field the reference field?
470 bool isReferenceField= false;
472 if( strcmp(_myDField->getName().c_str(),fieldsNames[i].c_str()) == 0)
473 isReferenceField = true;
476 if( strcmp(_myIField->getName().c_str(),fieldsNames[i].c_str()) == 0)
477 isReferenceField = true;
479 deque<DT_IT_> myIteration = _med->getFieldIteration (fieldsNames[i]);
480 string meshName = _med->getField(fieldsNames[i],myIteration[0].dt,myIteration[0].it)->getSupport()->getMesh()->getName();
482 // we process only fields on input mesh
483 if( strcmp(meshName.c_str(),_mesh->getName().c_str()) == 0){
485 // loop on time steps
486 int numberOfIteration = myIteration.size();
487 for(int j=0;j<numberOfIteration;j++){
489 // select input field
490 MEDMEM::FIELD_* field = _med->getField(fieldsNames[i],myIteration[j].dt,myIteration[j].it);
492 // if field not on nodes, take following field
493 if( field->getSupport()->getEntity() != MED_NODE )
496 FIELD<double> *myDField = NULL;
497 FIELD<double> *newDField = NULL;
498 FIELD<int> *myIField = NULL;
499 FIELD<int> *newIField = NULL;
501 if (dynamic_cast<MEDMEM::FIELD<double>*>(field)){
502 if(!isReferenceField){
503 // read input field on input file
504 myDField = new FIELD<double>(MEDMEM::MED_DRIVER,_file,fieldsNames[i],myIteration[j].dt,myIteration[j].it);
507 myDField = _myDField;
509 // create new output field
510 newDField = new FIELD<double>(newSup,field->getNumberOfComponents());
511 newDField->setName(myDField->getName());
514 if(!isReferenceField)
515 // read input field on input file
516 myIField = new FIELD<int>(MEDMEM::MED_DRIVER,_file,fieldsNames[i],myIteration[j].dt,myIteration[j].it);
518 myIField = _myIField;
519 // create new output field
520 newIField = new FIELD<int>(newSup,field->getNumberOfComponents());
521 newIField->setName(myIField->getName());
523 numberOfComponents = field->getNumberOfComponents();
525 // loop on nodes on new field
526 for (int k=1; k<=numberOfNodes; k++){
527 // read number of nodes on input field
528 int l = getNodeNumber(k);
532 for(int c=1;c<=numberOfComponents;c++){
533 // read value on input field
535 dval = myDField->getValueIJ(l,c);
537 ival = myIField->getValueIJ(l,c);
539 // write value on new field
541 newDField->setValueIJ(k,c,dval);
544 newIField->setValueIJ(k,c,ival);
549 _newMed->addField(newDField);
551 _newMed->addField(newIField);
553 // Destroy input field if not reference field
554 if(!isReferenceField)
556 delete myDField->getSupport();
560 delete myIField->getSupport();
568 catch(SALOME_Exception){
569 throw SALOME_FILTER::FILTER_Gen::FilterError("Unvalid decimate mlesh created by filtoo");
572 // destroy filtoo output files
573 command = "cd /tmp;rm -f output.*";
575 system(command.c_str());
579 void Filter_Gen_i::readMapping()
581 ifstream mapFile("/tmp/output.renum");
583 // read number of vertices to map
585 _map = new int[_nbvmap];
587 for(int i=0;i<_nbvmap;i++)
592 int Filter_Gen_i::getNodeNumber(int num)
594 int oldnum = _map[num-1];
596 // if new node get neighbour node
598 oldnum = _map[getNeighbourVertex(num)-1];
603 int Filter_Gen_i::getNeighbourVertex(int num) throw(SALOME_Exception)
606 int numberOfElements = _newMesh->getNumberOfElements(MED_CELL,MED_ALL_ELEMENTS);
609 // get index of created node in connectivity array
610 for(index=0;index<_connL;index++){
611 if(_conn[index] == num){
613 // get index of element which contain created node
615 for(i=1;i<=numberOfElements;i++)
616 if(_connI[i] > index)
619 // search neighbour node which are in old mesh
620 for(int j=_connI[i-1];j<_connI[i];j++){
622 if( _map[nnum-1] != 0)
626 // if neighbour node in old mesh: go out loop, else continue
632 // if no neighbour node in old mesh: throw exception
634 throw SALOME_Exception("None of the neighbour node are in old mesh!!");
639 void Filter_Gen_i::createMedOutputFile(const char *outMedFile)
643 MESSAGE("Create MED mesh: "<<outMedFile);
644 id = _newMed->addDriver(MED_DRIVER,outMedFile,MED_EN::MED_ECRI);
649 //=============================================================================
651 * C factory, accessible with dlsym, after dlopen
653 //=============================================================================
657 PortableServer::ObjectId * FILTEREngine_factory(
659 PortableServer::POA_ptr poa,
660 PortableServer::ObjectId * contId,
661 const char *instanceName,
662 const char *interfaceName)
664 MESSAGE("PortableServer::ObjectId * FilterEngine_factory()");
665 SCRUTE(interfaceName);
666 Filter_Gen_i * myFilter_Gen
667 = new Filter_Gen_i(orb, poa, contId, instanceName, interfaceName);
668 return myFilter_Gen->getId() ;