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 DTITSeq* Filter_Gen_i::getFieldIteration(const char* fieldName)
188 DTITSeq *seq = new DTITSeq();
189 deque<DT_IT_> deq = _med->getFieldIteration(fieldName);
190 seq->length(deq.size());
191 for(int i=0;i<deq.size();i++){
192 (*seq)[i].dt = deq[i].dt;
193 (*seq)[i].it = deq[i].it;
198 char* Filter_Gen_i::getMeshName(const char* fieldName,CORBA::Long dt,CORBA::Long it)
200 return (char*)(_med->getField(fieldName,dt,it)->getSupport()->getMesh()->getName().c_str());
203 void Filter_Gen_i::readReferenceField(const char* meshName, const char* fieldName, CORBA::Long ts)
205 // read of input mesh
206 _mesh = _med->getMesh(meshName);
209 // read of input field
210 deque<DT_IT_> myIteration = _med->getFieldIteration (fieldName);
211 MEDMEM::FIELD_* field = _med->getField(fieldName,myIteration[ts].dt,myIteration[ts].it);
212 if (dynamic_cast<MEDMEM::FIELD<double>*>(field)){
213 _myDField = (MEDMEM::FIELD<double>*)field;
218 _myIField = (MEDMEM::FIELD<int>*)field;
224 void Filter_Gen_i::buildGradient() throw(SALOME_FILTER::FILTER_Gen::FilterError)
227 FIELD<double> * gradient;
230 gradient = _myDField->buildGradient();
232 gradient = _myIField->buildGradient();
233 _myGradient = gradient->buildNorm2Field();
236 catch(MEDEXCEPTION& Mex){
237 MESSAGE("SALOME_Exception: Can't calculate gradient");
238 throw SALOME_FILTER::FILTER_Gen::FilterError("Can't calculate gradient");
243 void Filter_Gen_i::getMinMax(CORBA::Double& imin, CORBA::Double& imax,ref_func rf)
250 _myDField->getMinMax(min,max);
253 _myIField->getMinMax(xmin,xmax);
259 _myGradient->getMinMax(min,max);
266 LongSeq* Filter_Gen_i::getHistogram(CORBA::Long size,ref_func rf)
274 myh = _myDField->getHistogram(mysize);
276 myh = _myIField->getHistogram(mysize);
279 myh = _myGradient->getHistogram(mysize);
283 LongSeq *seq = new LongSeq();
284 seq->length(myh.size());
285 for(int i=0;i<myh.size();i++)
290 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)
292 double val, min, max;
295 MED_EN::medEntityMesh typ;
298 FIELD<double> *volume;
299 set <int> listElements;
300 set <int>::iterator elemIt ;
303 typ = _myDField->getSupport()->getEntity();
305 typ = _myIField->getSupport()->getEntity();
307 // create support on nodes
308 SUPPORT *sup = new SUPPORT(_mesh,"Support",MED_NODE);
310 // create integer field on nodes
311 _criteria = new FIELD<int>(sup,1);
313 _criteria->setName("Criteria");
315 // read number of nodes
316 int NumberOf = sup->getNumberOfElements(MED_ALL_ELEMENTS);
318 // if reference field is on elements get reference field on nodes
322 // calculate reverse connectivity to have the list of elements which contains node i
323 revC = _myDField->getSupport()->getMesh()->getReverseConnectivity(MED_NODAL,typ);
324 indC = _myDField->getSupport()->getMesh()->getReverseConnectivityIndex(MED_NODAL,typ);
325 // calculate volume field on mesh
326 volume = _myDField->getSupport()->getMesh()->getVolume(_myDField->getSupport());
329 // calculate reverse connectivity to have the list of elements which contains node i
330 revC = _myIField->getSupport()->getMesh()->getReverseConnectivity(MED_NODAL,typ);
331 indC = _myIField->getSupport()->getMesh()->getReverseConnectivityIndex(MED_NODAL,typ);
332 // calculate volume field on mesh
333 volume = _myIField->getSupport()->getMesh()->getVolume(_myIField->getSupport());
340 for (int i=1; i<NumberOf+1; i++){
342 // if reference field is on elements get reference field on nodes
345 // listElements contains elements which contains a node of element i
346 listElements.clear();
348 for(int j=indC[i-1];j<indC[i];j++){
349 // c element contains node i
351 listElements.insert(c);
354 // calculate field value on node i
357 for(elemIt=listElements.begin();elemIt!=listElements.end();elemIt++){
359 double vol = volume->getValueIJ(elem,1);
363 val += _myDField->getValueIJ(elem,1)/vol;
365 val += ((double)_myIField->getValueIJ(elem,1))/vol;
371 throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on faces");
374 throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on edges");
377 // read reference field value
379 val = _myDField->getValueIJ(i,1);
381 val = (double)_myIField->getValueIJ(i,1);
383 case MED_ALL_ENTITIES:
384 throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on all entities");
388 // set criteria field value
391 if( val >= fthresh ) isGVal = true;
394 if( val <= fthresh ) isGVal = true;
400 if(sthresh < fthresh){
405 if( (val <= min) || (val >= max) ) isGVal = true;
408 if( (val >= min) && (val <= max) ) isGVal = true;
412 _criteria->setValueIJ(i,1,1);
414 _criteria->setValueIJ(i,1,0);
418 void Filter_Gen_i::createEnsightInputFiles()
422 MESSAGE("Calculate boundary");
423 // generate MED boundary of geometry
424 SUPPORT *supB = _mesh->getBoundaryElements(MED_FACE);
426 // call ensight driver MED to generate input ensight mesh ,
427 // input ensight boundary mesh and input criteria ensight field for filtoo
428 MESSAGE("Create ensight mesh");
429 ENSIGHT_MESH_WRONLY_DRIVER myMeshDriver("/tmp/input.case",_mesh);
430 myMeshDriver.addSupport(supB);
431 // myMeshDriver.open();
432 myMeshDriver.write();
433 // myMeshDriver.close();
435 MESSAGE("Create ensight field");
436 ENSIGHT_FIELD_WRONLY_DRIVER<int> myFieldDriver("/tmp/input.case",_criteria);
437 // myFieldDriver.open();
438 myFieldDriver.write();
439 // myFieldDriver.close();
442 void Filter_Gen_i::filtering()
446 MESSAGE("call filtoo");
447 // send filtoo command
448 command = "cd /tmp;filtoo -f input -o output > /tmp/filter.log";
450 system(command.c_str());
452 // destroy filtoo input files
453 // command = "cd /tmp;rm -f input.*";
455 // system(command.c_str());
459 void Filter_Gen_i::projectFieldsOnDecimateMesh() throw(SALOME_FILTER::FILTER_Gen::FilterError)
463 // read of new mesh in ensight file
464 MESH* myMesh = new MESH();
465 ENSIGHT_MESH_RDONLY_DRIVER myEnsightMeshDriver("/tmp/output.case", myMesh) ;
466 myMesh->addDriver(ENSIGHT_DRIVER,"/tmp/output.case","myMesh",MED_EN::MED_LECT);
469 // have to call ensight driver MED to generate output MED file from filtoo output
470 _newMed = new ::MED();
471 _newMed->addMesh(myMesh);
473 // destroy filtoo output files
474 // command = "cd /tmp;rm -f output.*";
476 // system(command.c_str());
479 deque<string> meshesNames = _newMed->getMeshNames();
480 int numberOfMeshes = meshesNames.size();
481 if( numberOfMeshes != 1)
482 throw SALOME_FILTER::FILTER_Gen::FilterError("Unvalid number of meshes in filtoo output");
484 // new mesh generated by filtoo
485 _newMesh = _newMed->getMesh(meshesNames[0]);
487 // create support on nodes on all new mesh
488 SUPPORT *newSup = new SUPPORT(_newMesh,"Support",MED_NODE);
490 // read the id of nodes of output mesh, in input mesh
493 // read connectivity of new mesh to get neighbour node of created node
494 _connL = _newMesh->getConnectivityLength(MED_FULL_INTERLACE,MED_NODAL,MED_CELL,MED_ALL_ELEMENTS);
495 _conn = _newMesh->getConnectivity(MED_FULL_INTERLACE,MED_NODAL,MED_CELL,MED_ALL_ELEMENTS);
496 _connI = _newMesh->getConnectivityIndex(MED_NODAL,MED_CELL);
498 // read number of nodes on new mesh
499 int numberOfNodes = newSup->getNumberOfElements(MED_ALL_ELEMENTS);
500 int numberOfComponents;
502 deque<string> fieldsNames = _med->getFieldNames();
503 int numberOfFields = fieldsNames.size();
508 for (int i=0; i<numberOfFields; i++){
510 // is the input field the reference field?
511 bool isReferenceField= false;
513 if( strcmp(_myDField->getName().c_str(),fieldsNames[i].c_str()) == 0)
514 isReferenceField = true;
517 if( strcmp(_myIField->getName().c_str(),fieldsNames[i].c_str()) == 0)
518 isReferenceField = true;
520 deque<DT_IT_> myIteration = _med->getFieldIteration (fieldsNames[i]);
521 string meshName = _med->getField(fieldsNames[i],myIteration[0].dt,myIteration[0].it)->getSupport()->getMesh()->getName();
523 // we process only fields on input mesh
524 if( strcmp(meshName.c_str(),_mesh->getName().c_str()) == 0){
526 // loop on time steps
527 int numberOfIteration = myIteration.size();
528 for(int j=0;j<numberOfIteration;j++){
530 // select input field
531 MEDMEM::FIELD_* field = _med->getField(fieldsNames[i],myIteration[j].dt,myIteration[j].it);
532 FIELD<double> *myDField = NULL;
533 FIELD<double> *newDField = NULL;
534 FIELD<int> *myIField = NULL;
535 FIELD<int> *newIField = NULL;
537 if (dynamic_cast<MEDMEM::FIELD<double>*>(field)){
538 if(!isReferenceField){
539 // read input field on input file
540 myDField = new FIELD<double>(MEDMEM::MED_DRIVER,_file,fieldsNames[i],myIteration[j].dt,myIteration[j].it);
543 myDField = _myDField;
545 // create new output field
546 newDField = new FIELD<double>(newSup,field->getNumberOfComponents());
547 newDField->setName(myDField->getName());
550 if(!isReferenceField)
551 // read input field on input file
552 myIField = new FIELD<int>(MEDMEM::MED_DRIVER,_file,fieldsNames[i],myIteration[j].dt,myIteration[j].it);
554 myIField = _myIField;
555 // create new output field
556 newIField = new FIELD<int>(newSup,field->getNumberOfComponents());
557 newIField->setName(myIField->getName());
559 numberOfComponents = field->getNumberOfComponents();
561 // loop on nodes on new field
562 for (int k=1; k<=numberOfNodes; k++){
563 // read number of nodes on input field
564 int l = getNodeNumber(k);
568 for(int c=1;c<=numberOfComponents;c++){
569 // read value on input field
571 dval = myDField->getValueIJ(l,c);
573 ival = myIField->getValueIJ(l,c);
575 // write value on new field
577 newDField->setValueIJ(k,c,dval);
580 newIField->setValueIJ(k,c,ival);
585 _newMed->addField(newDField);
587 _newMed->addField(newIField);
589 // Destroy input field if not reference field
590 if(!isReferenceField)
592 delete myDField->getSupport();
596 delete myIField->getSupport();
604 catch(SALOME_Exception){
605 throw SALOME_FILTER::FILTER_Gen::FilterError("Unvalid decimate mlesh created by filtoo");
609 void Filter_Gen_i::readMapping()
611 ifstream mapFile("/tmp/output.renum");
613 // read number of vertices to map
615 _map = new int[_nbvmap];
617 for(int i=0;i<_nbvmap;i++)
622 int Filter_Gen_i::getNodeNumber(int num)
624 int oldnum = _map[num-1];
626 // if new node get neighbour node
628 oldnum = _map[getNeighbourVertex(num)-1];
633 int Filter_Gen_i::getNeighbourVertex(int num) throw(SALOME_Exception)
636 int numberOfElements = _newMesh->getNumberOfElements(MED_CELL,MED_ALL_ELEMENTS);
639 // get index of created node in connectivity array
640 for(index=0;index<_connL;index++){
641 if(_conn[index] == num){
643 // get index of element which contain created node
645 for(i=1;i<=numberOfElements;i++)
646 if(_connI[i] > index)
649 // search neighbour node which are in old mesh
650 for(int j=_connI[i-1];j<_connI[i];j++){
652 if( _map[nnum-1] != 0)
656 // if neighbour node in old mesh: go out loop, else continue
662 // if no neighbour node in old mesh: throw exception
664 throw SALOME_Exception("None of the neighbour node are in old mesh!!");
669 void Filter_Gen_i::createMedOutputFile(const char *outMedFile)
673 MESSAGE("Create MED mesh: "<<outMedFile);
674 id = _newMed->addDriver(MED_DRIVER,outMedFile,MED_EN::MED_ECRI);
679 //=============================================================================
681 * C factory, accessible with dlsym, after dlopen
683 //=============================================================================
687 PortableServer::ObjectId * FILTEREngine_factory(
689 PortableServer::POA_ptr poa,
690 PortableServer::ObjectId * contId,
691 const char *instanceName,
692 const char *interfaceName)
694 MESSAGE("PortableServer::ObjectId * FilterEngine_factory()");
695 SCRUTE(interfaceName);
696 Filter_Gen_i * myFilter_Gen
697 = new Filter_Gen_i(orb, poa, contId, instanceName, interfaceName);
698 return myFilter_Gen->getId() ;