]> SALOME platform Git repositories - modules/med.git/blob - src/MEDMEM/MEDMEM_Field.hxx
Salome HOME
committing the version in the main trunk of the CVS tree the branch
[modules/med.git] / src / MEDMEM / MEDMEM_Field.hxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/
19 //
20 /*
21  File Field.hxx
22  $Header$
23 */
24
25 #ifndef FIELD_HXX
26 #define FIELD_HXX
27
28 #include <vector>
29 #include <algorithm>
30 #include <math.h>
31 #include <cmath>
32
33 #include "MEDMEM_Utilities.hxx"
34 #include "MEDMEM_Exception.hxx"
35 #include "MEDMEM_define.hxx"
36 #include "MEDMEM_Support.hxx"
37 #include "MEDMEM_Unit.hxx"
38 #include "MEDMEM_nArray.hxx"
39 #include "MEDMEM_GenDriver.hxx"
40 #include "MEDMEM_ArrayInterface.hxx"
41 #include "MEDMEM_FieldForward.hxx"
42
43 /*!
44
45   This class contains all the informations related with a template class FIELD :
46   - Components descriptions
47   - Time step description
48   - Location of the values (a SUPPORT class)
49
50 */
51
52 namespace MEDMEM {
53
54   template < typename T > struct SET_VALUE_TYPE {
55     static const MED_EN::med_type_champ _valueType = MED_EN::MED_UNDEFINED_TYPE;};
56   template < > struct SET_VALUE_TYPE<double> {
57     static const MED_EN::med_type_champ _valueType = MED_EN::MED_REEL64; };
58   template < > struct SET_VALUE_TYPE<int> {
59     static const MED_EN::med_type_champ _valueType = MED_EN::MED_INT32; };
60
61   template < typename T > struct SET_INTERLACING_TYPE {
62     static const MED_EN::medModeSwitch _interlacingType = MED_EN::MED_UNDEFINED_INTERLACE; };
63   template < > struct SET_INTERLACING_TYPE<FullInterlace>{
64     static const MED_EN::medModeSwitch _interlacingType = MED_EN::MED_FULL_INTERLACE; };
65   template < > struct SET_INTERLACING_TYPE<NoInterlace> {
66     static const MED_EN::medModeSwitch _interlacingType = MED_EN::MED_NO_INTERLACE; };
67
68 class FIELD_    // GENERIC POINTER TO a template <class T, class INTERLACING_TAG> class FIELD
69 {  // Ã¹pihjpmoçhmpç_hmù
70 protected:
71
72   bool            _isRead ;
73
74   /*!
75     \if developper
76     Field name.
77     \endif
78   */
79   string          _name ;
80   /*!
81     \if developper
82     Field description.
83     \endif
84   */
85   string          _description ;
86   /*!
87     \if developper
88     Pointer to the support the field deals with.
89     \endif
90   */
91   const SUPPORT * _support ;
92
93   /*!
94     \if developper
95     Number of field's components.
96     \endif
97   */
98   int             _numberOfComponents ;
99   /*!
100     \if developper
101     Number of field's values.
102     \endif
103   */
104   int             _numberOfValues ;
105
106   /*!
107     \if developper
108     Array of size _numberOfComponents. \n
109     (constant, scalar, vector, tensor)\n
110     We could use an array of integer to store
111     numbers of values: \n
112     - 1 for scalar,\n
113     - space dimension for vector,\n
114     - space dimension square for tensor.\n
115     So numbers of values per entities would be
116     sum of _componentsTypes array.
117
118     Not implemented yet! All type are scalar !
119     \endif
120   */
121   int *           _componentsTypes ;
122   /*!
123     \if developper
124     Array of size _numberOfComponents
125     storing components names if any.
126     \endif
127   */
128   string *        _componentsNames;
129   /*!
130     \if developper
131     Array of size _numberOfComponents
132     storing components descriptions if any.
133     \endif
134  */
135   string *        _componentsDescriptions;
136   /*!
137     \if developper
138     Array of size _numberOfComponents
139     storing components units if any.
140     \endif
141  */
142   UNIT *          _componentsUnits;
143   /*!
144     \if developper
145     Array of size _numberOfComponents
146     storing components units if any.
147     \endif
148   */
149   string *        _MEDComponentsUnits;
150   /*!
151     \if developper
152     Iteration number of the field.
153     \endif
154   */
155   int             _iterationNumber ;
156   /*!
157     \if developper
158     Time of the field.
159     \endif
160   */
161   double          _time;
162   /*!
163     \if developper
164     Order number of the field.
165     \endif
166   */
167   int             _orderNumber ;
168   /*!
169     \if developper
170     At the initialization step of the field using the constructors; this attribute,
171     the value type (integer or real) , is set automatically. There is a get method
172     but not a set method for this attribute.
173     \endif
174   */
175   MED_EN::med_type_champ _valueType ;
176   /*!
177     \if developper
178     At the initialization step of the field using the constructors; this attribute,
179     the interlacing type (full interlace or no interlace field value storage), is set
180     automatically. There is a get method but not a set method for this attribute.
181     \endif
182   */
183   MED_EN::medModeSwitch _interlacingType;
184
185   vector<GENDRIVER *> _drivers; // Storage of the drivers currently in use
186   static void _checkFieldCompatibility(const FIELD_& m, const FIELD_& n, bool checkUnit=true) throw (MEDEXCEPTION);
187   static void _deepCheckFieldCompatibility(const FIELD_& m, const FIELD_& n, bool checkUnit=true) throw (MEDEXCEPTION);
188   void _checkNormCompatibility(const FIELD<double>* p_field_volume=NULL) const  throw (MEDEXCEPTION);
189   FIELD<double>* _getFieldSize() const;
190
191 public:
192
193   friend class MED_MED_RDONLY_DRIVER21;
194   friend class MED_MED_WRONLY_DRIVER21;
195   friend class MED_MED_RDWR_DRIVER21;
196   friend class MED_MED_RDONLY_DRIVER22;
197   friend class MED_MED_WRONLY_DRIVER22;
198   friend class MED_MED_RDWR_DRIVER22;
199
200   friend class VTK_MED_DRIVER;
201
202   /*!
203     Constructor.
204   */
205   FIELD_ ();
206   /*!
207     Constructor.
208   */
209   FIELD_(const SUPPORT * Support, const int NumberOfComponents);
210   /*!
211     Copy constructor.
212   */
213   FIELD_(const FIELD_ &m);
214
215   /*!
216     Destructor.
217   */
218   virtual ~FIELD_();
219
220  FIELD_& operator=(const FIELD_ &m);
221
222   virtual  void     rmDriver(int index=0);
223   virtual   int     addDriver(driverTypes driverType,
224                               const string & fileName="Default File Name.med",
225                               const string & driverFieldName="Default Field Nam",
226                               MED_EN::med_mode_acces access=MED_EN::MED_REMP) ;
227
228   virtual  int      addDriver( GENDRIVER & driver);
229   virtual  void     read (const GENDRIVER &);
230   virtual  void     read(int index=0);
231   virtual void openAppend( void );
232   virtual  void     write(const GENDRIVER &);
233   virtual  void     write(int index=0, const string & driverName="");
234
235   virtual  void     writeAppend(const GENDRIVER &);
236   virtual  void     writeAppend(int index=0, const string & driverName="");
237
238   inline void     setName(const string Name);
239   inline string   getName() const;
240   inline void     setDescription(const string Description);
241   inline string   getDescription() const;
242   inline const SUPPORT * getSupport() const;
243   inline void     setSupport(const SUPPORT * support);
244   inline void     setNumberOfComponents(const int NumberOfComponents);
245   inline int      getNumberOfComponents() const;
246   inline void     setNumberOfValues(const int NumberOfValues);
247   inline int      getNumberOfValues() const;
248   //    inline void     setComponentType(int *ComponentType);
249   //    inline int *    getComponentType() const;
250   //    inline int      getComponentTypeI(int i) const;
251   inline void     setComponentsNames(const string * ComponentsNames);
252   inline void     setComponentName(int i, const string ComponentName);
253   inline const string * getComponentsNames() const;
254   inline string   getComponentName(int i) const;
255   inline void     setComponentsDescriptions(const string * ComponentsDescriptions);
256   inline void     setComponentDescription(int i, const string ComponentDescription);
257   inline const string * getComponentsDescriptions() const;
258   inline string   getComponentDescription(int i) const;
259
260   // provisoire : en attendant de regler le probleme des unites !
261   inline void     setComponentsUnits(const UNIT * ComponentsUnits);
262   inline const UNIT *   getComponentsUnits() const;
263   inline const UNIT *   getComponentUnit(int i) const;
264   inline void     setMEDComponentsUnits(const string * MEDComponentsUnits);
265   inline void     setMEDComponentUnit(int i, const string MEDComponentUnit);
266   inline const string * getMEDComponentsUnits() const;
267   inline string   getMEDComponentUnit(int i) const;
268
269   inline void     setIterationNumber(int IterationNumber);
270   inline int      getIterationNumber() const;
271   inline void     setTime(double Time);
272   inline double   getTime() const;
273   inline void     setOrderNumber(int OrderNumber);
274   inline int      getOrderNumber() const;
275
276   inline MED_EN::med_type_champ getValueType () const;
277   inline MED_EN::medModeSwitch  getInterlacingType() const;
278   virtual inline bool getGaussPresence() const throw (MEDEXCEPTION);
279 protected:
280   void copyGlobalInfo(const FIELD_& m);
281 };
282
283 // ---------------------------------
284 // Implemented Methods : constructor
285 // ---------------------------------
286
287 // -----------------
288 // Methodes Inline
289 // -----------------
290 /*!
291   Set FIELD name.
292 */
293 inline void FIELD_::setName(const string Name)
294 {
295   _name=Name;
296 }
297 /*!
298   Get FIELD name.
299 */
300 inline string FIELD_::getName() const
301 {
302   return _name;
303 }
304 /*!
305   Set FIELD description.
306 */
307 inline void FIELD_::setDescription(const string Description)
308 {
309   _description=Description;
310 }
311 /*!
312   Get FIELD description.
313 */
314 inline string FIELD_::getDescription() const
315 {
316   return _description;
317 }
318 /*!
319   Set FIELD number of components.
320 */
321 inline void FIELD_::setNumberOfComponents(const int NumberOfComponents)
322 {
323   _numberOfComponents=NumberOfComponents;
324 }
325 /*!
326   Get FIELD number of components.
327 */
328 inline int FIELD_::getNumberOfComponents() const
329 {
330   return _numberOfComponents ;
331 }
332 /*!
333   Set FIELD number of values.
334
335   It must be the same than in the associated SUPPORT object.
336 */
337 inline void FIELD_::setNumberOfValues(const int NumberOfValues)
338 {
339   _numberOfValues=NumberOfValues;
340 }
341 /*!
342   Get FIELD number of value.
343 */
344 inline int FIELD_::getNumberOfValues() const
345 {
346   return _numberOfValues ;
347 }
348
349 //  inline void FIELD_::setComponentType(int *ComponentType)
350 //  {
351 //    _componentsTypes=ComponentType ;
352 //  }
353 //  inline int * FIELD_::getComponentType() const
354 //  {
355 //    return _componentsTypes ;
356 //  }
357 //  inline int FIELD_::getComponentTypeI(int i) const
358 //  {
359 //    return _componentsTypes[i-1] ;
360 //  }
361
362 /*!
363   Set FIELD components names.
364
365   Duplicate the ComponentsNames string array to put components names in
366   FIELD. ComponentsNames size must be equal to number of components.
367 */
368 inline void FIELD_::setComponentsNames(const string * ComponentsNames)
369 {
370   if (NULL == _componentsNames)
371     _componentsNames = new string[_numberOfComponents] ;
372   for (int i=0; i<_numberOfComponents; i++)
373     _componentsNames[i]=ComponentsNames[i] ;
374 }
375 /*!
376   Set FIELD i^th component name.
377
378   i must be >=1 and <= number of components.
379 */
380 inline void FIELD_::setComponentName(int i, const string ComponentName)
381 {
382   _componentsNames[i-1]=ComponentName ;
383 }
384 /*!
385   Get a reference to the string array which contain the components names.
386
387   This Array size is equal to number of components
388 */
389 inline const string * FIELD_::getComponentsNames() const
390 {
391   return _componentsNames ;
392 }
393 /*!
394   Get the name of the i^th component.
395 */
396 inline string FIELD_::getComponentName(int i) const
397 {
398   return _componentsNames[i-1] ;
399 }
400 /*!
401   Set FIELD components descriptions.
402
403   Duplicate the ComponentsDescriptions string array to put components
404   descriptions in FIELD.
405   ComponentsDescriptions size must be equal to number of components.
406 */
407 inline void FIELD_::setComponentsDescriptions(const string * ComponentsDescriptions)
408 {
409   if (NULL == _componentsDescriptions)
410     _componentsDescriptions = new string[_numberOfComponents] ;
411   for (int i=0; i<_numberOfComponents; i++)
412     _componentsDescriptions[i]=ComponentsDescriptions[i] ;
413 }
414 /*!
415   Set FIELD i^th component description.
416
417   i must be >=1 and <= number of components.
418 */
419 inline void FIELD_::setComponentDescription(int i,const string ComponentDescription)
420 {
421   _componentsDescriptions[i-1]=ComponentDescription ;
422 }
423 /*!
424   Get a reference to the string array which contain the components descriptions.
425
426   This Array size is equal to number of components
427 */
428 inline const string * FIELD_::getComponentsDescriptions() const
429 {
430   return _componentsDescriptions ;
431 }
432 /*!
433   Get the description of the i^th component.
434 */
435 inline string FIELD_::getComponentDescription(int i) const
436 {
437   return _componentsDescriptions[i-1];
438 }
439
440 /*!
441   \todo
442   Set FIELD components UNIT.
443
444   Duplicate the ComponentsUnits UNIT array to put components
445   units in FIELD.
446   ComponentsUnits size must be equal to number of components.
447 */
448 inline void FIELD_::setComponentsUnits(const UNIT * ComponentsUnits)
449 {
450   if (NULL == _componentsUnits)
451     _componentsUnits = new UNIT[_numberOfComponents] ;
452   for (int i=0; i<_numberOfComponents; i++)
453     _componentsUnits[i]=ComponentsUnits[i] ;
454 }
455 /*!
456   Get a reference to the UNIT array which contain the components units.
457
458   This Array size is equal to number of components
459 */
460 inline const UNIT * FIELD_::getComponentsUnits() const
461 {
462   return _componentsUnits ;
463 }
464 /*!
465   Get the UNIT of the i^th component.
466 */
467 inline const UNIT * FIELD_::getComponentUnit(int i) const
468 {
469   return &_componentsUnits[i-1] ;
470 }
471 /*!
472   Set FIELD components unit.
473
474   Duplicate the MEDComponentsUnits string array to put components
475   units in FIELD.
476   MEDComponentsUnits size must be equal to number of components.
477
478 */
479 inline void FIELD_::setMEDComponentsUnits(const string * MEDComponentsUnits)
480 {
481   if (NULL == _MEDComponentsUnits)
482     _MEDComponentsUnits = new string[_numberOfComponents] ;
483   for (int i=0; i<_numberOfComponents; i++)
484     _MEDComponentsUnits[i]=MEDComponentsUnits[i] ;
485 }
486 /*!
487   Set FIELD i^th component unit.
488
489   i must be >=1 and <= number of components.
490 */
491 inline void FIELD_::setMEDComponentUnit(int i, const string MEDComponentUnit)
492 {
493   _MEDComponentsUnits[i-1]=MEDComponentUnit ;
494 }
495 /*!
496   Get a reference to the string array which contain the components units.
497
498   This Array size is equal to number of components
499 */
500 inline const string * FIELD_::getMEDComponentsUnits() const
501 {
502   return _MEDComponentsUnits ;
503 }
504 /*!
505   Get the string for unit of the i^th component.
506 */
507 inline string FIELD_::getMEDComponentUnit(int i) const
508 {
509   return _MEDComponentsUnits[i-1] ;
510 }
511 /*!
512   Set the iteration number where FIELD has been calculated.
513 */
514 inline void FIELD_::setIterationNumber(int IterationNumber)
515 {
516   _iterationNumber=IterationNumber;
517 }
518 /*!
519   Get the iteration number where FIELD has been calculated.
520 */
521 inline int FIELD_::getIterationNumber() const
522 {
523   return _iterationNumber ;
524 }
525 /*!
526   Set the time (in second) where FIELD has been calculated.
527 */
528 inline void FIELD_::setTime(double Time)
529 {
530   _time=Time ;
531 }
532 /*!
533   Get the time (in second) where FIELD has been calculated.
534 */
535 inline double FIELD_::getTime() const
536 {
537   return _time ;
538 }
539 /*!
540   Set the order number where FIELD has been calculated.
541
542   It corresponds to internal iteration during one time step.
543 */
544 inline void FIELD_::setOrderNumber(int OrderNumber)
545 {
546   _orderNumber=OrderNumber ;
547 }
548 /*!
549   Get the order number where FIELD has been calculated.
550 */
551 inline int FIELD_::getOrderNumber() const
552 {
553   return _orderNumber ;
554 }
555 /*!
556   Get a reference to the SUPPORT object associated to FIELD.
557 */
558 inline  const SUPPORT * FIELD_::getSupport() const
559 {
560   return _support ;
561 }
562 /*!
563   Set the reference to the SUPPORT object associated to FIELD.
564
565   Reference is not duplicate, so it must not be deleted.
566 */
567 inline void FIELD_::setSupport(const SUPPORT * support)
568 {
569   //A.G. Addings for RC
570   if(_support)
571     _support->removeReference();
572   _support = support ;
573   if(_support)
574     _support->addReference();
575 }
576 /*!
577   Get the FIELD med value type (MED_INT32 or MED_REEL64).
578 */
579 inline MED_EN::med_type_champ FIELD_::getValueType () const
580 {
581   return _valueType ;
582 }
583
584 /*!
585   Get the FIELD med interlacing type (MED_FULL_INTERLACE or MED_NO_INTERLACE).
586 */
587   inline MED_EN::medModeSwitch FIELD_::getInterlacingType () const
588 {
589   return _interlacingType ;
590 }
591
592 /*!
593   Get the FIELD gauss presence.
594 */
595   inline bool  FIELD_::getGaussPresence() const throw (MEDEXCEPTION)
596 {
597   const char * LOC = "FIELD_::getGaussPresence() : ";
598   throw MEDEXCEPTION(STRING(LOC) << " This FIELD_ doesn't rely on a FIELD<T>" );
599 }
600
601 } //End namespace MEDMEM
602
603 /////////////////////////
604 // END OF CLASS FIELD_ //
605 /////////////////////////
606
607 /*!
608
609   This template class contains informations related with a FIELD :
610   - Values of the field, their type (real or integer), the storage mode (full interlace or
611     no interlace).
612
613 */
614
615 namespace MEDMEM {
616
617   template<class T2> class MED_FIELD_RDONLY_DRIVER21;
618   template<class T2> class MED_FIELD_WRONLY_DRIVER21;
619   template<class T2> class MED_FIELD_RDONLY_DRIVER22;
620   template<class T2> class MED_FIELD_WRONLY_DRIVER22;
621   template<class T2> class VTK_FIELD_DRIVER;
622
623   template <class T,
624             class INTERLACING_TAG
625             > class FIELD : public FIELD_
626 {
627 protected:
628
629   typedef typename MEDMEM_ArrayInterface<T,INTERLACING_TAG,NoGauss>::Array ArrayNoGauss;
630   typedef typename MEDMEM_ArrayInterface<T,INTERLACING_TAG,Gauss>::Array   ArrayGauss;
631   typedef typename MEDMEM_ArrayInterface<T,NoInterlace,NoGauss>::Array     ArrayNo;
632   typedef typename MEDMEM_ArrayInterface<T,FullInterlace,NoGauss>::Array   ArrayFull;
633   typedef  MEDMEM_Array_ Array;
634
635   // array of value of type T
636   Array *_value ;
637
638   static T _scalarForPow;
639   static T pow(T x);
640
641 private:
642   void _operation(const FIELD& m,const FIELD& n, char* Op);
643   void _operationInitialize(const FIELD& m,const FIELD& n, char* Op);
644   void _add_in_place(const FIELD& m,const FIELD& n);
645   void _sub_in_place(const FIELD& m,const FIELD& n);
646   void _mul_in_place(const FIELD& m,const FIELD& n);
647   void _div_in_place(const FIELD& m,const FIELD& n) throw (MEDEXCEPTION);
648   //setValueType() ;
649
650 public:
651   FIELD();
652   FIELD(const FIELD &m);
653   FIELD(const SUPPORT * Support, const int NumberOfComponents)  throw (MEDEXCEPTION) ;
654   FIELD( driverTypes driverType,
655          const string & fileName, const string & fieldDriverName,
656          const int iterationNumber=-1, const int orderNumber=-1)
657     throw (MEDEXCEPTION);
658   FIELD(const SUPPORT * Support, driverTypes driverType,
659         const string & fileName="", const string & fieldName="",
660         const int iterationNumber = -1, const int orderNumber = -1)
661     throw (MEDEXCEPTION);
662   ~FIELD();
663
664   FIELD & operator=(const FIELD &m);
665
666   const FIELD operator+(const FIELD& m) const;
667   const FIELD operator-(const FIELD& m) const;
668   const FIELD operator*(const FIELD& m) const;
669   const FIELD operator/(const FIELD& m) const;
670   const FIELD operator-() const;
671   FIELD& operator+=(const FIELD& m);
672   FIELD& operator-=(const FIELD& m);
673   FIELD& operator*=(const FIELD& m);
674   FIELD& operator/=(const FIELD& m);
675   static FIELD* add(const FIELD& m, const FIELD& n);
676   static FIELD* addDeep(const FIELD& m, const FIELD& n);
677   static FIELD* sub(const FIELD& m, const FIELD& n);
678   static FIELD* subDeep(const FIELD& m, const FIELD& n);
679   static FIELD* mul(const FIELD& m, const FIELD& n);
680   static FIELD* mulDeep(const FIELD& m, const FIELD& n);
681   static FIELD* div(const FIELD& m, const FIELD& n);
682   static FIELD* divDeep(const FIELD& m, const FIELD& n);
683   double normMax() const throw (MEDEXCEPTION);
684   double norm2() const throw (MEDEXCEPTION);
685   void   applyLin(T a, T b);
686   template <T T_function(T)> void applyFunc();
687   void applyPow(T scalar);
688   static FIELD* scalarProduct(const FIELD& m, const FIELD& n, bool deepCheck=false);
689   double normL2(int component, const FIELD<double,FullInterlace> * p_field_volume=NULL) const;
690   double normL2(const FIELD<double,FullInterlace> * p_field_volume=NULL) const;
691   double normL1(int component, const FIELD<double,FullInterlace> * p_field_volume=NULL) const;
692   double normL1(const FIELD<double,FullInterlace> * p_field_volume=NULL) const;
693   FIELD* extract(const SUPPORT *subSupport) const throw (MEDEXCEPTION);
694
695   friend class MED_FIELD_RDONLY_DRIVER21<T>;
696   friend class MED_FIELD_WRONLY_DRIVER21<T>;
697   friend class MED_FIELD_RDONLY_DRIVER22<T>;
698   friend class MED_FIELD_WRONLY_DRIVER22<T>;
699   friend class VTK_FIELD_DRIVER<T>;
700   //friend class MED_FIELD_RDWR_DRIVER  <T>;
701
702   void init ();
703   void rmDriver(int index=0);
704   int  addDriver(driverTypes driverType,
705                  const string & fileName="Default File Name.med",
706                  const string & driverFieldName="Default Field Name",
707                  MED_EN::med_mode_acces access=MED_EN::MED_REMP) ;
708
709   int  addDriver(GENDRIVER & driver);
710
711   void allocValue(const int NumberOfComponents);
712   void allocValue(const int NumberOfComponents, const int LengthValue);
713
714   void deallocValue();
715
716   inline void read(int index=0);
717   inline void read(const GENDRIVER & genDriver);
718   inline void write(int index=0, const string & driverName = "");
719   inline void write(const GENDRIVER &);
720
721   inline void writeAppend(int index=0, const string & driverName = "");
722   inline void writeAppend(const GENDRIVER &);
723
724   inline MEDMEM_Array_  * getArray()        const throw (MEDEXCEPTION);
725   inline ArrayGauss     * getArrayGauss()   const throw (MEDEXCEPTION);
726   inline ArrayNoGauss   * getArrayNoGauss() const throw (MEDEXCEPTION);
727   inline bool            getGaussPresence() const throw (MEDEXCEPTION);
728
729   inline int          getValueLength() const throw (MEDEXCEPTION);
730   inline const T*     getValue()       const throw (MEDEXCEPTION);
731   inline const T*     getRow(int i)    const throw (MEDEXCEPTION);
732   inline const T*     getColumn(int j) const throw (MEDEXCEPTION);
733   inline T            getValueIJ(int i,int j) const throw (MEDEXCEPTION);
734   bool                getValueOnElement(int eltIdInSup,T* retValues) const throw (MEDEXCEPTION);
735
736   inline void setArray(MEDMEM_Array_ *value) throw (MEDEXCEPTION);
737   inline void setValue( T* value) throw (MEDEXCEPTION);
738   inline void setRow( int i, T* value) throw (MEDEXCEPTION);
739   inline void setColumn( int i, T* value) throw (MEDEXCEPTION);
740   inline void setValueIJ(int i, int j, T value) throw (MEDEXCEPTION);
741
742   /*!
743     This fonction feeds the FIELD<double> private attributs _value with the
744     volume of each cells belonging to the argument Support. The field has to be
745     initialised via the constructor FIELD<double>(const SUPPORT * , const int )
746     with Support as SUPPORT argument, 1 has the number of components, and Support
747     has be a SUPPORT on 3D cells. This initialisation could be done by the empty
748     constructor followed by a setSupport and setNumberOfComponents call.
749    */
750   void getVolume() const throw (MEDEXCEPTION) ;
751   /*!
752     This fonction feeds the FIELD<double> private attributs _value with the
753     area of each cells (or faces) belonging to the attribut _support. The field
754     has to be initialised via the constructor FIELD<double>(const SUPPORT * ,
755     const int ) with 1 has the number of components, and _support has be a
756     SUPPORT on 2D cells or 3D faces. This initialisation could be done by the
757     empty constructor followed by a setSupport and setNumberOfComponents call.
758    */
759   void getArea() const throw (MEDEXCEPTION) ;
760   /*!
761     This fonction feeds the FIELD<double> private attributs _value with the
762     length of each segments belonging to the attribut _support. The field has
763     to be initialised via the constructor FIELD<double>(const SUPPORT * ,
764     const int ) with 1 has the number of components, and _support has be a
765     SUPPORT on 3D edges or 2D faces. This initialisation could be done by the
766     empty constructor followed by a setSupport and setNumberOfComponents call.
767    */
768   void getLength() const throw (MEDEXCEPTION) ;
769   /*!
770     This fonction feeds the FIELD<double> private attributs _value with the
771     normal vector of each faces belonging to the attribut _support. The field
772     has to be initialised via the constructor FIELD<double>(const SUPPORT * ,
773     const int ) with the space dimension has the number of components, and
774     _support has be a SUPPORT on 3D or 2D faces. This initialisation could be done
775     by the empty constructor followed by a setSupport and setNumberOfComponents
776     call.
777    */
778   void getNormal() const throw (MEDEXCEPTION) ;
779   /*!
780     This fonction feeds the FIELD<double> private attributs _value with the
781     barycenter of each faces or cells or edges belonging to the attribut _support.
782     The field has to be initialised via the constructor
783     FIELD<double>(const SUPPORT * ,const int ) with the space dimension has the
784     number of components, and _support has be a SUPPORT on 3D cells or 2D faces.
785     This initialisation could be done by the empty constructor followed by a
786     setSupport and setNumberOfComponents call.
787    */
788   void getBarycenter() const throw (MEDEXCEPTION) ;
789
790   typedef void (*myFuncType)(const double *,T*);
791   void fillFromAnalytic(myFuncType f) throw (MEDEXCEPTION);
792 };
793 }
794
795 #include "MEDMEM_DriverFactory.hxx"
796
797 namespace MEDMEM {
798
799 template <class T,class INTERLACING_TAG> T FIELD<T, INTERLACING_TAG>::_scalarForPow=1;
800
801 // --------------------
802 // Implemented Methods
803 // --------------------
804
805 /*!
806   Constructor with no parameter, most of the attribut members are set to NULL.
807 */
808 template <class T, class INTERLACING_TAG>
809 FIELD<T, INTERLACING_TAG>::FIELD():FIELD_()
810 {
811   MESSAGE("Constructeur FIELD sans parametre");
812
813   //INITIALISATION DE _valueType DS LE CONSTRUCTEUR DE FIELD_
814   ASSERT(FIELD_::_valueType == MED_EN::MED_UNDEFINED_TYPE);
815   FIELD_::_valueType=SET_VALUE_TYPE<T>::_valueType;
816
817   //INITIALISATION DE _interlacingType DS LE CONSTRUCTEUR DE FIELD_
818   ASSERT(FIELD_::_interlacingType == MED_EN::MED_UNDEFINED_INTERLACE);
819   FIELD_::_interlacingType=SET_INTERLACING_TYPE<INTERLACING_TAG>::_interlacingType;
820
821   _value = ( ArrayNoGauss * ) NULL;
822 }
823
824 /*!
825   Constructor with parameters such that all attrribut are set but the _value
826   attribut is allocated but not set.
827 */
828 template <class T, class INTERLACING_TAG>
829 FIELD<T, INTERLACING_TAG>::FIELD(const SUPPORT * Support,
830                                     const int NumberOfComponents) throw (MEDEXCEPTION) :
831   FIELD_(Support, NumberOfComponents),_value()
832 {
833   BEGIN_OF("FIELD<T>::FIELD(const SUPPORT * Support, const int NumberOfComponents)");
834   SCRUTE(this);
835
836   //INITIALISATION DE _valueType DS LE CONSTRUCTEUR DE FIELD_
837   ASSERT(FIELD_::_valueType == MED_EN::MED_UNDEFINED_TYPE)
838   FIELD_::_valueType=SET_VALUE_TYPE<T>::_valueType;
839
840   //INITIALISATION DE _interlacingType DS LE CONSTRUCTEUR DE FIELD_
841   ASSERT(FIELD_::_interlacingType == MED_EN::MED_UNDEFINED_INTERLACE)
842   FIELD_::_interlacingType=SET_INTERLACING_TYPE<INTERLACING_TAG>::_interlacingType;
843
844   try {
845     // becarefull about the numbre of gauss point
846     _numberOfValues = Support->getNumberOfElements(MED_EN::MED_ALL_ELEMENTS);
847   }
848   catch (MEDEXCEPTION &ex) {
849     MESSAGE("No value defined ! ("<<ex.what()<<")");
850   }
851   MESSAGE("FIELD : constructeur : "<< _numberOfValues <<" et "<< NumberOfComponents);
852   if (0<_numberOfValues) {
853     _value = new ArrayNoGauss (_numberOfComponents,_numberOfValues);
854     _isRead = true ;
855   }
856
857   END_OF("FIELD<T>::FIELD(const SUPPORT * Support, const int NumberOfComponents)");
858 }
859
860 /*!
861   \if developper
862   \endif
863 */
864 template <class T, class INTERLACING_TAG> void FIELD<T, INTERLACING_TAG>::init ()
865 {
866 }
867
868 /*!
869   Copy constructor.
870 */
871 template <class T, class INTERLACING_TAG> FIELD<T, INTERLACING_TAG>::FIELD(const FIELD & m):
872   FIELD_((FIELD_) m)
873 {
874   MESSAGE("Constructeur FIELD de recopie");
875
876   // RECOPIE PROFOND Rmq from EF
877   if (m._value != NULL)
878     {
879       if ( m.getGaussPresence() )
880         _value = new ArrayGauss( *(dynamic_cast< ArrayGauss * > (m._value) ) ,false);
881       else
882         _value = new ArrayNoGauss( *(dynamic_cast< ArrayNoGauss * > (m._value)) ,false);
883     }
884   else
885     _value = (ArrayNoGauss *) NULL;
886
887   _valueType       = m._valueType;
888   _interlacingType = m._interlacingType;
889   //drivers = m._drivers;
890 }
891
892 /*!
893   \if developper
894   Not implemented.
895   \endif
896 */
897 template <class T, class INTERLACING_TAG>
898 FIELD<T, INTERLACING_TAG> & FIELD<T, INTERLACING_TAG>::operator=(const FIELD &m)
899 {
900   MESSAGE("Appel de FIELD<T>::operator=") ;
901   if ( this == &m) return *this;
902
903   // copy values array
904   FIELD_::operator=(m);  // Driver are ignored & ?copie su pointeur de Support?
905
906   _value           = m._value; //PROBLEME RECOPIE DES POINTEURS PAS COHERENT AVEC LE
907                                //CONSTRUCTEUR PAR RECOPIE
908                                //CF :Commentaire dans MEDMEM_Array 
909   _valueType       = m._valueType;
910   _interlacingType = m._interlacingType;
911 }
912
913 /*!
914      Overload addition operator.
915      This operation is authorized only for compatible fields that have the same support.
916      The compatibility checking includes equality tests of the folowing data members:\n
917      - _support
918      - _numberOfComponents
919      - _numberOfValues
920      - _componentsTypes
921      - _MEDComponentsUnits.
922
923      The data members of the returned field are initialized, based on the first field, except for the name,
924      which is the combination of the two field's names and the operator.
925      Advised Utilisation in C++ : <tt> FIELD<T> c = a + b; </tt> \n
926      In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
927      When using python, this operator calls the copy constructor in any case.
928      The user has to be aware that when using operator + in associatives expressions like
929      <tt> a = b + c + d +e; </tt> \n
930      no optimisation is performed : the evaluation of last expression requires the construction of
931      3 temporary fields.
932 */
933 template <class T, class INTERLACING_TAG>
934 const FIELD<T, INTERLACING_TAG> FIELD<T, INTERLACING_TAG>::operator+(const FIELD & m) const
935 {
936     BEGIN_OF("FIELD<T>::operator+(const FIELD & m)");
937     FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
938
939     // Creation of the result - memory is allocated by FIELD constructor
940     FIELD<T, INTERLACING_TAG> result(this->getSupport(),this->getNumberOfComponents());
941     //result._operation(*this,m,mode,"+"); // perform Atribute's initialization & addition
942     result._operationInitialize(*this,m,"+"); // perform Atribute's initialization
943     result._add_in_place(*this,m); // perform addition
944
945     END_OF("FIELD<T>::operator+(const FIELD & m)");
946     return result;
947 }
948
949 /*!  Overloaded Operator +=
950  *   Operations are directly performed in the first field's array.
951  *   This operation is authorized only for compatible fields that have the same support.
952  */
953 template <class T, class INTERLACING_TAG>
954 FIELD<T, INTERLACING_TAG>& FIELD<T, INTERLACING_TAG>::operator+=(const FIELD & m)
955 {
956     BEGIN_OF("FIELD<T>::operator+=(const FIELD & m)");
957     FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
958
959     const T* value1=m.getValue(); // get pointers to the values we are adding
960
961     // get a non const pointer to the inside array of values and perform operation
962     T * value=const_cast<T *> (getValue());
963     const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
964     const T* endV=value+size; // pointer to the end of value
965     for(;value!=endV; value1++,value++)
966         *value += *value1;
967     END_OF("FIELD<T>::operator+=(const FIELD & m)");
968     return *this;
969 }
970
971
972 /*! Addition of fields. Static member function.
973  *  The function return a pointer to a new created field that holds the addition.
974  *  Data members are checked for compatibility and initialized.
975  *  The user is in charge of memory deallocation.
976  */
977 template <class T, class INTERLACING_TAG>
978 FIELD<T, INTERLACING_TAG>* FIELD<T, INTERLACING_TAG>::add(const FIELD& m, const FIELD& n)
979 {
980     BEGIN_OF("FIELD<T>::add(const FIELD & m, const FIELD& n)");
981     FIELD_::_checkFieldCompatibility(m, n); // may throw exception
982
983     // Creation of a new field
984     FIELD<T, INTERLACING_TAG>* result = new FIELD<T, INTERLACING_TAG>(m.getSupport(),
985                                                                       m.getNumberOfComponents());
986     result->_operationInitialize(m,n,"+"); // perform Atribute's initialization
987     result->_add_in_place(m,n); // perform addition
988
989     END_OF("FIELD<T>::add(const FIELD & m, const FIELD& n)");
990     return result;
991 }
992
993 /*! Same as add method except that field check is deeper.
994  */
995 template <class T, class INTERLACING_TAG>
996 FIELD<T, INTERLACING_TAG>* FIELD<T, INTERLACING_TAG>::addDeep(const FIELD& m, const FIELD& n)
997 {
998     BEGIN_OF("FIELD<T>::addDeep(const FIELD & m, const FIELD& n)");
999     FIELD_::_deepCheckFieldCompatibility(m, n); // may throw exception
1000
1001     // Creation of a new field
1002     FIELD<T, INTERLACING_TAG>* result = new FIELD<T, INTERLACING_TAG>(m.getSupport(),
1003                                                                       m.getNumberOfComponents());
1004     result->_operationInitialize(m,n,"+"); // perform Atribute's initialization
1005     result->_add_in_place(m,n); // perform addition
1006
1007     END_OF("FIELD<T>::addDeep(const FIELD & m, const FIELD& n)");
1008     return result;
1009 }
1010
1011 /*!
1012      Overload substraction operator.
1013      This operation is authorized only for compatible fields that have the same support.
1014      The compatibility checking includes equality tests of the folowing data members:\n
1015      - _support
1016      - _numberOfComponents
1017      - _numberOfValues
1018      - _componentsTypes
1019      - _MEDComponentsUnits.
1020
1021      The data members of the returned field are initialized, based on the first field, except for the name,
1022      which is the combination of the two field's names and the operator.
1023      Advised Utilisation in C++ : <tt> FIELD<T> c = a - b; </tt> \n
1024      In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
1025      When using python, this operator calls the copy constructor in any case.
1026      The user has to be aware that when using operator - in associatives expressions like
1027      <tt> a = b - c - d -e; </tt> \n
1028      no optimisation is performed : the evaluation of last expression requires the construction of
1029      3 temporary fields.
1030 */
1031 template <class T, class INTERLACING_TAG>
1032 const FIELD<T, INTERLACING_TAG> FIELD<T, INTERLACING_TAG>::operator-(const FIELD & m) const
1033 {
1034     BEGIN_OF("FIELD<T>::operator-(const FIELD & m)");
1035     FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
1036
1037     // Creation of the result - memory is allocated by FIELD constructor
1038     FIELD<T, INTERLACING_TAG> result(this->getSupport(),this->getNumberOfComponents());
1039     //result._operation(*this,m,mode,"-"); // perform Atribute's initialization & substraction
1040     result._operationInitialize(*this,m,"-"); // perform Atribute's initialization
1041     result._sub_in_place(*this,m); // perform substracion
1042
1043     END_OF("FIELD<T>::operator-(const FIELD & m)");
1044     return result;
1045 }
1046
1047 template <class T, class INTERLACING_TAG>
1048 const FIELD<T, INTERLACING_TAG> FIELD<T, INTERLACING_TAG>::operator-() const
1049 {
1050     BEGIN_OF("FIELD<T>::operator-()");
1051
1052     // Creation of the result - memory is allocated by FIELD constructor
1053     FIELD<T, INTERLACING_TAG> result(this->getSupport(),this->getNumberOfComponents());
1054     // Atribute's initialization
1055     result.setName("- "+getName());
1056     result.setComponentsNames(getComponentsNames());
1057     // not yet implemented    setComponentType(getComponentType());
1058     result.setComponentsDescriptions(getComponentsDescriptions());
1059     result.setMEDComponentsUnits(getMEDComponentsUnits());
1060     result.setComponentsUnits(getComponentsUnits());
1061     result.setIterationNumber(getIterationNumber());
1062     result.setTime(getTime());
1063     result.setOrderNumber(getOrderNumber());
1064
1065     const T* value1=getValue();
1066     // get a non const pointer to the inside array of values and perform operation
1067     T * value=const_cast<T *> (result.getValue());
1068     const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
1069     const T* endV=value+size; // pointer to the end of value
1070
1071     for(;value!=endV; value1++,value++)
1072         *value = -(*value1);
1073     END_OF("FIELD<T>::operator-=(const FIELD & m)");
1074     return result;
1075 }
1076
1077 /*!  Overloaded Operator -=
1078  *   Operations are directly performed in the first field's array.
1079  *   This operation is authorized only for compatible fields that have the same support.
1080  */
1081 template <class T, class INTERLACING_TAG>
1082 FIELD<T, INTERLACING_TAG>& FIELD<T, INTERLACING_TAG>::operator-=(const FIELD & m)
1083 {
1084     BEGIN_OF("FIELD<T>::operator-=(const FIELD & m)");
1085     FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
1086
1087     const T* value1=m.getValue();
1088
1089     // get a non const pointer to the inside array of values and perform operation
1090     T * value=const_cast<T *> (getValue());
1091     const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
1092     const T* endV=value+size; // pointer to the end of value
1093
1094     for(;value!=endV; value1++,value++)
1095         *value -= *value1;
1096
1097     END_OF("FIELD<T>::operator-=(const FIELD & m)");
1098     return *this;
1099 }
1100
1101
1102 /*! Substraction of fields. Static member function.
1103  *  The function return a pointer to a new created field that holds the substraction.
1104  *  Data members are checked for compatibility and initialized.
1105  *  The user is in charge of memory deallocation.
1106  */
1107 template <class T, class INTERLACING_TAG>
1108 FIELD<T, INTERLACING_TAG>* FIELD<T, INTERLACING_TAG>::sub(const FIELD& m, const FIELD& n)
1109 {
1110     BEGIN_OF("FIELD<T>::sub(const FIELD & m, const FIELD& n)");
1111     FIELD_::_checkFieldCompatibility(m, n); // may throw exception
1112
1113     // Creation of a new field
1114     FIELD<T, INTERLACING_TAG>* result = new FIELD<T, INTERLACING_TAG>(m.getSupport(),
1115                                                                       m.getNumberOfComponents());
1116     result->_operationInitialize(m,n,"-"); // perform Atribute's initialization
1117     result->_sub_in_place(m,n); // perform substraction
1118
1119     END_OF("FIELD<T>::sub(const FIELD & m, const FIELD& n)");
1120     return result;
1121 }
1122
1123 /*! Same as sub method except that field check is deeper.
1124  */
1125 template <class T, class INTERLACING_TAG>
1126 FIELD<T, INTERLACING_TAG>* FIELD<T, INTERLACING_TAG>::subDeep(const FIELD& m, const FIELD& n)
1127 {
1128     BEGIN_OF("FIELD<T>::subDeep(const FIELD & m, const FIELD& n)");
1129     FIELD_::_deepCheckFieldCompatibility(m, n); // may throw exception
1130
1131     // Creation of a new field
1132     FIELD<T, INTERLACING_TAG>* result = new FIELD<T, INTERLACING_TAG>(m.getSupport(),
1133                                                                       m.getNumberOfComponents());
1134     result->_operationInitialize(m,n,"-"); // perform Atribute's initialization
1135     result->_sub_in_place(m,n); // perform substraction
1136
1137     END_OF("FIELD<T>::subDeep(const FIELD & m, const FIELD& n)");
1138     return result;
1139 }
1140
1141 /*!
1142      Overload multiplication operator.
1143      This operation is authorized only for compatible fields that have the same support.
1144      The compatibility checking includes equality tests of the folowing data members:\n
1145      - _support
1146      - _numberOfComponents
1147      - _numberOfValues
1148      - _componentsTypes
1149      - _MEDComponentsUnits.
1150
1151      The data members of the returned field are initialized, based on the first field, except for the name,
1152      which is the combination of the two field's names and the operator.
1153      Advised Utilisation in C++ : <tt> FIELD<T> c = a * b; </tt> \n
1154      In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
1155      When using python, this operator calls the copy constructor in any case.
1156      The user has to be aware that when using operator * in associatives expressions like
1157      <tt> a = b * c * d *e; </tt> \n
1158      no optimisation is performed : the evaluation of last expression requires the construction of
1159      3 temporary fields.
1160 */
1161 template <class T, class INTERLACING_TAG>
1162 const FIELD<T, INTERLACING_TAG> FIELD<T, INTERLACING_TAG>::operator*(const FIELD & m) const
1163 {
1164     BEGIN_OF("FIELD<T>::operator*(const FIELD & m)");
1165     FIELD_::_checkFieldCompatibility(*this, m, false); // may throw exception
1166
1167     // Creation of the result - memory is allocated by FIELD constructor
1168     FIELD<T, INTERLACING_TAG> result(this->getSupport(),this->getNumberOfComponents());
1169     //result._operation(*this,m,mode,"*"); // perform Atribute's initialization & multiplication
1170     result._operationInitialize(*this,m,"*"); // perform Atribute's initialization
1171     result._mul_in_place(*this,m); // perform multiplication
1172
1173     END_OF("FIELD<T>::operator*(const FIELD & m)");
1174     return result;
1175 }
1176
1177 /*!  Overloaded Operator *=
1178  *   Operations are directly performed in the first field's array.
1179  *   This operation is authorized only for compatible fields that have the same support.
1180  */
1181 template <class T, class INTERLACING_TAG>
1182 FIELD<T, INTERLACING_TAG>& FIELD<T, INTERLACING_TAG>::operator*=(const FIELD & m)
1183 {
1184     BEGIN_OF("FIELD<T>::operator*=(const FIELD & m)");
1185     FIELD_::_checkFieldCompatibility(*this, m, false); // may throw exception
1186
1187     const T* value1=m.getValue();
1188
1189     // get a non const pointer to the inside array of values and perform operation
1190     T * value=const_cast<T *> (getValue());
1191     const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
1192     const T* endV=value+size; // pointer to the end of value
1193
1194     for(;value!=endV; value1++,value++)
1195         *value *= *value1;
1196
1197     END_OF("FIELD<T>::operator*=(const FIELD & m)");
1198     return *this;
1199 }
1200
1201
1202 /*! Multiplication of fields. Static member function.
1203  *  The function return a pointer to a new created field that holds the multiplication.
1204  *  Data members are checked for compatibility and initialized.
1205  *  The user is in charge of memory deallocation.
1206  */
1207 template <class T, class INTERLACING_TAG>
1208 FIELD<T, INTERLACING_TAG>* FIELD<T, INTERLACING_TAG>::mul(const FIELD& m, const FIELD& n)
1209 {
1210     BEGIN_OF("FIELD<T>::mul(const FIELD & m, const FIELD& n)");
1211     FIELD_::_checkFieldCompatibility(m, n, false); // may throw exception
1212
1213     // Creation of a new field
1214     FIELD<T, INTERLACING_TAG>* result = new FIELD<T, INTERLACING_TAG>(m.getSupport(),
1215                                                                       m.getNumberOfComponents());
1216     result->_operationInitialize(m,n,"*"); // perform Atribute's initialization
1217     result->_mul_in_place(m,n); // perform multiplication
1218
1219     END_OF("FIELD<T>::mul(const FIELD & m, const FIELD& n)");
1220     return result;
1221 }
1222
1223 /*! Same as mul method except that field check is deeper.
1224  */
1225 template <class T, class INTERLACING_TAG>
1226 FIELD<T, INTERLACING_TAG>* FIELD<T, INTERLACING_TAG>::mulDeep(const FIELD& m, const FIELD& n)
1227 {
1228     BEGIN_OF("FIELD<T>::mulDeep(const FIELD & m, const FIELD& n)");
1229     FIELD_::_deepCheckFieldCompatibility(m, n, false); // may throw exception
1230
1231     // Creation of a new field
1232     FIELD<T, INTERLACING_TAG>* result = new FIELD<T,INTERLACING_TAG>(m.getSupport(),
1233                                                                      m.getNumberOfComponents());
1234     result->_operationInitialize(m,n,"*"); // perform Atribute's initialization
1235     result->_mul_in_place(m,n); // perform multiplication
1236
1237     END_OF("FIELD<T>::mulDeep(const FIELD & m, const FIELD& n)");
1238     return result;
1239 }
1240
1241 /*!
1242      Overload division operator.
1243      This operation is authorized only for compatible fields that have the same support.
1244      The compatibility checking includes equality tests of the folowing data members:\n
1245      - _support
1246      - _numberOfComponents
1247      - _numberOfValues
1248      - _componentsTypes
1249      - _MEDComponentsUnits.
1250
1251      The data members of the returned field are initialized, based on the first field, except for the name,
1252      which is the combination of the two field's names and the operator.
1253      Advised Utilisation in C++ : <tt> FIELD<T> c = a / b; </tt> \n
1254      In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
1255      When using python, this operator calls the copy constructor in any case.
1256      The user has to be aware that when using operator / in associatives expressions like
1257      <tt> a = b / c / d /e; </tt> \n
1258      no optimisation is performed : the evaluation of last expression requires the construction of
1259      3 temporary fields.
1260 */
1261 template <class T, class INTERLACING_TAG>
1262 const FIELD<T, INTERLACING_TAG> FIELD<T, INTERLACING_TAG>::operator/(const FIELD & m) const
1263 {
1264     BEGIN_OF("FIELD<T>::operator/(const FIELD & m)");
1265     FIELD_::_checkFieldCompatibility(*this, m, false); // may throw exception
1266
1267     // Creation of the result - memory is allocated by FIELD constructor
1268     FIELD<T, INTERLACING_TAG> result(this->getSupport(),this->getNumberOfComponents());
1269     //result._operation(*this,m,mode,"/"); // perform Atribute's initialization & division
1270     result._operationInitialize(*this,m,"/"); // perform Atribute's initialization
1271     result._div_in_place(*this,m); // perform division
1272
1273     END_OF("FIELD<T>::operator/(const FIELD & m)");
1274     return result;
1275 }
1276
1277
1278 /*!  Overloaded Operator /=
1279  *   Operations are directly performed in the first field's array.
1280  *   This operation is authorized only for compatible fields that have the same support.
1281  */
1282 template <class T, class INTERLACING_TAG>
1283 FIELD<T, INTERLACING_TAG>& FIELD<T, INTERLACING_TAG>::operator/=(const FIELD & m)
1284 {
1285     BEGIN_OF("FIELD<T>::operator/=(const FIELD & m)");
1286     FIELD_::_checkFieldCompatibility(*this, m, false); // may throw exception
1287
1288     const T* value1=m.getValue(); // get pointers to the values we are adding
1289
1290     // get a non const pointer to the inside array of values and perform operation
1291     T * value=const_cast<T *> (getValue());
1292     const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
1293     const T* endV=value+size; // pointer to the end of value
1294
1295     for(;value!=endV; value1++,value++)
1296         *value /= *value1;
1297
1298     END_OF("FIELD<T>::operator/=(const FIELD & m)");
1299     return *this;
1300 }
1301
1302
1303 /*! Division of fields. Static member function.
1304  *  The function return a pointer to a new created field that holds the division.
1305  *  Data members are checked for compatibility and initialized.
1306  *  The user is in charge of memory deallocation.
1307  */
1308 template <class T, class INTERLACING_TAG>
1309 FIELD<T, INTERLACING_TAG>* FIELD<T, INTERLACING_TAG>::div(const FIELD& m, const FIELD& n)
1310 {
1311     BEGIN_OF("FIELD<T>::div(const FIELD & m, const FIELD& n)");
1312     FIELD_::_checkFieldCompatibility(m, n, false); // may throw exception
1313
1314     // Creation of a new field
1315     FIELD<T, INTERLACING_TAG>* result = new FIELD<T, INTERLACING_TAG>(m.getSupport(),
1316                                                                       m.getNumberOfComponents());
1317     result->_operationInitialize(m,n,"/"); // perform Atribute's initialization
1318     result->_div_in_place(m,n); // perform division
1319
1320     END_OF("FIELD<T>::div(const FIELD & m, const FIELD& n)");
1321     return result;
1322 }
1323
1324 /*! Same as div method except that field check is deeper.
1325  */
1326 template <class T,class INTERLACING_TAG>
1327 FIELD<T, INTERLACING_TAG>* FIELD<T, INTERLACING_TAG>::divDeep(const FIELD& m, const FIELD& n)
1328 {
1329   BEGIN_OF("FIELD<T>::divDeep(const FIELD & m, const FIELD& n)");
1330   FIELD_::_deepCheckFieldCompatibility(m, n, false); // may throw exception
1331
1332   // Creation of a new field
1333   FIELD<T, INTERLACING_TAG>* result = new FIELD<T, INTERLACING_TAG>(m.getSupport(),
1334                                                                     m.getNumberOfComponents());
1335   result->_operationInitialize(m,n,"/"); // perform Atribute's initialization
1336   result->_div_in_place(m,n); // perform division
1337
1338   END_OF("FIELD<T>::divDeep(const FIELD & m, const FIELD& n)");
1339   return result;
1340 }
1341
1342 /*!
1343   \if developper
1344   This internal method initialize the members of a new field created to hold the result of the operation Op .
1345   Initialization is based on the first field, except for the name, which is the combination of the two field's names
1346   and the operator.
1347   \endif
1348 */
1349 template <class T, class INTERLACING_TAG>
1350 void FIELD<T, INTERLACING_TAG>::_operationInitialize(const FIELD& m,const FIELD& n, char* Op)
1351 {
1352     MESSAGE("Appel methode interne " << Op);
1353
1354     // Atribute's initialization (copy of the first field's attributes)
1355     // Other data members (_support, _numberOfValues) are initialized in the field's constr.
1356     setName(m.getName()+" "+Op+" "+n.getName());
1357     setComponentsNames(m.getComponentsNames());
1358     // not yet implemented    setComponentType(m.getComponentType());
1359     setComponentsDescriptions(m.getComponentsDescriptions());
1360     setMEDComponentsUnits(m.getMEDComponentsUnits());
1361
1362     // The following data member may differ from field m to n.
1363     // The initialization is done based on the first field.
1364
1365     if(m.getComponentsUnits() != NULL)
1366       setComponentsUnits(m.getComponentsUnits());
1367     else
1368       _componentsUnits = (UNIT *) NULL;
1369
1370     setIterationNumber(m.getIterationNumber());
1371     setTime(m.getTime());
1372     setOrderNumber(m.getOrderNumber());
1373 }
1374
1375
1376 /*!
1377   \if developper
1378   Internal method called by FIELD<T>::operator+ and FIELD<T>::add to perform addition "in place".
1379   This method is applied to a just created field with medModeSwitch mode.
1380   For this reason, the alternate mode doesn't need to be set to 0 after performing operation :
1381   it doesn't exist!
1382   \endif
1383 */
1384 template <class T, class INTERLACING_TAG>
1385 void FIELD<T, INTERLACING_TAG>::_add_in_place(const FIELD& m,const FIELD& n)
1386 {
1387     // get pointers to the values we are adding
1388     const T* value1=m.getValue();
1389     const T* value2=n.getValue();
1390     // get a non const pointer to the inside array of values and perform operation
1391     T * value=const_cast<T *> (getValue());
1392
1393     const int size=getNumberOfValues()*getNumberOfComponents();
1394     SCRUTE(size);
1395     const T* endV1=value1+size;
1396     for(;value1!=endV1; value1++,value2++,value++)
1397         *value=(*value1)+(*value2);
1398 }
1399
1400 /*!
1401   \if developper
1402   Internal method called by FIELD<T>::operator- and FIELD<T>::sub to perform substraction "in place".
1403   This method is applied to a just created field with medModeSwitch mode.
1404   For this reason, the alternate mode doesn't need to be set to 0 after performing operation :
1405   it doesn't exist!
1406   \endif
1407 */
1408 template <class T, class INTERLACING_TAG>
1409 void FIELD<T, INTERLACING_TAG>::_sub_in_place(const FIELD& m,const FIELD& n)
1410 {
1411     // get pointers to the values we are adding
1412     const T* value1=m.getValue();
1413     const T* value2=n.getValue();
1414     // get a non const pointer to the inside array of values and perform operation
1415     T * value=const_cast<T *> (getValue());
1416
1417     const int size=getNumberOfValues()*getNumberOfComponents();
1418     SCRUTE(size);
1419     const T* endV1=value1+size;
1420     for(;value1!=endV1; value1++,value2++,value++)
1421         *value=(*value1)-(*value2);
1422 }
1423
1424 /*!
1425   \if developper
1426   Internal method called by FIELD<T>::operator* and FIELD<T>::mul to perform multiplication "in place".
1427   This method is applied to a just created field with medModeSwitch mode.
1428   For this reason, the alternate mode doesn't need to be set to 0 after performing operation :
1429   it doesn't exist!
1430   \endif
1431 */
1432 template <class T, class INTERLACING_TAG>
1433 void FIELD<T, INTERLACING_TAG>::_mul_in_place(const FIELD& m,const FIELD& n)
1434 {
1435     // get pointers to the values we are adding
1436     const T* value1=m.getValue();
1437     const T* value2=n.getValue();
1438     // get a non const pointer to the inside array of values and perform operation
1439     T * value=const_cast<T *> (getValue());
1440
1441     const int size=getNumberOfValues()*getNumberOfComponents();
1442     SCRUTE(size);
1443     const T* endV1=value1+size;
1444     for(;value1!=endV1; value1++,value2++,value++)
1445         *value=(*value1)*(*value2);
1446 }
1447
1448 /*!
1449   \if developper
1450   Internal method called by FIELD<T>::operator/ and FIELD<T>::div to perform division "in place".
1451   This method is applied to a just created field with medModeSwitch mode.
1452   For this reason, the alternate mode doesn't need to be set to 0 after performing operation :
1453   it doesn't exist!
1454   \endif
1455 */
1456 template <class T, class INTERLACING_TAG>
1457 void FIELD<T, INTERLACING_TAG>::_div_in_place(const FIELD& m,const FIELD& n) throw (MEDEXCEPTION)
1458 {
1459     // get pointers to the values we are adding
1460     const T* value1=m.getValue();
1461     const T* value2=n.getValue();
1462     // get a non const pointer to the inside array of values and perform operation
1463     T * value=const_cast<T *> (getValue());
1464
1465     const int size=getNumberOfValues()*getNumberOfComponents();
1466     SCRUTE(size);
1467     const T* endV1=value1+size;
1468     for(;value1!=endV1; value1++,value2++,value++){
1469       if ( *value2 == 0 ) { // FAIRE PLUTOT UN TRY CATCH Rmq from EF
1470           string diagnosis;
1471           diagnosis="FIELD<T,INTERLACING_TAG>::_div_in_place(...) : Divide by zero !";
1472           throw MEDEXCEPTION(diagnosis.c_str());
1473         }
1474         *value=(*value1)/(*value2);
1475     }
1476 }
1477
1478 /*!  Return Max Norm
1479  */
1480 template <class T, class INTERLACIN_TAG> double FIELD<T, INTERLACIN_TAG>::normMax() const throw (MEDEXCEPTION)
1481 {
1482     const T* value=getValue(); // get pointer to the values
1483     const int size=getNumberOfValues()*getNumberOfComponents();
1484     if (size <= 0) // Size of array has to be strictly positive
1485     {
1486         string diagnosis;
1487         diagnosis="FIELD<T,INTERLACIN_TAG>::normMax() : cannot compute the norm of "+getName()+
1488             " : it size is non positive!";
1489         throw MEDEXCEPTION(diagnosis.c_str());
1490     }
1491     const T* lastvalue=value+size; // get pointer just after last value
1492     const T* pMax=value; // pointer to the max value
1493     const T* pMin=value; // pointer to the min value
1494
1495     // get pointers to the max & min value of array
1496     while ( ++value != lastvalue )
1497     {
1498         if ( *pMin > *value )
1499             pMin=value;
1500         if ( *pMax < *value )
1501             pMax=value;
1502     }
1503
1504     T Max= *pMax>(T) 0 ? *pMax : -*pMax; // Max=abs(*pMax)
1505     T Min= *pMin>(T) 0 ? *pMin : -*pMin; // Min=abs(*pMin)
1506
1507     return Max>Min ? static_cast<double>(Max) : static_cast<double>(Min);
1508 }
1509
1510 /*!  Return Euclidien norm
1511  */
1512 template <class T, class INTERLACIN_TAG> double FIELD<T, INTERLACIN_TAG>::norm2() const throw (MEDEXCEPTION)
1513 {
1514     const T* value=this->getValue(); // get const pointer to the values
1515     const int size=getNumberOfValues()*getNumberOfComponents(); // get size of array
1516     if (size <= 0) // Size of array has to be strictly positive
1517     {
1518         string diagnosis;
1519         diagnosis="FIELD<T,INTERLACIN_TAG>::norm2() : cannot compute the norm of "+getName()+
1520             " : it size is non positive!";
1521         throw MEDEXCEPTION(diagnosis.c_str());
1522     }
1523     const T* lastvalue=value+size; // point just after last value
1524
1525     T result((T)0); // init
1526     for( ; value!=lastvalue ; ++value)
1527         result += (*value) * (*value);
1528
1529     return std::sqrt(static_cast<double> (result));
1530 }
1531
1532
1533 /*!  Apply to each (scalar) field component the template parameter T_function,
1534  *   which is a pointer to function.
1535  *   Since the pointer is known at compile time, the function is inlined into the inner loop!
1536  *   calculation is done "in place".
1537  *   Use examples :
1538  *
1539  *   \code  myField.applyFunc<std::sqrt>();  // apply sqare root function \endcode
1540  *     \code myField.applyFunc<myFunction>(); // apply your own created function \endcode
1541  */
1542 template <class T, class INTERLACIN_TAG> template <T T_function(T)>
1543 void FIELD<T, INTERLACIN_TAG>::applyFunc()
1544 {
1545   // get a non const pointer to the inside array of values and perform operation
1546     T * value=const_cast<T *> (getValue());
1547     const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
1548
1549     if (size>0) // for a negative size, there is nothing to do
1550     {
1551         const T* lastvalue=value+size; // pointer to the end of value
1552         for(;value!=lastvalue; ++value) // apply linear transformation
1553             *value = T_function(*value);
1554     }
1555 }
1556
1557 template <class T, class INTERLACIN_TAG> T FIELD<T, INTERLACIN_TAG>::pow(T x)
1558 {
1559   return (T)::pow(x,FIELD<T, INTERLACIN_TAG>::_scalarForPow);
1560 }
1561
1562 /*!  Apply to each (scalar) field component the math function pow.
1563  *   calculation is done "in place".
1564  *   Use examples :
1565  *
1566  *   \code  myField.applyFunc<std::sqrt>();  // apply sqare root function \endcode
1567  *     \code myField.applyFunc<myFunction>(); // apply your own created function \endcode
1568  */
1569 template <class T, class INTERLACIN_TAG> void FIELD<T, INTERLACIN_TAG>::applyPow(T scalar)
1570 {
1571   FIELD<T, INTERLACIN_TAG>::_scalarForPow=scalar;
1572   applyFunc<FIELD<T, INTERLACIN_TAG>::pow>();
1573 }
1574
1575 /*!  Apply to each (scalar) field component the linear function x -> ax+b.
1576  *   calculation is done "in place".
1577  */
1578 template <class T, class INTERLACIN_TAG> void FIELD<T, INTERLACIN_TAG>::applyLin(T a, T b)
1579 {
1580     // get a non const pointer to the inside array of values and perform operation in place
1581     T * value=const_cast<T *> (getValue());
1582     const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
1583
1584     if (size>0) // for a negative size, there is nothing to do
1585     {
1586         const T* lastvalue=value+size; // pointer to the end of value
1587         for(;value!=lastvalue; ++value) // apply linear transformation
1588             *value = a*(*value)+b;
1589     }
1590 }
1591
1592
1593 /*!
1594  *   Return a pointer to a new field that holds the scalar product. Static member function.
1595  *   This operation is authorized only for compatible fields that have the same support.
1596  *   The compatibility checking includes equality tests of the folowing data members:\n
1597  *   - _support
1598  *   - _numberOfComponents
1599  *   - _numberOfValues
1600  *   - _componentsTypes
1601  *   - _MEDComponentsUnits.
1602  *   Data members are initialized.
1603  *   The new field point to the same support and has one component.
1604  *   Each value of it is the scalar product of the two argument's fields.
1605  *   The user is in charge of memory deallocation.
1606  */
1607 template <class T, class INTERLACING_TAG>
1608 FIELD<T, INTERLACING_TAG>*
1609 FIELD<T, INTERLACING_TAG>::scalarProduct(const FIELD & m, const FIELD & n, bool deepCheck)
1610 {
1611     if(!deepCheck)
1612       FIELD_::_checkFieldCompatibility( m, n, false); // may throw exception
1613     else
1614       FIELD_::_deepCheckFieldCompatibility(m, n, false);
1615
1616     // we need a MED_FULL_INTERLACE representation of m & n to compute the scalar product
1617     // result type imply INTERLACING_TAG=FullInterlace for m & n
1618
1619     const int numberOfElements=m.getNumberOfValues(); // strictly positive
1620     const int NumberOfComponents=m.getNumberOfComponents(); // strictly positive
1621
1622     // Creation & init of a the result field on the same support, with one component
1623     // You have to be careful about the interlacing mode, because in the computation step,
1624     // it seems to assume the the interlacing mode is the FullInterlacing
1625
1626     FIELD<T, INTERLACING_TAG>* result = new FIELD<T, INTERLACING_TAG>(m.getSupport(),1);
1627     result->setName( "scalarProduct ( " + m.getName() + " , " + n.getName() + " )" );
1628     result->setIterationNumber(m.getIterationNumber());
1629     result->setTime(m.getTime());
1630     result->setOrderNumber(m.getOrderNumber());
1631
1632     const T* value1=m.getValue(); // get const pointer to the values
1633     const T* value2=n.getValue(); // get const pointer to the values
1634     // get a non const pointer to the inside array of values and perform operation
1635     T * value=const_cast<T *> (result->getValue());
1636
1637     const T* lastvalue=value+numberOfElements; // pointing just after last value of result
1638     for ( ; value!=lastvalue ; ++value ) // loop on all elements
1639     {
1640         *value=(T)0; // initialize value
1641         const T* endofRow=value1+NumberOfComponents; // pointing just after end of row
1642         for ( ; value1 != endofRow; ++value1, ++value2) // computation of dot product
1643             *value += (*value1) * (*value2);
1644     }
1645     return result;
1646 }
1647
1648 /*!  Return L2 Norm  of the field's component.
1649  *   Cannot be applied to a field with a support on nodes.
1650  *   If the optional p_field_volume argument is furnished, the volume is not re-calculated.
1651  */
1652 template <class T, class INTERLACING_TAG>
1653 double FIELD<T, INTERLACING_TAG>::normL2(int component,
1654                                          const FIELD<double, FullInterlace> * p_field_volume) const
1655 {
1656     _checkNormCompatibility(p_field_volume); // may throw exception
1657     if ( component<1 || component>getNumberOfComponents() )
1658         throw MEDEXCEPTION(STRING("FIELD<T>::normL2() : The component argument should be between 1 and the number of components"));
1659
1660     const FIELD<double, FullInterlace> * p_field_size=p_field_volume;
1661     if(!p_field_volume) // if the user don't supply the volume
1662         p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
1663
1664     // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
1665     const double* vol=p_field_size->getValue();
1666     // Il n'est vraiment pas optimal de mixer des champs dans des modes d'entrelacement
1667     // different juste pour le calcul
1668  
1669     const T * value     = NULL;
1670     ArrayNo * myArray   = NULL;
1671     if ( getInterlacingType() == MED_EN::MED_NO_INTERLACE )
1672       value = getValue();
1673     else {
1674       myArray = ArrayConvert( *( dynamic_cast< ArrayFull * > ( getArrayNoGauss() ) ));
1675       value   = myArray->getPtr();
1676     }
1677
1678     const T* lastvalue=value+getNumberOfValues(); // pointing just after the end of column
1679
1680     double integrale=0.0;
1681     double totVol=0.0;
1682     for (; value!=lastvalue ; ++value ,++vol)
1683     {
1684         integrale += static_cast<double>((*value) * (*value)) * (*vol);
1685         totVol+=*vol;
1686     }
1687
1688     if(!p_field_volume) // if the user didn't supply the volume
1689         delete p_field_size; // delete temporary volume field
1690     if ( getInterlacingType() == MED_EN::MED_FULL_INTERLACE ) delete myArray;
1691     if( totVol <= 0)
1692         throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
1693
1694     return integrale/totVol;
1695 }
1696
1697 /*!  Return L2 Norm  of the field.
1698  *   Cannot be applied to a field with a support on nodes.
1699  *   If the optional p_field_volume argument is furnished, the volume is not re-calculated.
1700  */
1701 template <class T, class INTERLACING_TAG>
1702 double FIELD<T, INTERLACING_TAG>::normL2(const FIELD<double, FullInterlace> * p_field_volume) const
1703 {
1704     _checkNormCompatibility(p_field_volume); // may throw exception
1705     const FIELD<double, FullInterlace> * p_field_size=p_field_volume;
1706     if(!p_field_volume) // if the user don't supply the volume
1707         p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
1708
1709     // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
1710     const double* vol=p_field_size->getValue();
1711     const double* lastvol=vol+getNumberOfValues(); // pointing just after the end of vol
1712
1713     const T * value     = NULL;
1714     ArrayNo * myArray   = NULL;
1715     if ( getInterlacingType() == MED_EN::MED_NO_INTERLACE )
1716       value = getValue();
1717     else {
1718       myArray = ArrayConvert( *( dynamic_cast< ArrayFull * > ( getArrayNoGauss() ) ));
1719       value   = myArray->getPtr();
1720     }
1721
1722     double totVol=0.0;
1723     const double* p_vol=vol;
1724     for (p_vol=vol; p_vol!=lastvol ; ++p_vol) // calculate total volume
1725         totVol+=*p_vol;
1726
1727     double integrale=0.0;
1728     for (int i=1; i<=getNumberOfComponents(); ++i) // compute integral on all components
1729         for (p_vol=vol; p_vol!=lastvol ; ++value ,++p_vol)
1730             integrale += static_cast<double>((*value) * (*value)) * (*p_vol);
1731
1732     if(!p_field_volume) // if the user didn't supply the volume
1733         delete p_field_size; // delete temporary volume field
1734     if ( getInterlacingType() == MED_EN::MED_FULL_INTERLACE ) delete myArray;
1735     if( totVol <= 0)
1736         throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
1737
1738     return integrale/totVol;
1739 }
1740
1741 /*!  Return L1 Norm  of the field's component.
1742  *   Cannot be applied to a field with a support on nodes.
1743  *   If the optional p_field_volume argument is furnished, the volume is not re-calculated.
1744  */
1745 template <class T, class INTERLACING_TAG>
1746 double FIELD<T, INTERLACING_TAG>::normL1(int component,
1747                                          const FIELD<double, FullInterlace > * p_field_volume) const
1748 {
1749     _checkNormCompatibility(p_field_volume); // may throw exception
1750     if ( component<1 || component>getNumberOfComponents() )
1751         throw MEDEXCEPTION(STRING("FIELD<T,INTERLACING_TAG>::normL2() : The component argument should be between 1 and the number of components"));
1752
1753     const FIELD<double,FullInterlace> * p_field_size=p_field_volume;
1754     if(!p_field_volume) // if the user don't supply the volume
1755         p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
1756
1757     // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
1758     const double* vol=p_field_size->getValue();
1759     const T * value     = NULL;
1760     ArrayNo * myArray   = NULL;
1761     if ( getInterlacingType() == MED_EN::MED_NO_INTERLACE )
1762       value = getColumn(component);
1763     else {
1764       myArray = ArrayConvert( *( dynamic_cast< ArrayFull * > ( getArrayNoGauss() ) ));
1765       value   = myArray->getColumn(component);
1766     }
1767
1768     const T* lastvalue=value+getNumberOfValues(); // pointing just after the end of column
1769
1770     double integrale=0.0;
1771     double totVol=0.0;
1772     for (; value!=lastvalue ; ++value ,++vol)
1773     {
1774         integrale += std::abs( static_cast<double>(*value) ) * (*vol);
1775         totVol+=*vol;
1776     }
1777
1778     if(!p_field_volume) // if the user didn't supply the volume
1779         delete p_field_size; // delete temporary volume field
1780     if ( getInterlacingType() == MED_EN::MED_FULL_INTERLACE ) delete myArray;
1781     if( totVol <= 0)
1782         throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
1783
1784     return integrale/totVol;
1785 }
1786
1787 /*!  Return L1 Norm  of the field.
1788  *   Cannot be applied to a field with a support on nodes.
1789  *   If the optional p_field_volume argument is furnished, the volume is not re-calculated.
1790  */
1791 template <class T, class INTERLACING_TAG>
1792 double FIELD<T, INTERLACING_TAG>::normL1(const FIELD<double, FullInterlace> * p_field_volume) const
1793 {
1794     _checkNormCompatibility(p_field_volume); // may throw exception
1795     const FIELD<double, FullInterlace> * p_field_size=p_field_volume;
1796     if(!p_field_volume) // if the user don't supply the volume
1797         p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
1798
1799     // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
1800     const double* vol=p_field_size->getValue();
1801     const double* lastvol=vol+getNumberOfValues(); // pointing just after the end of vol
1802
1803    const T * value     = NULL;
1804     ArrayNo * myArray   = NULL;
1805     if ( getInterlacingType() == MED_EN::MED_NO_INTERLACE )
1806       value = getValue();
1807     else {
1808       myArray = ArrayConvert( *( dynamic_cast< ArrayFull * > ( getArrayNoGauss() ) ));
1809       value   = myArray->getPtr();
1810     }
1811
1812     double totVol=0.0;
1813     const double* p_vol=vol;
1814     for (p_vol=vol; p_vol!=lastvol ; ++p_vol) // calculate total volume
1815         totVol+=*p_vol;
1816
1817     double integrale=0.0;
1818     for (int i=1; i<=getNumberOfComponents(); ++i) // compute integral on all components
1819         for (p_vol=vol; p_vol!=lastvol ; ++value ,++p_vol)
1820             integrale += std::abs( static_cast<double>(*value) ) * (*p_vol);
1821
1822     if(!p_field_volume) // if the user didn't supply the volume
1823         delete p_field_size; // delete temporary volume field
1824     if ( getInterlacingType() == MED_EN::MED_FULL_INTERLACE ) delete myArray;
1825     if( totVol <= 0)
1826         throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
1827
1828     return integrale/totVol;
1829 }
1830
1831 /*! Return a new field (to deallocate with delete) lying on subSupport that is included by
1832  *   this->_support with corresponding values extracting from this->_value.
1833  */
1834 template <class T, class INTERLACING_TAG>
1835 FIELD<T, INTERLACING_TAG>* FIELD<T, INTERLACING_TAG>::extract(const SUPPORT *subSupport) const throw (MEDEXCEPTION)
1836 {
1837   if(!subSupport->belongsTo(*_support))
1838     throw MEDEXCEPTION("FIELD<T>::extract : subSupport not included in this->_support !");
1839   if(_support->isOnAllElements() && subSupport->isOnAllElements())
1840     return new FIELD<T, INTERLACING_TAG>(*this);
1841
1842   FIELD<T, INTERLACING_TAG> *ret = new FIELD<T, INTERLACING_TAG>(subSupport,
1843                                                                  _numberOfComponents);
1844
1845   if(!ret->_value)
1846     throw MEDEXCEPTION("FIELD<T>::extract : unvalid support detected !");
1847
1848   T* valuesToSet=(T*)ret->getValue();
1849
1850   int nbOfEltsSub=subSupport->getNumberOfElements(MED_EN::MED_ALL_ELEMENTS);
1851   const int *eltsSub=subSupport->getNumber(MED_EN::MED_ALL_ELEMENTS);
1852   T* tempVals=new T[_numberOfComponents];
1853   for(int i=0;i<nbOfEltsSub;i++)
1854     {
1855       if(!getValueOnElement(eltsSub[i],tempVals))
1856         throw MEDEXCEPTION("Problem in belongsTo function !!!");
1857       for(int j=0;j<_numberOfComponents;j++)
1858         valuesToSet[i*_numberOfComponents+j]=tempVals[j];
1859     }
1860   delete [] tempVals;
1861
1862   ret->copyGlobalInfo(*this);
1863   return ret;
1864 }
1865
1866 /*!
1867   Constructor with parameters; the object is set via a file and its associated
1868   driver. For the moment only the MED_DRIVER is considered and if the last two
1869   argument (iterationNumber and orderNumber) are not set; their default value
1870   is -1. If the field fieldDriverName with the iteration number
1871   iterationNumber and the order number orderNumber does not exist in the file
1872   fieldDriverName; the constructor raises an exception.
1873 */
1874 template <class T, class INTERLACING_TAG>
1875 FIELD<T, INTERLACING_TAG>::FIELD(const SUPPORT * Support,
1876                                  driverTypes driverType,
1877                                  const string & fileName/*=""*/,
1878                                  const string & fieldDriverName/*=""*/,
1879                                  const int iterationNumber,
1880                                  const int orderNumber) throw (MEDEXCEPTION)
1881 {
1882   const char * LOC = "template <class T> FIELD<T>::FIELD(const SUPPORT * Support, driverTypes driverType, const string & fileName=\"\", const string & fieldName=\"\", const int iterationNumber=-1, const int orderNumber=-1) : ";
1883
1884   int current;
1885
1886   BEGIN_OF(LOC);
1887
1888   init();
1889
1890   //INITIALISATION DE _valueType DS LE CONSTRUCTEUR DE FIELD_
1891   ASSERT(FIELD_::_valueType == MED_EN::MED_UNDEFINED_TYPE)
1892   FIELD_::_valueType=SET_VALUE_TYPE<T>::_valueType;
1893
1894   //INITIALISATION DE _interlacingType DS LE CONSTRUCTEUR DE FIELD_
1895   ASSERT(FIELD_::_interlacingType == MED_EN::MED_UNDEFINED_INTERLACE)
1896   FIELD_::_interlacingType=SET_INTERLACING_TYPE<INTERLACING_TAG>::_interlacingType;
1897
1898   _support = Support;
1899   //A.G. Addings for RC
1900   if(_support)
1901     _support->addReference();
1902   _value = (MEDMEM_Array<T, INTERLACING_TAG> *) NULL;
1903
1904   _iterationNumber = iterationNumber;
1905   _time = 0.0;
1906   _orderNumber = orderNumber;
1907
1908   current = addDriver(driverType,fileName,fieldDriverName,MED_EN::MED_LECT);
1909
1910   _drivers[current]->open();
1911   _drivers[current]->read();
1912   _drivers[current]->close();
1913
1914   END_OF(LOC);
1915 }
1916
1917 /*!
1918   This constructor, at least, allows to create a FIELD without creating any
1919   SUPPORT then without having to load a MESH object, a support is created. It
1920   provides the meshName related mesh but doesn't not set a mesh in the created
1921   support.
1922 */
1923 template <class T, class INTERLACING_TAG>  
1924 FIELD<T,INTERLACING_TAG>::FIELD(driverTypes driverType,
1925                                 const string & fileName,
1926                                 const string & fieldDriverName,
1927                                 const int iterationNumber,
1928                                 const int orderNumber)
1929   throw (MEDEXCEPTION) :FIELD_()
1930 {
1931   int current;
1932   const char * LOC ="FIELD<T,INTERLACING_TAG>::FIELD( driverTypes driverType, const string & fileName, string & fieldDriverName, int iterationNumber, int orderNumber) : ";
1933   BEGIN_OF(LOC);
1934
1935   init();
1936
1937   //INITIALISATION DE _valueType DS LE CONSTRUCTEUR DE FIELD_
1938   ASSERT(FIELD_::_valueType == MED_EN::MED_UNDEFINED_TYPE)
1939   FIELD_::_valueType=SET_VALUE_TYPE<T>::_valueType;
1940
1941   //INITIALISATION DE _interlacingType DS LE CONSTRUCTEUR DE FIELD_
1942   ASSERT(FIELD_::_interlacingType == MED_EN::MED_UNDEFINED_INTERLACE)
1943   FIELD_::_interlacingType=SET_INTERLACING_TYPE<INTERLACING_TAG>::_interlacingType;
1944
1945   _support = (SUPPORT *) NULL;
1946   _value = (MEDMEM_Array<T,INTERLACING_TAG> *)NULL;
1947
1948   _iterationNumber = iterationNumber;
1949   _time = 0.0;
1950   _orderNumber = orderNumber;
1951
1952   current = addDriver(driverType,fileName,fieldDriverName,MED_EN::MED_LECT);
1953
1954   _drivers[current]->open();
1955   _drivers[current]->read();
1956   _drivers[current]->close();
1957
1958   END_OF(LOC);
1959 }
1960
1961 /*!
1962   Destructor.
1963 */
1964 template <class T, class INTERLACING_TAG> FIELD<T, INTERLACING_TAG>::~FIELD()
1965 {
1966   BEGIN_OF(" Destructeur FIELD<T, INTERLACING_TAG>::~FIELD()");
1967   SCRUTE(this);
1968   if (_value) delete _value;
1969   END_OF(" Destructeur FIELD<T,INTERLACING_TAG>::~FIELD()");
1970 }
1971
1972 /*!
1973
1974 */
1975 template <class T, class INTERLACING_TAG>
1976 void FIELD<T, INTERLACING_TAG>::allocValue(const int NumberOfComponents)
1977 {
1978   const char* LOC = "FIELD<T, INTERLACING_TAG>::allocValue(const int NumberOfComponents)" ;
1979   BEGIN_OF(LOC);
1980
1981   _numberOfComponents = NumberOfComponents ;
1982   if (_componentsTypes == NULL)
1983     _componentsTypes = new int[NumberOfComponents] ;
1984   if (_componentsNames == NULL)
1985     _componentsNames = new string[NumberOfComponents];
1986   if (_componentsDescriptions == NULL)
1987     _componentsDescriptions = new string[NumberOfComponents];
1988   if (_componentsUnits == NULL)
1989     _componentsUnits = new UNIT[NumberOfComponents];
1990   if (_MEDComponentsUnits == NULL)
1991     _MEDComponentsUnits = new string[NumberOfComponents];
1992   for (int i=0;i<NumberOfComponents;i++) {
1993     _componentsTypes[i] = 0 ;
1994   }
1995
1996   try {
1997     // becarefull about the number of gauss point
1998     _numberOfValues = _support->getNumberOfElements(MED_EN::MED_ALL_ELEMENTS);
1999     MESSAGE(LOC <<" : "<<_numberOfValues <<" et "<< NumberOfComponents);
2000
2001     //EF : A modifier lors de l'intégration de la classe de localisation des points de gauss
2002     _value = new ArrayNoGauss(_numberOfComponents,_numberOfValues);
2003
2004     _isRead = true ;
2005   }
2006   catch (MEDEXCEPTION &ex) {
2007     MESSAGE("No value defined, problem with NumberOfComponents (and may be _support) size of MEDARRAY<T>::_value !");
2008     _value = (MEDMEM_Array<T, INTERLACING_TAG> *)NULL ;
2009   }
2010
2011   SCRUTE(_value);
2012   END_OF("void FIELD<T, INTERLACING_TAG>::allocValue(const int NumberOfComponents)");
2013 }
2014
2015 /*!
2016
2017 */
2018 template <class T, class INTERLACING_TAG>
2019 void FIELD<T, INTERLACING_TAG>::allocValue(const int NumberOfComponents,
2020                                            const int LengthValue)
2021 {
2022   BEGIN_OF("void FIELD<T>::allocValue(const int NumberOfComponents,const int LengthValue)");
2023
2024   _numberOfComponents = NumberOfComponents ;
2025   if (_componentsTypes == NULL)
2026     _componentsTypes = new int[NumberOfComponents] ;
2027   if (_componentsNames == NULL)
2028     _componentsNames = new string[NumberOfComponents];
2029   if (_componentsDescriptions == NULL)
2030     _componentsDescriptions = new string[NumberOfComponents];
2031   if (_componentsUnits == NULL)
2032     _componentsUnits = new UNIT[NumberOfComponents];
2033   if (_MEDComponentsUnits == NULL)
2034     _MEDComponentsUnits = new string[NumberOfComponents];
2035   for (int i=0;i<NumberOfComponents;i++) {
2036     _componentsTypes[i] = 0 ;
2037   }
2038
2039   MESSAGE("FIELD : constructeur : "<<LengthValue <<" et "<< NumberOfComponents);
2040   _numberOfValues = LengthValue ;
2041
2042   //EF : A modifier lors de l'intégration de la classe de localisation des points de gauss
2043   _value = new ArrayNoGauss(_numberOfComponents,_numberOfValues);
2044
2045   _isRead = true ;
2046
2047   SCRUTE(_value);
2048   END_OF("void FIELD<T, INTERLACING_TAG>::allocValue(const int NumberOfComponents,const int LengthValue)");
2049 }
2050
2051 /*!
2052
2053 */
2054 template <class T, class INTERLACING_TAG>
2055 void FIELD<T, INTERLACING_TAG>::deallocValue()
2056 {
2057   BEGIN_OF("void FIELD<T, INTERLACING_TAG>::deallocValue()");
2058   _numberOfValues = 0 ;
2059   _numberOfComponents = 0 ;
2060   if (_value != NULL)
2061     delete _value;
2062
2063   END_OF("void FIELD<T, INTERLACING_TAG>::deallocValue()");
2064 }
2065
2066 // -----------------
2067 // Methodes Inline
2068 // -----------------
2069
2070 /*!
2071   Create the specified driver and return its index reference to path to
2072   read or write methods.
2073 */
2074
2075 template <class T, class INTERLACING_TAG>
2076 int FIELD<T, INTERLACING_TAG>::addDriver(driverTypes driverType,
2077                                          const string & fileName/*="Default File Name.med"*/,
2078                                          const string & driverName/*="Default Field Name"*/,
2079                                          MED_EN::med_mode_acces access)
2080 {
2081   //jfa tmp (as last argument has no default value):const char * LOC = "FIELD<T>::addDriver(driverTypes driverType, const string & fileName=\"Default File Name.med\",const string & driverName=\"Default Field Name\",MED_EN::med_mode_acces access) : ";
2082   const char * LOC = "FIELD<T>::addDriver(driverTypes driverType, const string & fileName,const string & driverName,MED_EN::med_mode_acces access) :";//jfa tmp
2083
2084   GENDRIVER * driver;
2085
2086   BEGIN_OF(LOC);
2087
2088   SCRUTE(driverType);
2089
2090   driver = DRIVERFACTORY::buildDriverForField(driverType,fileName,this,access);
2091
2092   _drivers.push_back(driver);
2093
2094   int current = _drivers.size()-1;
2095
2096   _drivers[current]->setFieldName(driverName);
2097
2098   END_OF(LOC);
2099
2100   return current;
2101 }
2102
2103
2104 /*!
2105   Duplicate the given driver and return its index reference to path to
2106   read or write methods.
2107 */
2108 template <class T, class INTERLACING_TAG>
2109 inline int FIELD<T, INTERLACING_TAG>::addDriver (GENDRIVER & driver )
2110 {
2111   const char * LOC = "FIELD<T, INTERLACING_TAG>::addDriver(GENDRIVER &) : ";
2112   int current;
2113
2114   BEGIN_OF(LOC);
2115
2116   // duplicate driver to delete it with destructor !
2117   GENDRIVER * newDriver = driver.copy() ;
2118
2119   _drivers.push_back(newDriver);
2120
2121   current = _drivers.size()-1;
2122   SCRUTE(current);
2123   driver.setId(current);
2124
2125   MESSAGE(LOC << " je suis la 1");
2126   END_OF(LOC);
2127   MESSAGE(LOC << " je suis la 2");
2128
2129   return current ;
2130 };
2131
2132 /*!
2133   Remove the driver referenced by its index.
2134 */
2135 template <class T, class INTERLACING_TAG>
2136 void FIELD<T, INTERLACING_TAG>::rmDriver (int index/*=0*/)
2137 {
2138   const char * LOC = "FIELD<T, INTERLACING_TAG>::rmDriver (int index=0): ";
2139   BEGIN_OF(LOC);
2140
2141   if ( _drivers[index] ) {
2142     //_drivers.erase(&_drivers[index]);
2143     // why not ????
2144     MESSAGE ("detruire");
2145   }
2146   else
2147     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
2148                                      << "The <index given is invalid, index must be between  0 and  |"
2149                                      << _drivers.size()
2150                                      )
2151                           );
2152
2153   END_OF(LOC);
2154 }
2155
2156 /*!
2157   Read FIELD in the file specified in the driver given by its index.
2158 */
2159 template <class T, class INTERLACING_TAG> inline void FIELD<T, INTERLACING_TAG>::read(int index/*=0*/)
2160 {
2161   const char * LOC = "FIELD<T, INTERLACING_TAG>::read(int index=0) : ";
2162   BEGIN_OF(LOC);
2163
2164   if ( _drivers[index] ) {
2165     _drivers[index]->open();
2166     _drivers[index]->read();
2167     _drivers[index]->close();
2168   }
2169   else
2170     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
2171                                      << "The index given is invalid, index must be between  0 and |"
2172                                      << _drivers.size()
2173                                      )
2174                           );
2175   END_OF(LOC);
2176 }
2177
2178 /*!
2179   Write FIELD in the file specified in the driver given by its index.
2180 */
2181 template <class T, class INTERLACING_TAG> inline void FIELD<T, INTERLACING_TAG>::write(int index/*=0*/, const string & driverName /*= ""*/)
2182 {
2183   const char * LOC = "FIELD<T,INTERLACING_TAG>::write(int index=0, const string & driverName = \"\") : ";
2184   BEGIN_OF(LOC);
2185
2186   if( _drivers[index] ) {
2187     _drivers[index]->open();
2188     if (driverName != "") _drivers[index]->setFieldName(driverName);
2189     _drivers[index]->write();
2190     _drivers[index]->close();
2191   }
2192   else
2193     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
2194                                      << "The index given is invalid, index must be between  0 and |"
2195                                      << _drivers.size()
2196                                      )
2197                           );
2198   END_OF(LOC);
2199 }
2200
2201 /*!
2202   Write FIELD in the file specified in the driver given by its index. Use this
2203   method for ASCII drivers (e.g. VTK_DRIVER)
2204 */
2205 template <class T, class INTERLACING_TAG> inline void FIELD<T, INTERLACING_TAG>::writeAppend(int index/*=0*/, const string & driverName /*= ""*/)
2206 {
2207   const char * LOC = "FIELD<T,INTERLACING_TAG>::write(int index=0, const string & driverName = \"\") : ";
2208   BEGIN_OF(LOC);
2209
2210   if( _drivers[index] ) {
2211     _drivers[index]->openAppend();
2212     if (driverName != "") _drivers[index]->setFieldName(driverName);
2213     _drivers[index]->writeAppend();
2214     _drivers[index]->close();
2215   }
2216   else
2217     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
2218                                      << "The index given is invalid, index must be between  0 and |"
2219                                      << _drivers.size()
2220                                      )
2221                           );
2222   END_OF(LOC);
2223 }
2224
2225 /*!
2226   \internal
2227   Write FIELD with the driver which is equal to the given driver.
2228
2229   Use by MED object.
2230 */
2231 template <class T, class INTERLACING_TAG> inline void FIELD<T, INTERLACING_TAG>::write(const GENDRIVER & genDriver)
2232 {
2233   const char * LOC = " FIELD<T, INTERLACING_TAG>::write(const GENDRIVER &) : ";
2234   BEGIN_OF(LOC);
2235
2236   for (unsigned int index=0; index < _drivers.size(); index++ )
2237     if ( *_drivers[index] == genDriver ) {
2238       _drivers[index]->open();
2239       _drivers[index]->write();
2240       _drivers[index]->close();
2241     }
2242
2243   END_OF(LOC);
2244
2245 }
2246
2247 /*!
2248   \internal
2249   Write FIELD with the driver which is equal to the given driver.
2250
2251   Use by MED object. Use this method for ASCII drivers (e.g. VTK_DRIVER).
2252 */
2253 template <class T, class INTERLACING_TAG> inline void FIELD<T, INTERLACING_TAG>::writeAppend(const GENDRIVER & genDriver)
2254 {
2255   const char * LOC = " FIELD<T, INTERLACING_TAG>::write(const GENDRIVER &) : ";
2256   BEGIN_OF(LOC);
2257
2258   for (unsigned int index=0; index < _drivers.size(); index++ )
2259     if ( *_drivers[index] == genDriver ) {
2260       _drivers[index]->openAppend();
2261       _drivers[index]->writeAppend();
2262       _drivers[index]->close();
2263     }
2264
2265   END_OF(LOC);
2266
2267 }
2268
2269 /*!
2270   \internal
2271   Read FIELD with the driver which is equal to the given driver.
2272
2273   Use by MED object.
2274 */
2275 template <class T, class INTERLACING_TAG> inline void FIELD<T, INTERLACING_TAG>::read(const GENDRIVER & genDriver)
2276 {
2277   const char * LOC = " FIELD<T, INTERLACING_TAG>::read(const GENDRIVER &) : ";
2278   BEGIN_OF(LOC);
2279
2280   for (unsigned int index=0; index < _drivers.size(); index++ )
2281     if ( *_drivers[index] == genDriver ) {
2282       _drivers[index]->open();
2283       _drivers[index]->read();
2284       _drivers[index]->close();
2285     }
2286
2287   END_OF(LOC);
2288
2289 }
2290
2291 /*!
2292   Fills in already allocated retValues array the values related to eltIdInSup.
2293   If the element does not exist in this->_support false is returned, true otherwise.
2294  */
2295 template <class T, class INTERLACING_TAG>
2296 bool FIELD<T, INTERLACING_TAG>::getValueOnElement(int eltIdInSup,T* retValues)
2297   const throw (MEDEXCEPTION)
2298 {
2299 //   retValues =  getRow(eltIdInSup);
2300
2301   if(eltIdInSup<1)
2302     return false;
2303   if(_support->isOnAllElements())
2304     {
2305       int nbOfEltsThis=_support->getMesh()->getNumberOfElements(_support->getEntity(),MED_EN::MED_ALL_ELEMENTS);
2306       if(eltIdInSup>nbOfEltsThis)
2307         return false;
2308       const T* valsThis=getValue();
2309       for(int j=0;j<_numberOfComponents;j++)
2310         retValues[j]=valsThis[(eltIdInSup-1)*_numberOfComponents+j];
2311       return true;
2312     }
2313   else
2314     {
2315       int nbOfEltsThis=_support->getNumberOfElements(MED_EN::MED_ALL_ELEMENTS);
2316       const int *eltsThis=_support->getNumber(MED_EN::MED_ALL_ELEMENTS);
2317       int iThis;
2318       bool found=false;
2319       for(iThis=0;iThis<nbOfEltsThis && !found;)
2320         if(eltsThis[iThis]==eltIdInSup)
2321           found=true;
2322         else
2323           iThis++;
2324       if(!found)
2325         return false;
2326       const T* valsThis=getValue();
2327       for(int j=0;j<_numberOfComponents;j++)
2328         retValues[j]=valsThis[iThis*_numberOfComponents+j];
2329       return true;
2330     }
2331 }
2332
2333 /*!
2334   \if developper
2335   Destroy the MEDARRAY<T> in FIELD and put the new one without copy.
2336   \endif
2337 */
2338 template <class T, class INTERLACING_TAG>
2339 inline void FIELD<T, INTERLACING_TAG>::setArray(MEDMEM_Array_ * Value)
2340   throw (MEDEXCEPTION)
2341 {
2342   if (NULL != _value) delete _value ;
2343   _value=Value ;
2344 }
2345
2346 /*!
2347   \if developper
2348   Return a reference to  the MEDARRAY<T, INTERLACING_TAG> in FIELD.
2349   \endif
2350 */
2351 template <class T, class INTERLACING_TAG>
2352 inline MEDMEM_Array_ * FIELD<T, INTERLACING_TAG>::getArray() const throw (MEDEXCEPTION)
2353 {
2354   const char * LOC = "MEDMEM_Array_ * FIELD<T, INTERLACING_TAG>::getArray() : ";
2355   BEGIN_OF(LOC);
2356   END_OF(LOC);
2357   return _value ;
2358 }
2359 template <class T,class INTERLACING_TAG>  inline 
2360 typename MEDMEM_ArrayInterface<T,INTERLACING_TAG,Gauss>::Array *
2361 FIELD<T, INTERLACING_TAG>::getArrayGauss() const throw (MEDEXCEPTION)
2362 {
2363   const char * LOC = "FIELD<T, INTERLACING_TAG>::getArrayGauss() : ";
2364   BEGIN_OF(LOC);
2365
2366   if ( getGaussPresence() )
2367     return dynamic_cast<ArrayGauss *> (_value);
2368   else
2369     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<
2370                                  "The field has no Gauss Point"));
2371
2372   END_OF(LOC);
2373
2374 }
2375
2376 template <class T,class INTERLACING_TAG>  inline 
2377 typename MEDMEM_ArrayInterface<T,INTERLACING_TAG,NoGauss>::Array *
2378 FIELD<T, INTERLACING_TAG>::getArrayNoGauss() const throw (MEDEXCEPTION)
2379 {
2380   const char * LOC = "FIELD<T, INTERLACING_TAG>::getArrayNoGauss() : ";
2381   BEGIN_OF(LOC);
2382
2383   if ( ! getGaussPresence() )
2384     return dynamic_cast < ArrayNoGauss * > (_value);
2385   else
2386     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<
2387                                  "The field has Gauss Point"));
2388
2389   END_OF(LOC);
2390 }
2391
2392
2393 template <class T,class INTERLACING_TAG> inline bool
2394 FIELD<T, INTERLACING_TAG>::getGaussPresence() const throw (MEDEXCEPTION)
2395 {
2396   const char * LOC = "FIELD<T, INTERLACING_TAG>::getGaussPresence() const :";
2397   BEGIN_OF(LOC);
2398
2399   if (_value != NULL)
2400     return _value->getGaussPresence();
2401   else
2402     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Can't call getGaussPresence on a null _value"));
2403
2404   END_OF(LOC);
2405 }
2406
2407 /*!
2408   Return the actual length of the reference to values array returned by getValue.
2409 */
2410 template <class T, class INTERLACING_TAG>
2411 inline int FIELD<T, INTERLACING_TAG>::getValueLength() const
2412   throw (MEDEXCEPTION)
2413 {
2414   // be carefull about number of gauss point
2415   return _numberOfComponents*_numberOfValues;
2416 }
2417
2418 /*!
2419   Return a reference to values array to read them.
2420 */
2421 template <class T, class INTERLACIN_TAG>
2422 inline const T* FIELD<T, INTERLACIN_TAG>::getValue() const throw (MEDEXCEPTION)
2423 {
2424   const char * LOC ="FIELD<T, INTERLACING_TAG>::getValue() : ";
2425   BEGIN_OF(LOC);
2426   if ( getGaussPresence() )
2427     return dynamic_cast<ArrayGauss *>(_value)->getPtr() ;
2428   else
2429     return dynamic_cast<ArrayNoGauss *>(_value)->getPtr() ;
2430 }
2431 /*!
2432   Return a reference to i^{th} row
2433   of FIELD values array.
2434   If a faster accessor is intended you may use getArray() once,
2435   then MEDMEM_Array accessors.
2436   Be careful if field support is not on all elements you might
2437   have to use support->getValIndFromGlobalNumber(i).
2438 */
2439 template <class T,class INTERLACING_TAG> inline
2440 const T*
2441 FIELD<T,INTERLACING_TAG>::getRow(int i) const throw (MEDEXCEPTION)
2442 {
2443   const char * LOC = "FIELD<T,INTERLACING_TAG>::getRow(int i) : ";
2444   BEGIN_OF(LOC);
2445
2446   int valIndex=-1;
2447   if (_support)
2448     valIndex = _support->getValIndFromGlobalNumber(i);
2449   else
2450     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Support not define |" ));
2451
2452   if ( getGaussPresence() )
2453     return dynamic_cast<ArrayGauss *>(_value)->getRow(valIndex) ;
2454   else
2455     return dynamic_cast<ArrayNoGauss *>(_value)->getRow(valIndex) ;
2456   END_OF(LOC);
2457 }
2458
2459 /*!
2460   Return a reference to j^{th} column
2461   of FIELD values array.
2462 */
2463 template <class T,class INTERLACING_TAG> inline const T*
2464 FIELD<T,INTERLACING_TAG>::getColumn(int j) const throw (MEDEXCEPTION)
2465 {
2466   const char * LOC ="FIELD<T,INTERLACING_TAG>::getColumn(int j) : ";
2467   BEGIN_OF(LOC);
2468   if ( getGaussPresence() )
2469     return dynamic_cast<ArrayGauss *>(_value)->getColumn(j) ;
2470   else
2471     return dynamic_cast<ArrayNoGauss *>(_value)->getColumn(j) ;
2472 }
2473
2474 /*!
2475   Return the value of i^{th} element and j^{th} component.
2476 */
2477 template <class T,class INTERLACING_TAG> inline T FIELD<T,INTERLACING_TAG>::getValueIJ(int i,int j) const throw (MEDEXCEPTION)
2478 {
2479   const char * LOC = "getValueIJ(..)";
2480   BEGIN_OF(LOC);
2481   int valIndex=-1;
2482   if (_support)
2483     valIndex = _support->getValIndFromGlobalNumber(i);
2484   else
2485     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Support not define |" ));
2486
2487   if ( getGaussPresence() )
2488     return dynamic_cast<ArrayGauss *>(_value)->getIJ(valIndex,j) ;
2489   else
2490     return dynamic_cast<ArrayNoGauss *>(_value)->getIJ(valIndex,j) ;
2491 }
2492
2493 /*!
2494   Copy new values array in FIELD according to the given mode.
2495
2496   Array must have right size. If not results are unpredicable.
2497 */
2498 template <class T,class INTERLACING_TAG> inline void FIELD<T,INTERLACING_TAG>::setValue( T* value) throw (MEDEXCEPTION) 
2499 {
2500   if ( getGaussPresence() )
2501     return dynamic_cast<ArrayGauss *>(_value)->setPtr(value) ;
2502   else
2503     return dynamic_cast<ArrayNoGauss *>(_value)->setPtr(value) ;
2504 }
2505
2506 /*!
2507   Update values array in the j^{th} row of FIELD values array with the given ones and
2508   according to specified mode.
2509 */
2510 template <class T,class INTERLACING_TAG>
2511 inline void FIELD<T,INTERLACING_TAG>::setRow( int i, T* value) throw (MEDEXCEPTION) 
2512 {
2513   const char * LOC = "FIELD<T,INTERLACING_TAG>::setRow(int i, T* value) : ";
2514   int valIndex=i;
2515 //   JE (NB) NE SUIS PAS SUR DE CA ????
2516   if (_support)
2517     valIndex = _support->getValIndFromGlobalNumber(i);
2518   else
2519     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Support not define |" ));
2520
2521   if ( getGaussPresence() )
2522     return dynamic_cast<ArrayGauss *>(_value)->setRow(valIndex, value) ;
2523   else
2524     return dynamic_cast<ArrayNoGauss *>(_value)->setRow(valIndex, value) ;
2525 }
2526
2527 /*!
2528   Update values array in the j^{th} column of FIELD values array with the given ones and
2529   according to specified mode.
2530 */
2531 template <class T,class INTERLACING_TAG>
2532 inline void FIELD<T,INTERLACING_TAG>::setColumn( int i, T* value) throw (MEDEXCEPTION) 
2533 {
2534   if ( getGaussPresence() )
2535     return dynamic_cast<ArrayGauss *>(_value)->setColumn(i, value) ;
2536   else
2537     return dynamic_cast<ArrayNoGauss *>(_value)->setColumn(i, value) ;
2538 }
2539
2540 /*!
2541   Set the value of i^{th} element and j^{th} component with the given one.
2542 */
2543 template <class T,class INTERLACING_TAG> inline void FIELD<T,INTERLACING_TAG>::setValueIJ(int i, int j, T value) throw (MEDEXCEPTION) 
2544 {
2545   const char * LOC = "FIELD<T,INTERLACING_TAG>::setValueIJ(int i, int j, T value) : ";
2546   int valIndex=-1;
2547   if (_support)
2548     valIndex = _support->getValIndFromGlobalNumber(i);
2549   else
2550     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Support not define |" ));
2551
2552   if ( getGaussPresence() )
2553     return dynamic_cast<ArrayGauss *>(_value)->setIJ(valIndex,j,value) ;
2554   else
2555     return dynamic_cast<ArrayNoGauss *>(_value)->setIJ(valIndex,j,value) ;
2556 }
2557
2558 /*
2559   METHODS
2560 */
2561
2562 /*!
2563   Fill values array with volume values.
2564 */
2565 template <class T, class INTERLACING_TAG>
2566 void FIELD<T, INTERLACING_TAG>::getVolume() const throw (MEDEXCEPTION)
2567 {
2568   const char * LOC = "FIELD<double>::getVolume() const : ";
2569   BEGIN_OF(LOC);
2570
2571   // The field has to be initilised by a non empty support and a
2572   // number of components = 1 and its value type has to be set to MED_REEL64
2573   // (ie a FIELD<double>)
2574
2575   if ((_support == (SUPPORT *) NULL) || (_numberOfComponents != 1) || (_valueType != MED_EN::MED_REEL64))
2576       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"The field has to be initialised with a non empty support, a number of components set to 1 and a value type set to MED_REEL64"));
2577
2578   END_OF(LOC);
2579 }
2580
2581 /*!
2582   Fill values array with area values.
2583 */
2584 template <class T, class INTERLACING_TAG>
2585 void FIELD<T, INTERLACING_TAG>::getArea() const throw (MEDEXCEPTION)
2586 {
2587   const char * LOC = "FIELD<double>::getArea() const : ";
2588   BEGIN_OF(LOC);
2589
2590   // The field has to be initilised by a non empty support and a
2591   // number of components = 1 and its value type has to be set to MED_REEL64
2592   // (ie a FIELD<double>)
2593
2594   if ((_support == (SUPPORT *) NULL) || (_numberOfComponents != 1) || (_valueType != MED_EN::MED_REEL64))
2595       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"The field has to be initialised with a non empty support, a number of components set to 1 and a value type set to MED_REEL64"));
2596
2597   END_OF(LOC);
2598 }
2599
2600 /*!
2601   Fill values array with length values.
2602 */
2603 template <class T, class INTERLACING_TAG>
2604 void FIELD<T, INTERLACING_TAG>::getLength() const throw (MEDEXCEPTION)
2605 {
2606   const char * LOC = "FIELD<double>::getLength() const : ";
2607   BEGIN_OF(LOC);
2608
2609   // The field has to be initilised by a non empty support and a
2610   // number of components = 1 and its value type has to be set to MED_REEL64
2611   // (ie a FIELD<double>)
2612
2613   if ((_support == (SUPPORT *) NULL) || (_numberOfComponents != 1) || (_valueType != MED_EN::MED_REEL64))
2614       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"The field has to be initialised with a non empty support, a number of components set to 1 and a value type set to MED_REEL64"));
2615
2616   END_OF(LOC);
2617 }
2618
2619 /*!
2620   Fill values array with normal values.
2621 */
2622 template <class T, class INTERLACING_TAG>
2623 void FIELD<T, INTERLACING_TAG>::getNormal() const throw (MEDEXCEPTION)
2624 {
2625   const char * LOC = "FIELD<double>::getNormal() const : ";
2626   BEGIN_OF(LOC);
2627
2628   // The field has to be initilised by a non empty support and a
2629   // number of components = 1 and its value type has to be set to MED_REEL64
2630   // (ie a FIELD<double>)
2631
2632   if (_support == (SUPPORT *) NULL)
2633       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"The field has to be initialised with a non empty support, a number of components set to the space dimension and a value type set to MED_REEL64"));
2634
2635   int dim_space = _support->getMesh()->getSpaceDimension();
2636
2637   if ((_numberOfComponents != dim_space) || (_valueType != MED_EN::MED_REEL64))
2638       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"The field has to be initialised with a non empty support, a number of components set to the space dimension and a value type set to MED_REEL64"));
2639
2640   END_OF(LOC);
2641 }
2642
2643 /*!
2644   Fill values array with barycenter values.
2645 */
2646 template <class T, class INTERLACING_TAG>
2647 void FIELD<T, INTERLACING_TAG>::getBarycenter() const throw (MEDEXCEPTION)
2648 {
2649   const char * LOC = "FIELD<double>::getBarycenter() const : ";
2650   BEGIN_OF(LOC);
2651
2652   // The field has to be initilised by a non empty support and a number of
2653   //components = space dimension and its value type has to be set to MED_REEL64
2654   // (ie a FIELD<double>)
2655
2656   if (_support == (SUPPORT *) NULL)
2657       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"The field has to be initialised with a non empty support, a number of components set to the space dimension and a value type set to MED_REEL64"));
2658
2659   int dim_space = _support->getMesh()->getSpaceDimension();
2660
2661   if ((_numberOfComponents != dim_space) || (_valueType != MED_EN::MED_REEL64))
2662       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"The field has to be initialised with a non empty support, a number of components set to the space dimension and a value type set to MED_REEL64"));
2663
2664   END_OF(LOC);
2665 }
2666
2667 /*!
2668   Fill array by using T_Analytic.
2669   WARNING : "this" must have allocated its array by setting this->_support and this->_numberOfComponents properly.
2670   Typically you should use it on a field built with constructor FIELD<T>::FIELD<T>(SUPPORT *,int nbOfComponents)
2671  */
2672 template <class T, class INTERLACING_TAG>
2673 void FIELD<T, INTERLACING_TAG>::fillFromAnalytic(myFuncType f) throw (MEDEXCEPTION)
2674 {
2675   const char * LOC = "void FIELD<T, INTERLACING_TAG>::fillFromAnalytic(myFuncType f) : ";
2676   int i,j;
2677   if (_support == (SUPPORT *) NULL)
2678       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"No Support defined."));
2679
2680   MESH * mesh = _support->getMesh();
2681   int spaceDim = mesh->getSpaceDimension();
2682   const double * coord;
2683
2684   const double * bary;
2685   FIELD<double,FullInterlace> * barycenterField=0;
2686
2687   double ** xyz=new double* [spaceDim];
2688   bool deallocateXyz=false;
2689   if(_support->getEntity()==MED_EN::MED_NODE)
2690     {
2691       if (_support->isOnAllElements())
2692         {
2693           coord=mesh->getCoordinates(MED_EN::MED_NO_INTERLACE);
2694           for(i=0; i<spaceDim; i++)
2695             xyz[i]=(double *)coord+i*_numberOfValues;
2696         }
2697       else
2698         {
2699           coord = mesh->getCoordinates(MED_EN::MED_FULL_INTERLACE);
2700           const int * nodesNumber=_support->getNumber(MED_EN::MED_ALL_ELEMENTS);
2701           for(i=0; i<spaceDim; i++)
2702             xyz[i]=new double[_numberOfValues];
2703           deallocateXyz=true;
2704           for(i=0;i<_numberOfValues;i++)
2705             {
2706               for(j=0;j<spaceDim;j++)
2707                 xyz[j][i]=coord[(nodesNumber[i]-1)*spaceDim+j];
2708             }
2709         }
2710     }
2711   else
2712     {
2713       barycenterField = mesh->getBarycenter(_support);
2714       bary=barycenterField->getValue();
2715       for(i=0; i<spaceDim; i++)
2716         xyz[i]=(double *)(bary+i*_numberOfValues);
2717     }
2718   T* valsToSet=(T*)getValue();
2719   double *temp=new double[spaceDim];
2720   for(i=0;i<_numberOfValues;i++)
2721   {
2722     for(j=0;j<spaceDim;j++)
2723       temp[j]=xyz[j][i];
2724     f(temp,valsToSet+i*_numberOfComponents);
2725   }
2726   delete [] temp;
2727   if(barycenterField)
2728     delete barycenterField;
2729   if(deallocateXyz)
2730     for(j=0;j<spaceDim;j++)
2731       delete [] xyz[j];
2732   delete [] xyz;
2733 }
2734
2735 }//End namespace MEDMEM
2736
2737 #endif /* FIELD_HXX */