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