Salome HOME
This commit was generated by cvs2git to create tag 'V4_1_0a1'.
[modules/filter.git] / src / FILTER / Filter_Gen_i.cxx
1 //  FILTER FILTER : implemetation of FILTER idl descriptions
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //
23 //
24 //  File   : Filter_Gen_i.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : FILTER
27 //  $Header$
28
29 #include "Filter_Gen_i.hxx"
30
31 #include "Utils_SINGLETON.hxx"
32 #include "OpUtil.hxx"
33 #include "Utils_CorbaException.hxx"
34 #include "utilities.h"
35
36 #include "MEDMEM_EnsightMeshDriver.hxx"
37 #include <string>
38 #include <deque>
39 #include <map>
40
41 #include <TCollection_AsciiString.hxx>
42 #include <TColStd_SequenceOfAsciiString.hxx>
43 #include <HDFascii.hxx>
44
45 using namespace std;
46 using namespace SALOME_FILTER;
47 Filter_Gen_i* Filter_Gen_i::_FILTERGen = NULL;
48
49 //=============================================================================
50 /*!
51  *  default constructor: not for use
52  */
53 //=============================================================================
54
55 Filter_Gen_i::Filter_Gen_i()
56 {
57   MESSAGE("Filter_Gen_i::Filter_Gen_i");
58 }
59
60 //=============================================================================
61 /*!
62  *  standard constructor
63  */
64 //=============================================================================
65
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)
72 {
73   MESSAGE("activate object");
74   _thisObj = this ;
75   _id = _poa->activate_object(_thisObj);
76
77   _duringLoad=false;
78   // get an NamingService interface
79   _NS = SINGLETON_<SALOME_NamingService>::Instance() ;
80   ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting()) ;
81   _NS->init_orb( _orb ) ;
82
83   _FILTERGen = this;
84 }
85
86 //=============================================================================
87 /*!
88  *  default destructor: not for use
89  */
90 //=============================================================================
91
92 Filter_Gen_i::~Filter_Gen_i()
93 {
94   MESSAGE("Filter_Gen_i::~Filter_Gen_i");
95
96   // destruction of gradient field
97   if(_myGradient)
98     delete _myGradient;
99
100   // destruction of support of reference field: reference field is destroyed
101   // by destruction of med object
102   if(_myIField)
103     delete _myIField->getSupport();
104   if(_myDField)
105     delete _myDField->getSupport();
106
107  // destruction of criteria: support and field
108   if(_criteria){
109     delete _criteria->getSupport();
110     delete _criteria;
111   }
112
113   if(_map)
114     delete [] _map;
115   if(_med)
116     delete _med;
117   if(_newMed)
118     delete _newMed;
119 }
120
121 void Filter_Gen_i::loadMED(const char* inMedFile)
122 {
123   SCRUTE(inMedFile);
124   _file = inMedFile;
125   _med = new ::MED(MED_DRIVER,_file);
126 }
127
128 void Filter_Gen_i::unloadMED()
129 {
130   MESSAGE("unloadMED called");
131   // destruction of gradient field
132   if(_myGradient){
133     delete _myGradient;
134     _myGradient=NULL;
135   }
136
137   // destruction of support of reference field: reference field is destroyed
138   // by destruction of med object
139   if(_myIField){
140     delete _myIField->getSupport();
141     _myIField=NULL;
142   }
143   if(_myDField){
144     delete _myDField->getSupport();
145     _myDField=NULL;
146   }
147
148  // destruction of criteria: support and field
149   if(_criteria){
150     delete _criteria->getSupport();
151     delete _criteria;
152     _criteria=NULL;
153   }
154
155   if(_med){
156     delete _med;
157     _med=NULL;
158   }
159 }
160
161 StrSeq* Filter_Gen_i::getMeshNames()
162 {
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();
168   return seq;
169 }
170   
171 StrSeq * Filter_Gen_i::getFieldNames()
172 {
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();
178   return seq;
179 }
180
181 CORBA::Long  Filter_Gen_i::getMeshDimension(const char* meshName)
182 {
183   return _med->getMesh(meshName)->getMeshDimension();
184 }
185
186 CORBA::Long  Filter_Gen_i::getFieldEntity(const char* fieldName,CORBA::Long dt,CORBA::Long it)
187 {
188   return _med->getField(fieldName,dt,it)->getSupport()->getEntity();
189 }
190
191 CORBA::Boolean Filter_Gen_i::fieldIsOnAllElements(const char* fieldName,CORBA::Long dt,CORBA::Long it)
192 {
193   return _med->getField(fieldName,dt,it)->getSupport()->isOnAllElements();
194 }
195
196 DTITSeq* Filter_Gen_i::getFieldIteration(const char* fieldName)
197 {
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;
204   }
205   return seq;
206 }
207
208 char* Filter_Gen_i::getMeshName(const char* fieldName,CORBA::Long dt,CORBA::Long it)
209 {
210   return (char*)(_med->getField(fieldName,dt,it)->getSupport()->getMesh()->getName().c_str());
211 }
212
213 void Filter_Gen_i::readReferenceField(const char* meshName, const char* fieldName, CORBA::Long ts)
214 {
215   // read of input mesh
216   _mesh = _med->getMesh(meshName);
217   _mesh->read();
218   
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;
224     _myDField->read();
225     _myIField = NULL;
226   }
227   else{
228     _myIField = (MEDMEM::FIELD<int>*)field;
229     _myIField->read();
230     _myDField = NULL;
231   }
232 }
233
234 void Filter_Gen_i::buildGradient() throw(SALOME_FILTER::FILTER_Gen::FilterError)
235 {
236   if(!_myGradient){
237     FIELD<double> * gradient;
238     try{
239       if(_myDField)
240         gradient = _myDField->buildGradient();
241       else
242         gradient = _myIField->buildGradient();
243       _myGradient = gradient->buildNorm2Field();
244       delete gradient;
245     }
246     catch(MEDEXCEPTION& Mex){
247       MESSAGE("SALOME_Exception: Can't calculate gradient");
248       throw SALOME_FILTER::FILTER_Gen::FilterError("Can't calculate gradient");
249     }
250   }
251 }
252
253 void Filter_Gen_i::getMinMax(CORBA::Double& imin, CORBA::Double& imax,ref_func rf)
254 {
255   double min, max;
256
257   switch(rf){
258   case F_FIELD:
259     if (_myDField)
260       _myDField->getMinMax(min,max);
261     else{
262       int xmin, xmax;
263       _myIField->getMinMax(xmin,xmax);
264       min = (double)xmin;
265       max = (double)xmax;
266     }
267     break;
268   case F_GRAD:
269     _myGradient->getMinMax(min,max);
270     break;
271   }
272   imin = min;
273   imax = max;
274 }
275
276 LongSeq* Filter_Gen_i::getHistogram(CORBA::Long size,ref_func rf)
277 {
278   int mysize = size;
279   vector<int> myh;
280
281   switch(rf){
282   case F_FIELD:
283     if (_myDField)
284       myh = _myDField->getHistogram(mysize);
285     else
286       myh = _myIField->getHistogram(mysize);
287     break;
288   case F_GRAD:
289     myh = _myGradient->getHistogram(mysize);
290     break;
291   }
292
293   LongSeq *seq = new LongSeq();
294   seq->length(myh.size());
295   for(int i=0;i<myh.size();i++)
296     (*seq)[i] = myh[i];
297   return seq;
298 }
299
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)
301 {
302   double val, min, max;
303   bool isGVal;
304   MED_EN::medEntityMesh typ;
305
306   try{
307     if(_myDField)
308       typ = _myDField->getSupport()->getEntity();
309     else
310       typ = _myIField->getSupport()->getEntity();
311
312     // create support on nodes
313     SUPPORT *sup = new SUPPORT(_mesh,"Support",MED_NODE);
314
315     // create integer field on nodes
316     _criteria = new FIELD<int>(sup,1);
317
318     _criteria->setName("Criteria");
319
320     // read number of nodes
321     int NumberOf = sup->getNumberOfElements(MED_ALL_ELEMENTS);
322
323     for (int i=1; i<NumberOf+1; i++){
324
325       // if reference field is on elements get reference field on nodes
326       switch(typ){
327       case MED_CELL:
328         throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on cells");
329         break;
330       case MED_FACE:
331         throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on faces");
332         break;
333       case MED_EDGE:
334         throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on edges");
335         break;
336       case MED_NODE:
337         // read reference field value
338         switch(rf){
339         case F_FIELD:
340           if(_myDField)
341             val = _myDField->getValueIJ(i,1);
342           else
343             val = (double)_myIField->getValueIJ(i,1);
344           break;
345         case F_GRAD:
346           val = _myGradient->getValueIJ(i,1);
347           break;
348         }
349         break;
350       case MED_ALL_ENTITIES:
351         throw SALOME_FILTER::FILTER_Gen::FilterError("Filter doesn't run on reference field on all entities");
352         break;
353       }
354
355       // set criteria field value
356       if( nbthresh == 1 ){
357         if( areaFlag )
358           if( val >= fthresh ) isGVal = true;
359           else isGVal = false;
360         else
361           if( val <= fthresh ) isGVal = true;
362           else isGVal = false;
363       }
364       else{
365         min = fthresh;
366         max = sthresh;
367         if(sthresh < fthresh){ 
368           min = sthresh;
369           max = fthresh;
370         }
371         if( areaFlag )
372           if( (val <= min) || (val >= max) ) isGVal = true;
373           else isGVal = false;  
374         else
375           if( (val >= min) && (val <= max) ) isGVal = true;
376           else isGVal = false;  
377       }
378       if( isGVal )
379         _criteria->setValueIJ(i,1,1);
380       else
381         _criteria->setValueIJ(i,1,0);
382     }
383   }
384   catch(SALOME_Exception& ex){
385     throw SALOME_FILTER::FILTER_Gen::FilterError(ex.what());
386   }
387 }
388
389 void Filter_Gen_i::createEnsightInputFiles() throw(SALOME_FILTER::FILTER_Gen::FilterError)
390 {
391   try{
392     // call ensight driver MED to generate input ensight mesh ,
393     // input ensight boundary mesh and input criteria ensight field for filtoo
394     MESSAGE("Create ensight mesh");
395     ENSIGHT_MESH_WRONLY_DRIVER myMeshDriver("/tmp/input.case",_mesh);
396     myMeshDriver.open();
397     myMeshDriver.write();
398     myMeshDriver.close();
399
400     MESSAGE("Create ensight field");
401     ENSIGHT_FIELD_WRONLY_DRIVER<int> myFieldDriver("/tmp/input.case",_criteria);
402     myFieldDriver.open();
403     myFieldDriver.write();
404     myFieldDriver.close();
405   }
406   catch(SALOME_Exception& ex){
407     throw SALOME_FILTER::FILTER_Gen::FilterError(ex.what());
408   }
409 }
410
411 void Filter_Gen_i::filtering() throw(SALOME_FILTER::FILTER_Gen::FilterError)
412 {
413   string command;
414
415   MESSAGE("call filtoo");
416   // send filtoo command
417   command = "cd /tmp;filtoo -s -m 1 -f input -o output > /tmp/filter.log";
418   MESSAGE(command);
419   int status = system(command.c_str());
420   if(status != 0)
421     throw SALOME_FILTER::FILTER_Gen::FilterError("filtoo error");    
422
423   // destroy filtoo input files
424   command = "cd /tmp;rm -f input.*";
425   MESSAGE(command);
426   system(command.c_str());
427  
428 }
429
430 void Filter_Gen_i::projectFieldsOnDecimateMesh() throw(SALOME_FILTER::FILTER_Gen::FilterError)
431 {
432   string command;
433
434   // read of new mesh in ensight file
435   MESH* myMesh = new MESH();
436   ENSIGHT_MESH_RDONLY_DRIVER myEnsightMeshDriver("/tmp/output.case", myMesh) ;
437   myMesh->addDriver(ENSIGHT_DRIVER,"/tmp/output.case","myMesh",MED_EN::MED_LECT);
438   myMesh->read() ;
439
440   // have to call ensight driver MED to generate output MED file from filtoo output
441   _newMed = new ::MED();
442   _newMed->addMesh(myMesh);
443
444   // get new mesh name
445   deque<string> meshesNames = _newMed->getMeshNames();
446   int numberOfMeshes = meshesNames.size();
447   if( numberOfMeshes != 1)
448     throw SALOME_FILTER::FILTER_Gen::FilterError("Unvalid number of meshes in filtoo output");
449
450   // new mesh generated by filtoo
451   _newMesh = _newMed->getMesh(meshesNames[0]);
452
453   // create support on nodes on all new mesh
454   SUPPORT *newSup = new SUPPORT(_newMesh,"Support",MED_NODE);
455
456   // read the id of nodes of output mesh, in input mesh
457   readMapping();
458
459   // read connectivity of new mesh to get neighbour node of created node
460   _connL = _newMesh->getConnectivityLength(MED_FULL_INTERLACE,MED_NODAL,MED_CELL,MED_ALL_ELEMENTS);
461   _conn = _newMesh->getConnectivity(MED_FULL_INTERLACE,MED_NODAL,MED_CELL,MED_ALL_ELEMENTS);
462   _connI = _newMesh->getConnectivityIndex(MED_NODAL,MED_CELL);
463
464   // read number of nodes on new mesh
465   int numberOfNodes = newSup->getNumberOfElements(MED_ALL_ELEMENTS);
466   int numberOfComponents;
467
468   deque<string> fieldsNames = _med->getFieldNames();
469   int numberOfFields = fieldsNames.size();
470
471   try{
472
473     // loop on fields
474     for (int i=0; i<numberOfFields; i++){
475
476       // is the input field the reference field?
477       bool isReferenceField= false;
478       if(_myDField){
479         if( strcmp(_myDField->getName().c_str(),fieldsNames[i].c_str()) == 0)
480           isReferenceField = true;
481       }
482       else
483         if( strcmp(_myIField->getName().c_str(),fieldsNames[i].c_str()) == 0)
484           isReferenceField = true;
485
486       deque<DT_IT_> myIteration = _med->getFieldIteration (fieldsNames[i]);
487       string meshName = _med->getField(fieldsNames[i],myIteration[0].dt,myIteration[0].it)->getSupport()->getMesh()->getName();
488
489       // we process only fields on input mesh
490       if( strcmp(meshName.c_str(),_mesh->getName().c_str()) == 0){
491
492         // loop on time steps
493         int numberOfIteration = myIteration.size();
494         for(int j=0;j<numberOfIteration;j++){
495
496           // select input field
497           MEDMEM::FIELD_* field = _med->getField(fieldsNames[i],myIteration[j].dt,myIteration[j].it);
498
499           // if field not on nodes, take following field
500           if( field->getSupport()->getEntity() != MED_NODE )
501             break;
502
503           FIELD<double> *myDField = NULL;
504           FIELD<double> *newDField = NULL;
505           FIELD<int> *myIField = NULL;
506           FIELD<int> *newIField = NULL;
507
508           if (dynamic_cast<MEDMEM::FIELD<double>*>(field)){
509             if(!isReferenceField){
510               // read input field on input file
511               myDField = new FIELD<double>(MEDMEM::MED_DRIVER,_file,fieldsNames[i],myIteration[j].dt,myIteration[j].it);
512             }
513             else{
514               myDField = _myDField;
515             }
516             // create new output field
517             newDField = new FIELD<double>(newSup,field->getNumberOfComponents());
518             newDField->setName(myDField->getName());
519             newDField->setIterationNumber(myIteration[j].dt);
520             newDField->setOrderNumber(myIteration[j].it);
521             newDField->setTime(myDField->getTime());
522           }
523           else{
524             if(!isReferenceField)
525               // read input field on input file
526               myIField = new FIELD<int>(MEDMEM::MED_DRIVER,_file,fieldsNames[i],myIteration[j].dt,myIteration[j].it);
527             else
528               myIField = _myIField;
529             // create new output field
530             newIField = new FIELD<int>(newSup,field->getNumberOfComponents());
531             newIField->setName(myIField->getName());
532             newIField->setIterationNumber(myIteration[j].dt);
533             newIField->setOrderNumber(myIteration[j].it);
534             newIField->setTime(myIField->getTime());
535           }
536           numberOfComponents = field->getNumberOfComponents();
537           
538           // loop on nodes on new field
539           for (int k=1; k<=numberOfNodes; k++){
540             // read number of nodes on input field
541             int l = getNodeNumber(k);
542             double dval;
543             int ival;
544             
545             for(int c=1;c<=numberOfComponents;c++){
546               // read value on input field
547               if(myDField)
548                 dval = myDField->getValueIJ(l,c);
549               else
550                 ival = myIField->getValueIJ(l,c);
551               
552               // write value on new field
553               if(newDField){
554                 newDField->setValueIJ(k,c,dval);
555               }
556               else
557                 newIField->setValueIJ(k,c,ival);
558             }
559           
560           }
561           if(newDField)
562             _newMed->addField(newDField);
563           else
564             _newMed->addField(newIField);
565           
566           // Destroy input field if not reference field
567           if(!isReferenceField)
568             if(myDField){
569               delete myDField->getSupport();
570               delete myDField;
571             }
572             else{
573               delete myIField->getSupport();
574               delete myIField;
575             }
576           
577         }
578       }
579     }
580   }
581   catch(SALOME_Exception){
582     throw SALOME_FILTER::FILTER_Gen::FilterError("Unvalid decimate mlesh created by filtoo");
583   }
584
585   // destroy filtoo output files
586   command = "cd /tmp;rm -f output.*";
587   MESSAGE(command);
588   system(command.c_str());
589
590 }
591
592 void Filter_Gen_i::readMapping()
593 {
594   double tmp;
595   string firstline;
596   ifstream mapFile("/tmp/output.renum");
597
598   // read first line of file
599   getline(mapFile, firstline);
600
601   // read number of vertices to map
602   string::size_type pos = firstline.find(":");
603   istringstream iss(firstline.substr(pos+1));
604   iss >> _nbvmap;
605
606   // read each vertices in array
607   _map = new int[_nbvmap];
608   
609   for(int i=0;i<_nbvmap;i++){
610     mapFile >> tmp;
611     _map[i] = (int)tmp;
612   }
613
614 }
615
616 int Filter_Gen_i::getNodeNumber(int num)
617 {
618   int oldnum = _map[num-1];
619
620   // if new node get neighbour node
621   if(oldnum == 0)
622     oldnum = _map[getNeighbourVertex(num)-1];
623   
624   return oldnum;
625 }
626
627 int Filter_Gen_i::getNeighbourVertex(int num) throw(SALOME_Exception)
628 {
629   int nnum;
630   int numberOfElements = _newMesh->getNumberOfElements(MED_CELL,MED_ALL_ELEMENTS);
631
632   int index;
633   // get index of created node in connectivity array
634   for(index=0;index<_connL;index++){
635     if(_conn[index] == num){
636
637       // get index of element which contain created node
638       int i;
639       for(i=1;i<=numberOfElements;i++)
640         if(_connI[i] > index)
641           break;
642
643       // search neighbour node which are in old mesh
644       for(int j=_connI[i-1];j<_connI[i];j++){
645         nnum = _conn[j-1];
646         if( _map[nnum-1] != 0)
647           break;
648       }
649
650       // if neighbour node in old mesh: go out loop, else continue
651       if(_map[nnum-1]!=0)
652         break;
653     }
654   }
655
656   // if no neighbour node in old mesh: throw exception
657   if(_map[nnum-1]==0)
658     throw SALOME_Exception("None of the neighbour node are in old mesh!!");
659
660   return nnum;
661 }
662
663 void Filter_Gen_i::createMedOutputFile(const char *outMedFile)
664 {
665   int id;
666
667   MESSAGE("Create MED mesh: "<<outMedFile);
668   id = _newMed->addDriver(MED_DRIVER,outMedFile,MED_EN::MED_ECRI);
669   _newMed->write(id);
670 }
671
672
673 //=============================================================================
674 /*!
675  * C factory, accessible with dlsym, after dlopen
676  */
677 //=============================================================================
678
679 extern "C"
680 {
681   PortableServer::ObjectId * FILTEREngine_factory(
682                                CORBA::ORB_ptr orb,
683                                PortableServer::POA_ptr poa,
684                                PortableServer::ObjectId * contId,
685                                const char *instanceName,
686                                const char *interfaceName)
687   {
688     MESSAGE("PortableServer::ObjectId * FilterEngine_factory()");
689     SCRUTE(interfaceName);
690     Filter_Gen_i * myFilter_Gen
691       = new Filter_Gen_i(orb, poa, contId, instanceName, interfaceName);
692     return myFilter_Gen->getId() ;
693   }
694 }