Salome HOME
update due to bugs PAL8113 and another I do not remember the number ;) .
[modules/med.git] / src / MEDMEM / MEDMEM_Field.hxx
index fef3312bb8536fb886ace48f066bc4967441bc95..cde465b131bfe34f50d0686e77b6bc26e14a3842 100644 (file)
@@ -7,6 +7,8 @@
 #define FIELD_HXX
 
 #include <vector>
+#include <algorithm>
+#include <cmath>
 
 #include "utilities.h"
 #include "MEDMEM_Exception.hxx"
 #include "MEDMEM_Unit.hxx"
 #include "MEDMEM_Array.hxx"
 #include "MEDMEM_GenDriver.hxx"
+#include "MEDMEM_DriverFactory.hxx"
 
-#include "MEDMEM_MedFieldDriver.hxx"
+/*!
 
-// template <class T> class MED_FIELD_RDONLY_DRIVER;
-// template <class T> class MED_FIELD_WRONLY_DRIVER;
-// template <class T> class MED_FIELD_RDWR_DRIVER;
+  This class contains all the informations related with a template class FIELD :
+  - Components descriptions
+  - Time step description
+  - Location of the values (a SUPPORT class)
 
-using namespace MED_EN;
+*/
+
+namespace MEDMEM {
+
+  template<class T> class FIELD;
 
-//class GENDRIVER;
 class FIELD_    // GENERIC POINTER TO a template <class T> class FIELD
 {
-
 protected:
 
-  string    _name ;
-  string    _description ;
+  bool            _isRead ;
+
+  /*!
+    \if developper
+    Field name.
+    \endif
+  */
+  string          _name ;
+  /*!
+    \if developper
+    Field description.
+    \endif
+  */
+  string          _description ;
+  /*!
+    \if developper
+    Pointer to the support the field deals with.
+    \endif
+  */
   const SUPPORT * _support ;
-  int       _numberOfComponents ;
-  int *     _componentsTypes ; // array of size _numberOfComponents 
-  // (constant, scalar, vector, tensor)
-  // we could use an array of integer to store 
-  // numbers of values
-  //           1 for scalar, 
-  //           space dimension for vector, 
-  //           space dimension square for tensor.
-  // so numbers of values per entities are 
-  // sum of _componentsTypes array
-  // Do not use yet! All type are scalar !
-  string * _componentsNames;             // array of size _numberOfComponents
-  string * _componentsDescriptions; // array of size _numberOfComponents
-  UNIT *   _componentsUnits;        // array of size _numberOfComponents 
-  string * _MEDComponentsUnits;     // array of size _numberOfComponents : 
-  // get unit from med file
-
-  int      _iterationNumber ;
-  double   _time;
-  int      _orderNumber ;
-
-  /*MED_EN::*/med_type_champ _valueType ;
+
+  /*!
+    \if developper
+    Number of field's components.
+    \endif
+  */
+  int             _numberOfComponents ;
+  /*!
+    \if developper
+    Number of field's values.
+    \endif
+  */
+  int             _numberOfValues ;
+
+  /*!
+    \if developper
+    Array of size _numberOfComponents. \n
+    (constant, scalar, vector, tensor)\n
+    We could use an array of integer to store
+    numbers of values: \n
+    - 1 for scalar,\n
+    - space dimension for vector,\n
+    - space dimension square for tensor.\n
+    So numbers of values per entities would be
+    sum of _componentsTypes array.
+
+    Not implemented yet! All type are scalar !
+    \endif
+  */
+  int *           _componentsTypes ;
+  /*!
+    \if developper
+    Array of size _numberOfComponents
+    storing components names if any.
+    \endif
+  */
+  string *       _componentsNames;     
+  /*!
+    \if developper
+    Array of size _numberOfComponents
+    storing components descriptions if any.
+    \endif
+ */
+  string *        _componentsDescriptions;
+  /*!
+    \if developper
+    Array of size _numberOfComponents
+    storing components units if any.
+    \endif
+ */
+  UNIT *          _componentsUnits;
+  /*!
+    \if developper
+    Array of size _numberOfComponents
+    storing components units if any.
+    \endif
+  */
+  string *        _MEDComponentsUnits;
+  int             _iterationNumber ;
+  double         _time;
+  int            _orderNumber ;
+
+  // _valueType should be a static const. Here is an initialization exemple 
+  // template < classType T > struct SET_VALUE_TYPE { static const med_type_champ _valueType = 0; }
+  // template < > struct SET_VALUE_TYPE<double> { static const med_type_champ _valueType = MED_EN::MED_REEL64; }
+  // template < > struct SET_VALUE_TYPE<int> { static const med_type_champ _valueType = MED_EN::MED_INT32; }
+  // static const med_type_champ _valueType = SET_VALUE_TYPE <T>::_valueType;
+  MED_EN::med_type_champ _valueType ;
+
+  vector<GENDRIVER *> _drivers; // Storage of the drivers currently in use
+  static void _checkFieldCompatibility(const FIELD_& m, const FIELD_& n ) throw (MEDEXCEPTION);
+  void _checkNormCompatibility(const FIELD<double>* p_field_volume=NULL) const  throw (MEDEXCEPTION);
+  FIELD<double>* _getFieldSize() const;
 
 public:
+
+  friend class MED_MED_RDONLY_DRIVER;
+  friend class MED_MED_WRONLY_DRIVER;
+  friend class MED_MED_RDWR_DRIVER;
+
+  friend class VTK_MED_DRIVER;
+
+  /*!
+    Constructor.
+  */
   FIELD_ ();
+  /*!
+    Constructor.
+  */
   FIELD_(const SUPPORT * Support, const int NumberOfComponents);
+  /*!
+    Copy constructor.
+  */
   FIELD_(const FIELD_ &m);
 
-  ~FIELD_();
+  /*!
+    Destructor.
+  */
+  virtual ~FIELD_();
 
 //    virtual  void     setIterationNumber (int IterationNumber);
-//    virtual  void     setOrderNumber     (int OrderNumber); 
-//    virtual  void     setFieldName       (string& fieldName); 
+//    virtual  void     setOrderNumber     (int OrderNumber);
+//    virtual  void     setFieldName       (string& fieldName);
 
   virtual  void     rmDriver(int index);
-  virtual   int     addDriver(driverTypes driverType, 
-                              const string & fileName,
-                              const string & driverFieldName) ;
-  virtual   int     addDriver(GENDRIVER & driver);
+  virtual   int     addDriver(driverTypes driverType,
+                              const string & fileName="Default File Name.med",
+                             const string & driverFieldName="Default Field Nam",
+                             MED_EN::med_mode_acces access=MED_EN::MED_REMP) ;
+
+  virtual  int      addDriver( GENDRIVER & driver);
+  virtual  void     read (const GENDRIVER &);
+  virtual  void     read(int index=0);
+  virtual void openAppend( void );
   virtual  void     write(const GENDRIVER &);
+  virtual  void     write(int index=0, const string & driverName="");
 
-  //  virtual  void     getValueType (MED_FR::med_type_champ ValueType) ;
-  //  virtual  void     setValueType (/*MED_EN::*/med_type_champ ValueType) ;
-  //  virtual  med_type_champ getValueType () ;
+  virtual  void     writeAppend(const GENDRIVER &);
+  virtual  void     writeAppend(int index=0, const string & driverName="");
 
-  inline void     setName(string Name);
+  inline void     setName(const string Name);
   inline string   getName() const;
-  inline void     setDescription(string Description);
-  inline string   getDescription()const;
+  inline void     setDescription(const string Description);
+  inline string   getDescription() const;
   inline const SUPPORT * getSupport() const;
-  inline void      setSupport(SUPPORT * support);
-  inline void     setNumberOfComponents(int NumberOfComponents);
+  inline void     setSupport(const SUPPORT * support);
+  inline void     setNumberOfComponents(const int NumberOfComponents);
   inline int      getNumberOfComponents() const;
+  inline void     setNumberOfValues(const int NumberOfValues);
+  inline int      getNumberOfValues() const;
   //    inline void     setComponentType(int *ComponentType);
   //    inline int *    getComponentType() const;
   //    inline int      getComponentTypeI(int i) const;
-  inline void     setComponentsNames(string * ComponentsNames);
-  inline void setComponentName(int i, string ComponentName);
-  inline string * getComponentsNames() const;
+  inline void     setComponentsNames(const string * ComponentsNames);
+  inline void     setComponentName(int i, const string ComponentName);
+  inline const string * getComponentsNames() const;
   inline string   getComponentName(int i) const;
-  inline void     setComponentsDescriptions(string *ComponentsDescriptions);
-  inline void     setComponentDescription(int i, string ComponentDescription);
-  inline string * getComponentsDescriptions() const;
+  inline void     setComponentsDescriptions(const string * ComponentsDescriptions);
+  inline void     setComponentDescription(int i, const string ComponentDescription);
+  inline const string * getComponentsDescriptions() const;
   inline string   getComponentDescription(int i) const;
 
   // provisoire : en attendant de regler le probleme des unites !
-  inline void     setComponentsUnits(UNIT * ComponentsUnits);
-  inline UNIT *   getComponentsUnits() const;
-  inline UNIT *   getComponentUnit(int i) const;
-  inline void     setMEDComponentsUnits(string * MEDComponentsUnits);
-  inline void     setMEDComponentUnit(int i, string MEDComponentUnit);
-  inline string * getMEDComponentsUnits() const;
+  inline void     setComponentsUnits(const UNIT * ComponentsUnits);
+  inline const UNIT *   getComponentsUnits() const;
+  inline const UNIT *   getComponentUnit(int i) const;
+  inline void     setMEDComponentsUnits(const string * MEDComponentsUnits);
+  inline void     setMEDComponentUnit(int i, const string MEDComponentUnit);
+  inline const string * getMEDComponentsUnits() const;
   inline string   getMEDComponentUnit(int i) const;
 
   inline void     setIterationNumber(int IterationNumber);
   inline int      getIterationNumber() const;
   inline void     setTime(double Time);
   inline double   getTime() const;
-  inline void     setOrderNumber(int OrderNumber); 
+  inline void     setOrderNumber(int OrderNumber);
   inline int      getOrderNumber() const;
 
-  inline void     setValueType (/*MED_EN::*/med_type_champ ValueType) ;
-  inline /*MED_EN::*/med_type_champ getValueType () ;
+  inline void     setValueType (const MED_EN::med_type_champ ValueType) ;
+  inline MED_EN::med_type_champ getValueType () const;
 
 };
 
@@ -128,294 +227,1477 @@ public:
 // -----------------
 // Methodes Inline
 // -----------------
-
-inline void FIELD_::setName(string Name)
+/*!
+  Set FIELD name.
+*/
+inline void FIELD_::setName(const string Name)
 {
   _name=Name;
 }
-inline string FIELD_::getName() const 
+/*!
+  Get FIELD name.
+*/
+inline string FIELD_::getName() const
 {
   return _name;
 }
-inline void FIELD_::setDescription(string Description)
+/*!
+  Set FIELD description.
+*/
+inline void FIELD_::setDescription(const string Description)
 {
   _description=Description;
 }
-inline string FIELD_::getDescription() const 
+/*!
+  Get FIELD description.
+*/
+inline string FIELD_::getDescription() const
 {
   return _description;
 }
-inline void FIELD_::setNumberOfComponents(int NumberOfComponents)
+/*!
+  Set FIELD number of components.
+*/
+inline void FIELD_::setNumberOfComponents(const int NumberOfComponents)
 {
   _numberOfComponents=NumberOfComponents;
-} 
-inline int FIELD_::getNumberOfComponents() const 
-{ 
-  return _numberOfComponents ; 
-}
-//  inline void FIELD_::setComponentType(int *ComponentType) 
-//  { 
-//    _componentsTypes=ComponentType ; 
+}
+/*!
+  Get FIELD number of components.
+*/
+inline int FIELD_::getNumberOfComponents() const
+{
+  return _numberOfComponents ;
+}
+/*!
+  Set FIELD number of values.
+
+  It must be the same than in the associated SUPPORT object.
+*/
+inline void FIELD_::setNumberOfValues(const int NumberOfValues)
+{
+  _numberOfValues=NumberOfValues;
+}
+/*!
+  Get FIELD number of value.
+*/
+inline int FIELD_::getNumberOfValues() const
+{
+  return _numberOfValues ;
+}
+
+//  inline void FIELD_::setComponentType(int *ComponentType)
+//  {
+//    _componentsTypes=ComponentType ;
 //  }
-//  inline int * FIELD_::getComponentType() const 
-//  { 
-//    return _componentsTypes ; 
+//  inline int * FIELD_::getComponentType() const
+//  {
+//    return _componentsTypes ;
 //  }
-//  inline int FIELD_::getComponentTypeI(int i) const 
-//  { 
-//    return _componentsTypes[i-1] ; 
+//  inline int FIELD_::getComponentTypeI(int i) const
+//  {
+//    return _componentsTypes[i-1] ;
 //  }
-inline void FIELD_::setComponentsNames(string * ComponentsNames) 
-{ 
-  _componentsNames=ComponentsNames ; 
+
+/*!
+  Set FIELD components names.
+
+  Duplicate the ComponentsNames string array to put components names in
+  FIELD. ComponentsNames size must be equal to number of components.
+*/
+inline void FIELD_::setComponentsNames(const string * ComponentsNames)
+{
+  if (NULL == _componentsNames)
+    _componentsNames = new string[_numberOfComponents] ;
+  for (int i=0; i<_numberOfComponents; i++)
+    _componentsNames[i]=ComponentsNames[i] ;
 }
-inline void FIELD_::setComponentName(int i, string ComponentName) 
-{ 
-  _componentsNames[i-1]=ComponentName ; 
+/*!
+  Set FIELD i^th component name.
+
+  i must be >=1 and <= number of components.
+*/
+inline void FIELD_::setComponentName(int i, const string ComponentName)
+{
+  _componentsNames[i-1]=ComponentName ;
 }
-inline string * FIELD_::getComponentsNames() const 
-{ 
-  return _componentsNames ; 
+/*!
+  Get a reference to the string array which contain the components names.
+
+  This Array size is equal to number of components
+*/
+inline const string * FIELD_::getComponentsNames() const
+{
+  return _componentsNames ;
 }
-inline string FIELD_::getComponentName(int i) const 
-{ 
-  return _componentsNames[i-1] ; 
+/*!
+  Get the name of the i^th component.
+*/
+inline string FIELD_::getComponentName(int i) const
+{
+  return _componentsNames[i-1] ;
 }
-inline void FIELD_::setComponentsDescriptions(string *ComponentsDescriptions) 
-{ 
-  _componentsDescriptions=ComponentsDescriptions ; 
+/*!
+  Set FIELD components descriptions.
+
+  Duplicate the ComponentsDescriptions string array to put components 
+  descriptions in FIELD.
+  ComponentsDescriptions size must be equal to number of components.
+*/
+inline void FIELD_::setComponentsDescriptions(const string * ComponentsDescriptions)
+{
+  if (NULL == _componentsDescriptions)
+    _componentsDescriptions = new string[_numberOfComponents] ;
+  for (int i=0; i<_numberOfComponents; i++)
+    _componentsDescriptions[i]=ComponentsDescriptions[i] ;
 }
-inline void FIELD_::setComponentDescription(int i,string ComponentDescription)
-{ 
-  _componentsDescriptions[i-1]=ComponentDescription ; 
+/*!
+  Set FIELD i^th component description.
+
+  i must be >=1 and <= number of components.
+*/
+inline void FIELD_::setComponentDescription(int i,const string ComponentDescription)
+{
+  _componentsDescriptions[i-1]=ComponentDescription ;
 }
-inline string * FIELD_::getComponentsDescriptions() const
-{ 
-  return _componentsDescriptions ; 
+/*!
+  Get a reference to the string array which contain the components descriptions.
+
+  This Array size is equal to number of components
+*/
+inline const string * FIELD_::getComponentsDescriptions() const
+{
+  return _componentsDescriptions ;
 }
+/*!
+  Get the description of the i^th component.
+*/
 inline string FIELD_::getComponentDescription(int i) const
-{ 
-  return _componentsDescriptions[i-1]; 
-}
-inline void FIELD_::setComponentsUnits(UNIT * ComponentsUnits) 
-{ 
-  _componentsUnits=ComponentsUnits ; 
-}
-inline UNIT * FIELD_::getComponentsUnits() const 
-{ 
-  return _componentsUnits ; 
-}
-inline UNIT * FIELD_::getComponentUnit(int i) const 
-{ 
-  return &_componentsUnits[i-1] ; 
-}
-inline void FIELD_::setMEDComponentsUnits(string * MEDComponentsUnits) 
-{ 
-  _MEDComponentsUnits=MEDComponentsUnits ; 
-}
-inline void FIELD_::setMEDComponentUnit(int i, string MEDComponentUnit) 
-{ 
-  _MEDComponentsUnits[i-1]=MEDComponentUnit ; 
-}
-inline string * FIELD_::getMEDComponentsUnits() const 
-{ 
-  return _MEDComponentsUnits ; 
-}
-inline string FIELD_::getMEDComponentUnit(int i) const 
-{ 
-  return _MEDComponentsUnits[i-1] ; 
-}
-inline void FIELD_::setIterationNumber(int IterationNumber) 
-{ 
-  _iterationNumber=IterationNumber; 
-} 
-inline int FIELD_::getIterationNumber() const              
-{ 
-  return _iterationNumber ; 
-} 
-inline void FIELD_::setTime(double Time) 
-{
-  _time=Time ;   
-} 
-inline double FIELD_::getTime() const      
-{ 
-  return _time ; 
-}
-inline void FIELD_::setOrderNumber(int OrderNumber) 
-{ 
-  _orderNumber=OrderNumber ; 
-}
-inline int FIELD_::getOrderNumber() const                      
-{ 
+{
+  return _componentsDescriptions[i-1];
+}
+
+/*!
+  \todo
+  Set FIELD components UNIT.
+
+  Duplicate the ComponentsUnits UNIT array to put components 
+  units in FIELD.
+  ComponentsUnits size must be equal to number of components.
+*/
+inline void FIELD_::setComponentsUnits(const UNIT * ComponentsUnits)
+{
+  if (NULL == _componentsUnits)
+    _componentsUnits = new UNIT[_numberOfComponents] ;
+  for (int i=0; i<_numberOfComponents; i++)
+    _componentsUnits[i]=ComponentsUnits[i] ;
+}
+/*!
+  Get a reference to the UNIT array which contain the components units.
+
+  This Array size is equal to number of components
+*/
+inline const UNIT * FIELD_::getComponentsUnits() const
+{
+  return _componentsUnits ;
+}
+/*!
+  Get the UNIT of the i^th component.
+*/
+inline const UNIT * FIELD_::getComponentUnit(int i) const
+{
+  return &_componentsUnits[i-1] ;
+}
+/*!
+  Set FIELD components unit.
+
+  Duplicate the MEDComponentsUnits string array to put components 
+  units in FIELD.
+  MEDComponentsUnits size must be equal to number of components.
+  
+*/
+inline void FIELD_::setMEDComponentsUnits(const string * MEDComponentsUnits)
+{
+  if (NULL == _MEDComponentsUnits)
+    _MEDComponentsUnits = new string[_numberOfComponents] ;
+  for (int i=0; i<_numberOfComponents; i++)
+    _MEDComponentsUnits[i]=MEDComponentsUnits[i] ;
+}
+/*!
+  Set FIELD i^th component unit.
+
+  i must be >=1 and <= number of components.
+*/
+inline void FIELD_::setMEDComponentUnit(int i, const string MEDComponentUnit)
+{
+  _MEDComponentsUnits[i-1]=MEDComponentUnit ;
+}
+/*!
+  Get a reference to the string array which contain the components units.
+
+  This Array size is equal to number of components
+*/
+inline const string * FIELD_::getMEDComponentsUnits() const
+{
+  return _MEDComponentsUnits ;
+}
+/*!
+  Get the string for unit of the i^th component.
+*/
+inline string FIELD_::getMEDComponentUnit(int i) const
+{
+  return _MEDComponentsUnits[i-1] ;
+}
+/*!
+  Set the iteration number where FIELD has been calculated.
+*/
+inline void FIELD_::setIterationNumber(int IterationNumber)
+{
+  _iterationNumber=IterationNumber;
+}
+/*!
+  Get the iteration number where FIELD has been calculated.
+*/
+inline int FIELD_::getIterationNumber() const
+{
+  return _iterationNumber ;
+}
+/*!
+  Set the time (in second) where FIELD has been calculated.
+*/
+inline void FIELD_::setTime(double Time)
+{
+  _time=Time ;
+}
+/*!
+  Get the time (in second) where FIELD has been calculated.
+*/
+inline double FIELD_::getTime() const
+{
+  return _time ;
+}
+/*!
+  Set the order number where FIELD has been calculated.
+
+  It corresponds to internal iteration during one time step.
+*/
+inline void FIELD_::setOrderNumber(int OrderNumber)
+{
+  _orderNumber=OrderNumber ;
+}
+/*!
+  Get the order number where FIELD has been calculated.
+*/
+inline int FIELD_::getOrderNumber() const
+{
   return _orderNumber ;
 }
+/*!
+  Get a reference to the SUPPORT object associated to FIELD.
+*/
 inline  const SUPPORT * FIELD_::getSupport() const
 {
   return _support ;
 }
+/*!
+  Set the reference to the SUPPORT object associated to FIELD.
 
-inline void FIELD_::setSupport(SUPPORT * support)
+  Reference is not duplicate, so it must not be deleted.
+*/
+inline void FIELD_::setSupport(const SUPPORT * support)
 {
   _support = support ;
 }
-
-inline /*MED_EN::*/med_type_champ FIELD_::getValueType () 
+/*!
+  Get the FIELD med value type (MED_INT32 or MED_REEL64).
+*/
+inline MED_EN::med_type_champ FIELD_::getValueType () const
 {
   return _valueType ;
 }
-
-inline void FIELD_::setValueType (/*MED_EN::*/med_type_champ ValueType) 
+/*!
+  Set the FIELD med value type (MED_INT32 or MED_REEL64).
+*/
+inline void FIELD_::setValueType (const MED_EN::med_type_champ ValueType)
 {
   _valueType = ValueType ;
 }
 
+}//End namespace MEDMEM
+
 /////////////////////////
 // END OF CLASS FIELD_ //
 /////////////////////////
 
-template <class T> class FIELD : public FIELD_
-{
+/*!
 
-  // ------- Drivers Management Part
-protected:
+  This template class contains informations related with a FIELD :
+  - Values of the field
 
- //-----------------------//
-   class INSTANCE 
-  //-----------------------//
-  {
-  public:
-    virtual GENDRIVER * run(const string & fileName, FIELD<T> * ptrFIELD) const = 0 ;
-  } ;
-  
-  //-------------------------------------------------------//
-  template <class T2> class INSTANCE_DE : public INSTANCE 
-  //-------------------------------------------------------//
-  {
-  public :
-    GENDRIVER * run(const string & fileName, FIELD<T> * ptrFIELD) const 
-    { 
-      return new T2(fileName,ptrFIELD); 
-    }
-  } ;
-  
-  //    static INSTANCE_DE<MED_FIELD_RDONLY_DRIVER> inst_med_rdonly ;
-  static INSTANCE_DE<MED_FIELD_RDWR_DRIVER<T> >   inst_med ;
-  static const INSTANCE * const instances[] ;
+*/
 
-  // ------ End of Drivers Management Part
+namespace MEDMEM {
+
+  template<class T2> class MED_FIELD_RDONLY_DRIVER;
+  template<class T2> class MED_FIELD_WRONLY_DRIVER;
+  template<class T2> class VTK_FIELD_DRIVER;
   
-  vector<GENDRIVER *> _drivers; // Storage of the drivers currently in use
+template <class T> class FIELD : public FIELD_
+{
+protected:
+  // ------ End of Drivers Management Part
 
   // array of value of type T
   MEDARRAY<T> *_value ;
 
 private:
+  void _operation(const FIELD& m,const FIELD& n, const MED_EN::medModeSwitch mode, char* Op);
+  void _operationInitialize(const FIELD& m,const FIELD& n, char* Op);
+  void _add_in_place(const FIELD& m,const FIELD& n, const MED_EN::medModeSwitch mode);
+  void _sub_in_place(const FIELD& m,const FIELD& n, const MED_EN::medModeSwitch mode);
+  void _mul_in_place(const FIELD& m,const FIELD& n, const MED_EN::medModeSwitch mode);
+  void _div_in_place(const FIELD& m,const FIELD& n, const MED_EN::medModeSwitch mode) throw (MEDEXCEPTION);
   //setValueType() ;
 
+  FIELD & operator=(const FIELD &m);   // A FAIRE
 public:
   FIELD();
-  FIELD(const FIELD &m);               // A FAIRE
-  FIELD & operator=(const FIELD &m);   // A FAIRE
-  FIELD(const SUPPORT * Support, const int NumberOfComponents); // Ajout NB Constructeur FIELD avec allocation de memoire de tous ses attribut
-  FIELD(driverTypes driverType, const string & fileName="", 
-       const string & fieldName="");
-  ~FIELD();   
+  FIELD(const FIELD &m);
+  FIELD(const SUPPORT * Support, const int NumberOfComponents, const MED_EN::medModeSwitch Mode=MED_EN::MED_FULL_INTERLACE)  throw (MEDEXCEPTION) ; // Ajout NB Constructeur FIELD avec allocation de memoire de tous ses attribut
+  FIELD(const SUPPORT * Support, driverTypes driverType,
+       const string & fileName="", const string & fieldName="",
+       const int iterationNumber = -1, const int orderNumber = -1)
+    throw (MEDEXCEPTION);
+  ~FIELD();
+
+  const FIELD operator+(const FIELD& m) const;
+  const FIELD operator-(const FIELD& m) const;
+  const FIELD operator*(const FIELD& m) const;
+  const FIELD operator/(const FIELD& m) const;
+  const FIELD operator-() const;
+  FIELD& operator+=(const FIELD& m);
+  FIELD& operator-=(const FIELD& m);
+  FIELD& operator*=(const FIELD& m);
+  FIELD& operator/=(const FIELD& m);
+  static FIELD* add(const FIELD& m, const FIELD& n);
+  static FIELD* sub(const FIELD& m, const FIELD& n);
+  static FIELD* mul(const FIELD& m, const FIELD& n);
+  static FIELD* div(const FIELD& m, const FIELD& n);
+  double normMax() const throw (MEDEXCEPTION);
+  double norm2() const throw (MEDEXCEPTION);
+  void   applyLin(T a, T b);
+  template <T T_function(T)> void applyFunc();
+  static FIELD* scalarProduct(const FIELD& m, const FIELD& n);
+  double normL2(int component, const FIELD<double> * p_field_volume=NULL) const;
+  double normL2(const FIELD<double> * p_field_volume=NULL) const;
+  double normL1(int component, const FIELD<double> * p_field_volume=NULL) const;
+  double normL1(const FIELD<double> * p_field_volume=NULL) const;
 
   friend class MED_FIELD_RDONLY_DRIVER<T>;
   friend class MED_FIELD_WRONLY_DRIVER<T>;
-  friend class MED_FIELD_RDWR_DRIVER  <T>;
+  friend class VTK_FIELD_DRIVER<T>;
+  //friend class MED_FIELD_RDWR_DRIVER  <T>;
 
   void init ();
   void rmDriver(int index=0);
-  int  addDriver(driverTypes driverType, 
+  int  addDriver(driverTypes driverType,
                 const string & fileName="Default File Name.med",
-                const string & driverFieldName="Default Field Name") ;
+                const string & driverFieldName="Default Field Name",
+                MED_EN::med_mode_acces access=MED_EN::MED_REMP) ;
+
   int  addDriver(GENDRIVER & driver);
 
   void allocValue(const int NumberOfComponents);
   void allocValue(const int NumberOfComponents, const int LengthValue);
 
   void deallocValue();
-  
-  inline void read(int index=0);  
+
+  inline void read(int index=0);
+  inline void read(const GENDRIVER & genDriver);
   inline void write(int index=0, const string & driverName = "");
   inline void write(const GENDRIVER &);
 
+  inline void writeAppend(int index=0, const string & driverName = "");
+  inline void writeAppend(const GENDRIVER &);
+
   inline void     setValue(MEDARRAY<T> *Value);
 
-  inline T*       getValue(medModeSwitch Mode) const;
-  inline T*       getValueI(medModeSwitch Mode,int i) const;
+  inline MEDARRAY<T>* getvalue() const;
+  inline int getValueLength(MED_EN::medModeSwitch Mode) const;
+  inline const T*       getValue(MED_EN::medModeSwitch Mode) const;
+  inline const T*       getValueI(MED_EN::medModeSwitch Mode,int i) const;
   inline T        getValueIJ(int i,int j) const;
 
-  inline void setValue(medModeSwitch mode, T* value);
-  inline void setValueI(medModeSwitch mode, int i, T* value);
+  inline void setValue(MED_EN::medModeSwitch mode, T* value);
+  inline void setValueI(MED_EN::medModeSwitch mode, int i, T* value);
   inline void setValueIJ(int i, int j, T value);
+
+  /*!
+    This fonction feeds the FIELD<double> private attributs _value with the
+    volume of each cells belonging to the argument Support. The field has to be
+    initialised via the constructor FIELD<double>(const SUPPORT * , const int )
+    with Support as SUPPORT argument, 1 has the number of components, and Support
+    has be a SUPPORT on 3D cells. This initialisation could be done by the empty
+    constructor followed by a setSupport and setNumberOfComponents call but it has
+    be followed by a setValueType(MED_REEL64) call.
+   */
+  void getVolume() const throw (MEDEXCEPTION) ;
+  /*!
+    This fonction feeds the FIELD<double> private attributs _value with the
+    area of each cells (or faces) belonging to the attribut _support. The field
+    has to be initialised via the constructor FIELD<double>(const SUPPORT * ,
+    const int ) with 1 has the number of components, and _support has be a
+    SUPPORT on 2D cells or 3D faces. This initialisation could be done by the
+    empty constructor followed by a setSupport and setNumberOfComponents call but
+    it has be followed by a setValueType(MED_REEL64) call.
+   */
+  void getArea() const throw (MEDEXCEPTION) ;
+  /*!
+    This fonction feeds the FIELD<double> private attributs _value with the
+    length of each segments belonging to the attribut _support. The field has
+    to be initialised via the constructor FIELD<double>(const SUPPORT * ,
+    const int ) with 1 has the number of components, and _support has be a
+    SUPPORT on 3D edges or 2D faces. This initialisation could be done by the
+    empty constructor followed by a setSupport and setNumberOfComponents call but
+    it has be followed by a setValueType(MED_REEL64) call.
+   */
+  void getLength() const throw (MEDEXCEPTION) ;
+  /*!
+    This fonction feeds the FIELD<double> private attributs _value with the
+    normal vector of each faces belonging to the attribut _support. The field
+    has to be initialised via the constructor FIELD<double>(const SUPPORT * ,
+    const int ) with the space dimension has the number of components, and
+    _support has be a SUPPORT on 3D or 2D faces. This initialisation could be done
+    by the empty constructor followed by a setSupport and setNumberOfComponents
+    call but it has be followed by a setValueType(MED_REEL64) call.
+   */
+  void getNormal() const throw (MEDEXCEPTION) ;
+  /*!
+    This fonction feeds the FIELD<double> private attributs _value with the
+    barycenter of each faces or cells or edges belonging to the attribut _support.
+    The field has to be initialised via the constructor
+    FIELD<double>(const SUPPORT * ,const int ) with the space dimension has the
+    number of components, and _support has be a SUPPORT on 3D cells or 2D faces.
+    This initialisation could be done by the empty constructor followed by a
+    setSupport and setNumberOfComponents call but it has be followed by a
+    setValueType(MED_REEL64) call.
+   */
+  void getBarycenter() const throw (MEDEXCEPTION) ;
 };
 
 // --------------------
-// Implemented Methods 
+// Implemented Methods
 // --------------------
 
-template <class T>  FIELD<T>::FIELD(): 
+/*!
+  Constructor with no parameter, most of the attribut members are set to NULL.
+*/
+template <class T>  FIELD<T>::FIELD():
  _value((MEDARRAY<T>*)NULL)
 {
   MESSAGE("Constructeur FIELD sans parametre");
 }
 
+/*!
+  Constructor with parameters such that all attrribut are set but the _value
+  attribut is allocated but not set.
+*/
 template <class T>  FIELD<T>::FIELD(const SUPPORT * Support,
-                                   const int NumberOfComponents):
+                                   const int NumberOfComponents, const MED_EN::medModeSwitch Mode) throw (MEDEXCEPTION) :
   FIELD_(Support, NumberOfComponents)
 {
-  BEGIN_OF("FIELD<T>::FIELD(const SUPPORT * Support, const int NumberOfComponents)");
-  
-  int length = 0 ;
+  BEGIN_OF("FIELD<T>::FIELD(const SUPPORT * Support, const int NumberOfComponents, const medModeSwitch Mode)");
+  SCRUTE(this);
+
   try {
-    length = Support->getNumberOfElements(MED_ALL_ELEMENTS);
+    _numberOfValues = Support->getNumberOfElements(MED_ALL_ELEMENTS);
   }
   catch (MEDEXCEPTION &ex) {
     MESSAGE("No value defined ! ("<<ex.what()<<")");
     _value = (MEDARRAY<T>*)NULL ;
   }
-  MESSAGE("FIELD : constructeur : "<<length <<" et "<< NumberOfComponents);
-  if (0<length)
-    _value = new MEDARRAY<T>::MEDARRAY(NumberOfComponents,length);
-  else
+  MESSAGE("FIELD : constructeur : "<< _numberOfValues <<" et "<< NumberOfComponents);
+  if (0<_numberOfValues) {
+    _value = new MEDARRAY<T>(_numberOfComponents,_numberOfValues,Mode);
+    _isRead = true ;
+  } else
     _value = (MEDARRAY<T>*)NULL ;
 
-  END_OF("FIELD<T>::FIELD(const SUPPORT * Support, const int NumberOfComponents)");
+  END_OF("FIELD<T>::FIELD(const SUPPORT * Support, const int NumberOfComponents, const medModeSwitch Mode)");
 }
 
+/*!
+  \if developper
+  \endif
+*/
 template <class T> void FIELD<T>::init ()
 {
 }
 
-template <class T> FIELD<T>::FIELD(const FIELD &m):
+/*!
+  Copy constructor.
+*/
+template <class T> FIELD<T>::FIELD(const FIELD & m):
   FIELD_((FIELD_) m)
 {
-  _value = m._value;
-  _drivers = m._drivers;
+  MESSAGE("Constructeur FIELD de recopie");
+  if (m._value != NULL)
+    {
+      // copie only default !
+      _value = new MEDARRAY<T>(* m._value,false);
+    }
+  else
+    _value = (MEDARRAY<T> *) NULL;
+  //_drivers = m._drivers;
+}
+
+/*!
+  \if developper
+  Not implemented.
+  \endif
+*/
+template <class T> FIELD<T> & FIELD<T>::operator=(const FIELD &m)
+{
+  MESSAGE("Appel de FIELD<T>::operator=") ;
+  // operator= on FIELD_
+  // ignore driver
+  // copy values array
 }
 
-template <class T> FIELD<T> & FIELD<T>::FIELD::operator=(const FIELD &m)
+/*!
+     Overload addition operator.
+     This operation is authorized only for compatible fields that have the same support.
+     The compatibility checking includes equality tests of the folowing data members:\n
+     - _support
+     - _numberOfComponents
+     - _numberOfValues
+     - _componentsTypes
+     - _MEDComponentsUnits.
+
+     The data members of the returned field are initialized, based on the first field, except for the name, 
+     which is the combination of the two field's names and the operator.
+     Advised Utilisation in C++ : <tt> FIELD<T> c = a + b; </tt> \n
+     In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
+     When using python, this operator calls the copy constructor in any case.
+     The user has to be aware that when using operator + in associatives expressions like
+     <tt> a = b + c + d +e; </tt> \n
+     no optimisation is performed : the evaluation of last expression requires the construction of
+     3 temporary fields.
+*/
+template <class T>
+const FIELD<T> FIELD<T>::operator+(const FIELD & m) const
 {
+    BEGIN_OF("FIELD<T>::operator+(const FIELD & m)");
+    FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
+
+    // Select mode : avoid if possible any calculation of other mode for fields m or *this
+    MED_EN::medModeSwitch mode;
+    if(this->getvalue()->getMode()==m.getvalue()->getMode() || this->getvalue()->isOtherCalculated())
+       mode=m.getvalue()->getMode();
+    else
+       mode=this->getvalue()->getMode();
+    
+    // Creation of the result - memory is allocated by FIELD constructor
+    FIELD<T> result(this->getSupport(),this->getNumberOfComponents(),mode);
+    //result._operation(*this,m,mode,"+"); // perform Atribute's initialization & addition
+    result._operationInitialize(*this,m,"+"); // perform Atribute's initialization
+    result._add_in_place(*this,m,mode); // perform addition
+
+    END_OF("FIELD<T>::operator+(const FIELD & m)");
+    return result;
 }
 
-template <class T> FIELD<T>::FIELD(driverTypes driverType, 
-                                  const string & fileName="", 
-                                  const string & fieldName="")
+/*!  Overloaded Operator +=
+ *   Operations are directly performed in the first field's array.
+ *   This operation is authorized only for compatible fields that have the same support.
+ */
+template <class T>
+FIELD<T>& FIELD<T>::operator+=(const FIELD & m)
 {
+    BEGIN_OF("FIELD<T>::operator+=(const FIELD & m)");
+    FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
+
+    // We choose to keep *this mode, even if it may cost a re-calculation for m
+    MED_EN::medModeSwitch mode=this->getvalue()->getMode();
+    const T* value1=m.getValue(mode); // get pointers to the values we are adding
+
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (getValue(mode));
+    const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
+    const T* endV=value+size; // pointer to the end of value
+    for(;value!=endV; value1++,value++)
+       *value += *value1;
+    // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
+    this->getvalue()->clearOtherMode();
+    END_OF("FIELD<T>::operator+=(const FIELD & m)");
+    return *this;
 }
 
-template <class T> FIELD<T>::~FIELD() 
-{   
+
+/*! Addition of fields. Static member function.
+ *  The function return a pointer to a new created field that holds the addition.
+ *  Data members are checked for compatibility and initialized.
+ *  The user is in charge of memory deallocation.
+ */
+template <class T>
+FIELD<T>* FIELD<T>::add(const FIELD& m, const FIELD& n)
+{
+    BEGIN_OF("FIELD<T>::add(const FIELD & m, const FIELD& n)");
+    FIELD_::_checkFieldCompatibility(m, n); // may throw exception
+
+    // Select mode : avoid if possible any calculation of other mode for fields m or *this
+    MED_EN::medModeSwitch mode;
+    if(m.getvalue()->getMode()==n.getvalue()->getMode() || n.getvalue()->isOtherCalculated())
+       mode=m.getvalue()->getMode();
+    else
+       mode=n.getvalue()->getMode();
+    
+    // Creation of a new field
+    FIELD<T>* result = new FIELD<T>(m.getSupport(),m.getNumberOfComponents(),mode);
+    result->_operationInitialize(m,n,"+"); // perform Atribute's initialization
+    result->_add_in_place(m,n,mode); // perform addition
+
+    END_OF("FIELD<T>::add(const FIELD & m, const FIELD& n)");
+    return result;
+}
+
+/*!
+     Overload substraction operator.
+     This operation is authorized only for compatible fields that have the same support.
+     The compatibility checking includes equality tests of the folowing data members:\n
+     - _support
+     - _numberOfComponents
+     - _numberOfValues
+     - _componentsTypes
+     - _MEDComponentsUnits.
+
+     The data members of the returned field are initialized, based on the first field, except for the name, 
+     which is the combination of the two field's names and the operator.
+     Advised Utilisation in C++ : <tt> FIELD<T> c = a - b; </tt> \n
+     In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
+     When using python, this operator calls the copy constructor in any case.
+     The user has to be aware that when using operator - in associatives expressions like
+     <tt> a = b - c - d -e; </tt> \n
+     no optimisation is performed : the evaluation of last expression requires the construction of
+     3 temporary fields.
+*/
+template <class T>
+const FIELD<T> FIELD<T>::operator-(const FIELD & m) const
+{
+    BEGIN_OF("FIELD<T>::operator-(const FIELD & m)");
+    FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
+
+    MED_EN::medModeSwitch mode;
+    if(this->getvalue()->getMode()==m.getvalue()->getMode() || this->getvalue()->isOtherCalculated())
+       mode=m.getvalue()->getMode();
+    else
+       mode=this->getvalue()->getMode();
+    
+    // Creation of the result - memory is allocated by FIELD constructor
+    FIELD<T> result(this->getSupport(),this->getNumberOfComponents(),mode);
+    //result._operation(*this,m,mode,"-"); // perform Atribute's initialization & substraction
+    result._operationInitialize(*this,m,"-"); // perform Atribute's initialization
+    result._sub_in_place(*this,m,mode); // perform substracion
+
+    END_OF("FIELD<T>::operator-(const FIELD & m)");
+    return result;
+}
+
+template <class T>
+const FIELD<T> FIELD<T>::operator-() const
+{
+    BEGIN_OF("FIELD<T>::operator-()");
+
+    MED_EN::medModeSwitch mode=this->getvalue()->getMode();
+    // Creation of the result - memory is allocated by FIELD constructor
+    FIELD<T> result(this->getSupport(),this->getNumberOfComponents(),mode);
+    // Atribute's initialization 
+    result.setName("- "+getName());
+    result.setComponentsNames(getComponentsNames());
+    // not yet implemented    setComponentType(getComponentType());
+    result.setComponentsDescriptions(getComponentsDescriptions());
+    result.setMEDComponentsUnits(getMEDComponentsUnits());
+    result.setComponentsUnits(getComponentsUnits());
+    result.setIterationNumber(getIterationNumber());
+    result.setTime(getTime());
+    result.setOrderNumber(getOrderNumber());
+    result.setValueType(getValueType());
+
+    const T* value1=getValue(mode); 
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (result.getValue(mode));
+    const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
+    const T* endV=value+size; // pointer to the end of value
+
+    for(;value!=endV; value1++,value++)
+       *value = -(*value1);
+    END_OF("FIELD<T>::operator-=(const FIELD & m)");
+    return result;
+}
+
+/*!  Overloaded Operator -=
+ *   Operations are directly performed in the first field's array.
+ *   This operation is authorized only for compatible fields that have the same support.
+ */
+template <class T>
+FIELD<T>& FIELD<T>::operator-=(const FIELD & m)
+{
+    BEGIN_OF("FIELD<T>::operator-=(const FIELD & m)");
+    FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
+
+    // We choose to keep *this mode, even if it may cost a re-calculation for m
+    MED_EN::medModeSwitch mode=this->getvalue()->getMode();
+    const T* value1=m.getValue(mode); // get pointers to the values we are adding
+
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (getValue(mode));
+    const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
+    const T* endV=value+size; // pointer to the end of value
+
+    for(;value!=endV; value1++,value++)
+       *value -= *value1;
+    // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
+    this->getvalue()->clearOtherMode();
+    END_OF("FIELD<T>::operator-=(const FIELD & m)");
+    return *this;
+}
+
+
+/*! Substraction of fields. Static member function.
+ *  The function return a pointer to a new created field that holds the substraction.
+ *  Data members are checked for compatibility and initialized.
+ *  The user is in charge of memory deallocation.
+ */
+template <class T>
+FIELD<T>* FIELD<T>::sub(const FIELD& m, const FIELD& n)
+{
+    BEGIN_OF("FIELD<T>::sub(const FIELD & m, const FIELD& n)");
+    FIELD_::_checkFieldCompatibility(m, n); // may throw exception
+
+    // Select mode : avoid if possible any calculation of other mode for fields m or *this
+    MED_EN::medModeSwitch mode;
+    if(m.getvalue()->getMode()==n.getvalue()->getMode() || n.getvalue()->isOtherCalculated())
+       mode=m.getvalue()->getMode();
+    else
+       mode=n.getvalue()->getMode();
+    
+    // Creation of a new field
+    FIELD<T>* result = new FIELD<T>(m.getSupport(),m.getNumberOfComponents(),mode);
+    result->_operationInitialize(m,n,"-"); // perform Atribute's initialization
+    result->_sub_in_place(m,n,mode); // perform substraction
+
+    END_OF("FIELD<T>::sub(const FIELD & m, const FIELD& n)");
+    return result;
+}
+
+/*!
+     Overload multiplication operator.
+     This operation is authorized only for compatible fields that have the same support.
+     The compatibility checking includes equality tests of the folowing data members:\n
+     - _support
+     - _numberOfComponents
+     - _numberOfValues
+     - _componentsTypes
+     - _MEDComponentsUnits.
+
+     The data members of the returned field are initialized, based on the first field, except for the name, 
+     which is the combination of the two field's names and the operator.
+     Advised Utilisation in C++ : <tt> FIELD<T> c = a * b; </tt> \n
+     In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
+     When using python, this operator calls the copy constructor in any case.
+     The user has to be aware that when using operator * in associatives expressions like
+     <tt> a = b * c * d *e; </tt> \n
+     no optimisation is performed : the evaluation of last expression requires the construction of
+     3 temporary fields.
+*/
+template <class T>
+const FIELD<T> FIELD<T>::operator*(const FIELD & m) const
+{
+    BEGIN_OF("FIELD<T>::operator*(const FIELD & m)");
+    FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
+
+    // Select mode : avoid if possible any calculation of other mode for fields m or *this
+    MED_EN::medModeSwitch mode;
+    if(this->getvalue()->getMode()==m.getvalue()->getMode() || this->getvalue()->isOtherCalculated())
+       mode=m.getvalue()->getMode();
+    else
+       mode=this->getvalue()->getMode();
+    
+    // Creation of the result - memory is allocated by FIELD constructor
+    FIELD<T> result(this->getSupport(),this->getNumberOfComponents(),mode);
+    //result._operation(*this,m,mode,"*"); // perform Atribute's initialization & multiplication
+    result._operationInitialize(*this,m,"*"); // perform Atribute's initialization
+    result._mul_in_place(*this,m,mode); // perform multiplication
+
+    END_OF("FIELD<T>::operator*(const FIELD & m)");
+    return result;
+}
+
+/*!  Overloaded Operator *=
+ *   Operations are directly performed in the first field's array.
+ *   This operation is authorized only for compatible fields that have the same support.
+ */
+template <class T>
+FIELD<T>& FIELD<T>::operator*=(const FIELD & m)
+{
+    BEGIN_OF("FIELD<T>::operator*=(const FIELD & m)");
+    FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
+
+    // We choose to keep *this mode, even if it may cost a re-calculation for m
+    MED_EN::medModeSwitch mode=this->getvalue()->getMode();
+    const T* value1=m.getValue(mode); // get pointers to the values we are adding
+
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (getValue(mode));
+    const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
+    const T* endV=value+size; // pointer to the end of value
+
+    for(;value!=endV; value1++,value++)
+       *value *= *value1;
+    // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
+    this->getvalue()->clearOtherMode();
+    END_OF("FIELD<T>::operator*=(const FIELD & m)");
+    return *this;
+}
+
+
+/*! Multiplication of fields. Static member function.
+ *  The function return a pointer to a new created field that holds the multiplication.
+ *  Data members are checked for compatibility and initialized.
+ *  The user is in charge of memory deallocation.
+ */
+template <class T>
+FIELD<T>* FIELD<T>::mul(const FIELD& m, const FIELD& n)
+{
+    BEGIN_OF("FIELD<T>::mul(const FIELD & m, const FIELD& n)");
+    FIELD_::_checkFieldCompatibility(m, n); // may throw exception
+
+    // Select mode : avoid if possible any calculation of other mode for fields m or *this
+    MED_EN::medModeSwitch mode;
+    if(m.getvalue()->getMode()==n.getvalue()->getMode() || n.getvalue()->isOtherCalculated())
+       mode=m.getvalue()->getMode();
+    else
+       mode=n.getvalue()->getMode();
+    
+    // Creation of a new field
+    FIELD<T>* result = new FIELD<T>(m.getSupport(),m.getNumberOfComponents(),mode);
+    result->_operationInitialize(m,n,"*"); // perform Atribute's initialization
+    result->_mul_in_place(m,n,mode); // perform multiplication
+
+    END_OF("FIELD<T>::mul(const FIELD & m, const FIELD& n)");
+    return result;
+}
+
+
+/*!
+     Overload division operator.
+     This operation is authorized only for compatible fields that have the same support.
+     The compatibility checking includes equality tests of the folowing data members:\n
+     - _support
+     - _numberOfComponents
+     - _numberOfValues
+     - _componentsTypes
+     - _MEDComponentsUnits.
+
+     The data members of the returned field are initialized, based on the first field, except for the name, 
+     which is the combination of the two field's names and the operator.
+     Advised Utilisation in C++ : <tt> FIELD<T> c = a / b; </tt> \n
+     In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
+     When using python, this operator calls the copy constructor in any case.
+     The user has to be aware that when using operator / in associatives expressions like
+     <tt> a = b / c / d /e; </tt> \n
+     no optimisation is performed : the evaluation of last expression requires the construction of
+     3 temporary fields.
+*/
+template <class T>
+const FIELD<T> FIELD<T>::operator/(const FIELD & m) const
+{
+    BEGIN_OF("FIELD<T>::operator/(const FIELD & m)");
+    FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
+
+    // Select mode : avoid if possible any calculation of other mode for fields m or *this
+    MED_EN::medModeSwitch mode;
+    if(this->getvalue()->getMode()==m.getvalue()->getMode() || this->getvalue()->isOtherCalculated())
+       mode=m.getvalue()->getMode();
+    else
+       mode=this->getvalue()->getMode();
+    
+    // Creation of the result - memory is allocated by FIELD constructor
+    FIELD<T> result(this->getSupport(),this->getNumberOfComponents(),mode);
+    //result._operation(*this,m,mode,"/"); // perform Atribute's initialization & division
+    result._operationInitialize(*this,m,"/"); // perform Atribute's initialization
+    result._div_in_place(*this,m,mode); // perform division
+
+    END_OF("FIELD<T>::operator/(const FIELD & m)");
+    return result;
+}
+
+
+/*!  Overloaded Operator /=
+ *   Operations are directly performed in the first field's array.
+ *   This operation is authorized only for compatible fields that have the same support.
+ */
+template <class T>
+FIELD<T>& FIELD<T>::operator/=(const FIELD & m)
+{
+    BEGIN_OF("FIELD<T>::operator/=(const FIELD & m)");
+    FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
+
+    // We choose to keep *this mode, even if it may cost a re-calculation for m
+    MED_EN::medModeSwitch mode=this->getvalue()->getMode();
+    const T* value1=m.getValue(mode); // get pointers to the values we are adding
+
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (getValue(mode));
+    const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
+    const T* endV=value+size; // pointer to the end of value
+
+    for(;value!=endV; value1++,value++)
+       *value /= *value1;
+    // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
+    this->getvalue()->clearOtherMode();
+    END_OF("FIELD<T>::operator/=(const FIELD & m)");
+    return *this;
+}
+
+
+/*! Division of fields. Static member function.
+ *  The function return a pointer to a new created field that holds the division.
+ *  Data members are checked for compatibility and initialized.
+ *  The user is in charge of memory deallocation.
+ */
+template <class T>
+FIELD<T>* FIELD<T>::div(const FIELD& m, const FIELD& n)
+{
+    BEGIN_OF("FIELD<T>::div(const FIELD & m, const FIELD& n)");
+    FIELD_::_checkFieldCompatibility(m, n); // may throw exception
+
+    // Select mode : avoid if possible any calculation of other mode for fields m or *this
+    MED_EN::medModeSwitch mode;
+    if(m.getvalue()->getMode()==n.getvalue()->getMode() || n.getvalue()->isOtherCalculated())
+       mode=m.getvalue()->getMode();
+    else
+       mode=n.getvalue()->getMode();
+    
+    // Creation of a new field
+    FIELD<T>* result = new FIELD<T>(m.getSupport(),m.getNumberOfComponents(),mode);
+    result->_operationInitialize(m,n,"/"); // perform Atribute's initialization
+    result->_div_in_place(m,n,mode); // perform division
+
+    END_OF("FIELD<T>::div(const FIELD & m, const FIELD& n)");
+    return result;
+}
+
+
+/*!
+  \if developper
+  This internal method initialize the members of a new field created to hold the result of the operation Op .
+  Initialization is based on the first field, except for the name, which is the combination of the two field's names
+  and the operator.
+  \endif
+*/
+template <class T>
+void FIELD<T>::_operationInitialize(const FIELD& m,const FIELD& n, char* Op)
+{
+    MESSAGE("Appel methode interne _add" << Op);
+
+    // Atribute's initialization (copy of the first field's attributes)
+    // Other data members (_support, _numberOfValues) are initialized in the field's constr.
+    setName(m.getName()+" "+Op+" "+n.getName());
+    setComponentsNames(m.getComponentsNames());
+    // not yet implemented    setComponentType(m.getComponentType());
+    setComponentsDescriptions(m.getComponentsDescriptions());
+    setMEDComponentsUnits(m.getMEDComponentsUnits());
+
+    // The following data member may differ from field m to n.
+    // The initialization is done based on the first field.
+    setComponentsUnits(m.getComponentsUnits());
+    setIterationNumber(m.getIterationNumber());
+    setTime(m.getTime());
+    setOrderNumber(m.getOrderNumber());
+    setValueType(m.getValueType());
+}
+
+
+/*!
+  \if developper
+  Internal method called by FIELD<T>::operator+ and FIELD<T>::add to perform addition "in place".
+  This method is applied to a just created field with medModeSwitch mode.
+  For this reason, the alternate mode doesn't need to be set to 0 after performing operation : 
+  it doesn't exist!
+  \endif
+*/
+template <class T>
+void FIELD<T>::_add_in_place(const FIELD& m,const FIELD& n, const MED_EN::medModeSwitch mode)
+{
+    // get pointers to the values we are adding
+    const T* value1=m.getValue(mode);
+    const T* value2=n.getValue(mode);
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (getValue(mode));
+
+    const int size=getNumberOfValues()*getNumberOfComponents();
+    SCRUTE(size);
+    const T* endV1=value1+size;
+    for(;value1!=endV1; value1++,value2++,value++)
+       *value=(*value1)+(*value2);
+}
+
+/*!
+  \if developper
+  Internal method called by FIELD<T>::operator- and FIELD<T>::sub to perform substraction "in place".
+  This method is applied to a just created field with medModeSwitch mode.
+  For this reason, the alternate mode doesn't need to be set to 0 after performing operation : 
+  it doesn't exist!
+  \endif
+*/
+template <class T>
+void FIELD<T>::_sub_in_place(const FIELD& m,const FIELD& n, const MED_EN::medModeSwitch mode)
+{
+    // get pointers to the values we are adding
+    const T* value1=m.getValue(mode);
+    const T* value2=n.getValue(mode);
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (getValue(mode));
+
+    const int size=getNumberOfValues()*getNumberOfComponents();
+    SCRUTE(size);
+    const T* endV1=value1+size;
+    for(;value1!=endV1; value1++,value2++,value++)
+       *value=(*value1)-(*value2);
+}
+
+/*!
+  \if developper
+  Internal method called by FIELD<T>::operator* and FIELD<T>::mul to perform multiplication "in place".
+  This method is applied to a just created field with medModeSwitch mode.
+  For this reason, the alternate mode doesn't need to be set to 0 after performing operation : 
+  it doesn't exist!
+  \endif
+*/
+template <class T>
+void FIELD<T>::_mul_in_place(const FIELD& m,const FIELD& n, const MED_EN::medModeSwitch mode)
+{
+    // get pointers to the values we are adding
+    const T* value1=m.getValue(mode);
+    const T* value2=n.getValue(mode);
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (getValue(mode));
+
+    const int size=getNumberOfValues()*getNumberOfComponents();
+    SCRUTE(size);
+    const T* endV1=value1+size;
+    for(;value1!=endV1; value1++,value2++,value++)
+       *value=(*value1)*(*value2);
+}
+
+/*!
+  \if developper
+  Internal method called by FIELD<T>::operator/ and FIELD<T>::div to perform division "in place".
+  This method is applied to a just created field with medModeSwitch mode.
+  For this reason, the alternate mode doesn't need to be set to 0 after performing operation : 
+  it doesn't exist!
+  \endif
+*/
+template <class T>
+void FIELD<T>::_div_in_place(const FIELD& m,const FIELD& n, const MED_EN::medModeSwitch mode) throw (MEDEXCEPTION)
+{
+    // get pointers to the values we are adding
+    const T* value1=m.getValue(mode);
+    const T* value2=n.getValue(mode);
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (getValue(mode));
+
+    const int size=getNumberOfValues()*getNumberOfComponents();
+    SCRUTE(size);
+    const T* endV1=value1+size;
+    for(;value1!=endV1; value1++,value2++,value++){
+      if ( *value2 == 0 ) {
+         string diagnosis;
+         diagnosis="FIELD<T>::_div_in_place(...) : Divide by zero !";
+         throw MEDEXCEPTION(diagnosis.c_str());
+       }
+       *value=(*value1)/(*value2);
+    }
+}
+
+/*!  Return Max Norm 
+ */
+template <class T> double FIELD<T>::normMax() const throw (MEDEXCEPTION)
+{
+    const T* value=getValue(getvalue()->getMode()); // get pointer to the values
+    const int size=getNumberOfValues()*getNumberOfComponents();
+    if (size <= 0) // Size of array has to be strictly positive
+    {
+       string diagnosis;
+       diagnosis="FIELD<T>::normMax() : cannot compute the norm of "+getName()+
+           " : it size is non positive!";
+       throw MEDEXCEPTION(diagnosis.c_str());
+    }
+    const T* lastvalue=value+size; // get pointer just after last value
+    const T* pMax=value; // pointer to the max value
+    const T* pMin=value; // pointer to the min value
+
+    // get pointers to the max & min value of array
+    while ( ++value != lastvalue )
+    {
+       if ( *pMin > *value )
+           pMin=value;
+       if ( *pMax < *value )
+           pMax=value;
+    }
+
+    T Max= *pMax>(T) 0 ? *pMax : -*pMax; // Max=abs(*pMax)
+    T Min= *pMin>(T) 0 ? *pMin : -*pMin; // Min=abs(*pMin)
+
+    return Max>Min ? static_cast<double>(Max) : static_cast<double>(Min);
+}
+
+/*!  Return Euclidien norm 
+ */
+template <class T> double FIELD<T>::norm2() const throw (MEDEXCEPTION)
+{
+    const T* value=this->getValue(this->getvalue()->getMode()); // get const pointer to the values
+    const int size=getNumberOfValues()*getNumberOfComponents(); // get size of array
+    if (size <= 0) // Size of array has to be strictly positive
+    {
+       string diagnosis;
+       diagnosis="FIELD<T>::norm2() : cannot compute the norm of "+getName()+
+           " : it size is non positive!";
+       throw MEDEXCEPTION(diagnosis.c_str());
+    }
+    const T* lastvalue=value+size; // point just after last value
+    
+    T result((T)0); // init
+    for( ; value!=lastvalue ; ++value)
+       result += (*value) * (*value);
+    
+    return std::sqrt(static_cast<double> (result));
+}
+
+
+/*!  Apply to each (scalar) field component the template parameter T_function, 
+ *   which is a pointer to function.
+ *   Since the pointer is known at compile time, the function is inlined into the inner loop!
+ *   calculation is done "in place".
+ *   Use examples : 
+ *   
+ *   \code  myField.applyFunc<std::sqrt>();  // apply sqare root function \endcode
+ *     \code myField.applyFunc<myFunction>(); // apply your own created function \endcode
+ */
+template <class T> template <T T_function(T)> 
+void FIELD<T>::applyFunc()
+{
+    MED_EN::medModeSwitch mode=getvalue()->getMode();
+
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (getValue(mode));
+    const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
+
+    if (size>0) // for a negative size, there is nothing to do
+    {
+       const T* lastvalue=value+size; // pointer to the end of value
+       for(;value!=lastvalue; ++value) // apply linear transformation
+           *value = T_function(*value);
+       // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
+       getvalue()->clearOtherMode();
+    }
+}
+    
+  
+/*!  Apply to each (scalar) field component the linear function x -> ax+b.
+ *   calculation is done "in place".
+ */
+template <class T> void FIELD<T>::applyLin(T a, T b)
+{
+    MED_EN::medModeSwitch mode=getvalue()->getMode();
+
+    // get a non const pointer to the inside array of values and perform operation in place
+    T * value=const_cast<T *> (getValue(mode));
+    const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
+
+    if (size>0) // for a negative size, there is nothing to do
+    {
+       const T* lastvalue=value+size; // pointer to the end of value
+       for(;value!=lastvalue; ++value) // apply linear transformation
+           *value = a*(*value)+b;
+       // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
+       getvalue()->clearOtherMode();
+    }
+}
+
+
+/*!
+ *   Return a pointer to a new field that holds the scalar product. Static member function.
+ *   This operation is authorized only for compatible fields that have the same support.
+ *   The compatibility checking includes equality tests of the folowing data members:\n
+ *   - _support
+ *   - _numberOfComponents
+ *   - _numberOfValues
+ *   - _componentsTypes
+ *   - _MEDComponentsUnits.
+ *   Data members are initialized.
+ *   The new field point to the same support and has one component.
+ *   Each value of it is the scalar product of the two argument's fields.
+ *   The user is in charge of memory deallocation.
+ */
+template <class T> FIELD<T>* FIELD<T>::scalarProduct(const FIELD & m, const FIELD & n)
+{
+    FIELD_::_checkFieldCompatibility( m, n); // may throw exception
+    // we need a MED_FULL_INTERLACE representation of m & n to compute the scalar product
+    const MED_EN::medModeSwitch mode=MED_EN::MED_FULL_INTERLACE; 
+
+    const int numberOfElements=m.getNumberOfValues(); // strictly positive
+    const int NumberOfComponents=m.getNumberOfComponents(); // strictly positive
+
+    // Creation & init of a the result field on the same suppot, with one component
+    FIELD<T>* result = new FIELD<T>(m.getSupport(),1,mode);
+    result->setName( "scalarProduct ( " + m.getName() + " , " + n.getName() + " )" );
+    result->setIterationNumber(m.getIterationNumber());
+    result->setTime(m.getTime());
+    result->setOrderNumber(m.getOrderNumber());
+    result->setValueType(m.getValueType());
+
+    const T* value1=m.getValue(mode); // get const pointer to the values
+    const T* value2=n.getValue(mode); // get const pointer to the values
+    // get a non const pointer to the inside array of values and perform operation
+    T * value=const_cast<T *> (result->getValue(mode));
+    
+    const T* lastvalue=value+numberOfElements; // pointing just after last value of result
+    for ( ; value!=lastvalue ; ++value ) // loop on all elements
+    {
+       *value=(T)0; // initialize value
+       const T* endofRow=value1+NumberOfComponents; // pointing just after end of row
+       for ( ; value1 != endofRow; ++value1, ++value2) // computation of dot product
+           *value += (*value1) * (*value2);
+    }
+    return result;
+}
+
+/*!  Return L2 Norm  of the field's component.
+ *   Cannot be applied to a field with a support on nodes.
+ *   If the optional p_field_volume argument is furnished, the volume is not re-calculated.
+ */
+template <class T> double FIELD<T>::normL2(int component, const FIELD<double> * p_field_volume) const
+{
+    _checkNormCompatibility(p_field_volume); // may throw exception
+    if ( component<1 || component>getNumberOfComponents() )
+       throw MEDEXCEPTION(STRING("FIELD<T>::normL2() : The component argument should be between 1 and the number of components"));
+
+    const FIELD<double> * p_field_size=p_field_volume;
+    if(!p_field_volume) // if the user don't supply the volume
+       p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
+
+    // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
+    const double* vol=p_field_size->getValue(MED_FULL_INTERLACE); 
+    const T* value=getValueI( MED_NO_INTERLACE, component); // get pointer to the component's values
+    const T* lastvalue=value+getNumberOfValues(); // pointing just after the end of column
+
+    double integrale=0.0;
+    double totVol=0.0;
+    for (; value!=lastvalue ; ++value ,++vol) 
+    {
+       integrale += static_cast<double>((*value) * (*value)) * (*vol);
+       totVol+=*vol;
+    }
+
+    if(!p_field_volume) // if the user didn't supply the volume
+       delete p_field_size; // delete temporary volume field
+    if( totVol <= 0)
+       throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
+
+    return integrale/totVol;
+}
+
+/*!  Return L2 Norm  of the field.
+ *   Cannot be applied to a field with a support on nodes.
+ *   If the optional p_field_volume argument is furnished, the volume is not re-calculated.
+ */
+template <class T> double FIELD<T>::normL2(const FIELD<double> * p_field_volume) const
+{
+    _checkNormCompatibility(p_field_volume); // may throw exception
+    const FIELD<double> * p_field_size=p_field_volume;
+    if(!p_field_volume) // if the user don't supply the volume
+       p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
+
+    // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
+    const double* vol=p_field_size->getValue(MED_FULL_INTERLACE); 
+    const double* lastvol=vol+getNumberOfValues(); // pointing just after the end of vol
+    const T* value=getValue( MED_NO_INTERLACE); // get pointer to the field's values
+
+    double totVol=0.0;
+    const double* p_vol=vol;
+    for (p_vol=vol; p_vol!=lastvol ; ++p_vol) // calculate total volume
+       totVol+=*p_vol;
+    
+    double integrale=0.0;
+    for (int i=1; i<=getNumberOfComponents(); ++i) // compute integral on all components
+       for (p_vol=vol; p_vol!=lastvol ; ++value ,++p_vol) 
+           integrale += static_cast<double>((*value) * (*value)) * (*p_vol);
+
+    if(!p_field_volume) // if the user didn't supply the volume
+       delete p_field_size; // delete temporary volume field
+    if( totVol <= 0)
+       throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
+
+    return integrale/totVol;
+}
+
+/*!  Return L1 Norm  of the field's component.
+ *   Cannot be applied to a field with a support on nodes.
+ *   If the optional p_field_volume argument is furnished, the volume is not re-calculated.
+ */
+template <class T> double FIELD<T>::normL1(int component, const FIELD<double> * p_field_volume) const
+{
+    _checkNormCompatibility(p_field_volume); // may throw exception
+    if ( component<1 || component>getNumberOfComponents() )
+       throw MEDEXCEPTION(STRING("FIELD<T>::normL2() : The component argument should be between 1 and the number of components"));
+
+    const FIELD<double> * p_field_size=p_field_volume;
+    if(!p_field_volume) // if the user don't supply the volume
+       p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
+
+    // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
+    const double* vol=p_field_size->getValue(MED_FULL_INTERLACE); 
+    const T* value=getValueI( MED_NO_INTERLACE, component); // get pointer to the component's values
+    const T* lastvalue=value+getNumberOfValues(); // pointing just after the end of column
+
+    double integrale=0.0;
+    double totVol=0.0;
+    for (; value!=lastvalue ; ++value ,++vol) 
+    {
+       integrale += std::abs( static_cast<double>(*value) ) * (*vol);
+       totVol+=*vol;
+    }
+
+    if(!p_field_volume) // if the user didn't supply the volume
+       delete p_field_size; // delete temporary volume field
+    if( totVol <= 0)
+       throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
+
+    return integrale/totVol;
+}
+
+/*!  Return L1 Norm  of the field.
+ *   Cannot be applied to a field with a support on nodes.
+ *   If the optional p_field_volume argument is furnished, the volume is not re-calculated.
+ */
+template <class T> double FIELD<T>::normL1(const FIELD<double> * p_field_volume) const
+{
+    _checkNormCompatibility(p_field_volume); // may throw exception
+    const FIELD<double> * p_field_size=p_field_volume;
+    if(!p_field_volume) // if the user don't supply the volume
+       p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
+
+    // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
+    const double* vol=p_field_size->getValue(MED_FULL_INTERLACE); 
+    const double* lastvol=vol+getNumberOfValues(); // pointing just after the end of vol
+    const T* value=getValue( MED_NO_INTERLACE); // get pointer to the field's values
+
+    double totVol=0.0;
+    const double* p_vol=vol;
+    for (p_vol=vol; p_vol!=lastvol ; ++p_vol) // calculate total volume
+       totVol+=*p_vol;
+    
+    double integrale=0.0;
+    for (int i=1; i<=getNumberOfComponents(); ++i) // compute integral on all components
+       for (p_vol=vol; p_vol!=lastvol ; ++value ,++p_vol) 
+           integrale += std::abs( static_cast<double>(*value) ) * (*p_vol);
+
+    if(!p_field_volume) // if the user didn't supply the volume
+       delete p_field_size; // delete temporary volume field
+    if( totVol <= 0)
+       throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
+
+    return integrale/totVol;
+}
+
+
+
+
+/*!
+  Constructor with parameters; the object is set via a file and its associated
+  driver. For the moment only the MED_DRIVER is considered and if the last two
+  argument (iterationNumber and orderNumber) are not set; their default value
+  is -1. If the field fieldDriverName with the iteration number
+  iterationNumber and the order number orderNumber does not exist in the file
+  fieldDriverName; the constructor raises an exception.
+*/
+template <class T> FIELD<T>::FIELD(const SUPPORT * Support,
+                                  driverTypes driverType,
+                                  const string & fileName/*=""*/,
+                                  const string & fieldDriverName/*=""*/,
+                                  const int iterationNumber,
+                                  const int orderNumber)
+  throw (MEDEXCEPTION)
+{
+  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) : ";
+
+  int current;
+
+  BEGIN_OF(LOC);
+
+  init();
+
+  _support = Support;
+  _value = (MEDARRAY<T>*)NULL;
+
+  _iterationNumber = iterationNumber;
+  _time = 0.0;
+  _orderNumber = orderNumber;
+
+  current = addDriver(driverType,fileName,fieldDriverName,MED_LECT);
+
+//   switch(driverType)
+//     {
+//     case MED_DRIVER :
+//       {
+//     MED_FIELD_RDONLY_DRIVER<T> myDriver(fileName,this);
+//     myDriver.setFieldName(fieldDriverName);
+//     current = addDriver(myDriver);
+//     break;
+//       }
+//   current = addDriver(driverType,fileName,fieldDriverName);
+//   switch(_drivers[current]->getAccessMode() ) {
+//   case MED_WRONLY : {
+//     MESSAGE("FIELD<T>::FIELD(driverTypes driverType, .....) : driverType must have a MED_RDONLY or MED_RDWR accessMode");
+//     rmDriver(current);
+//     break;}
+//   default : {
+//   }
+//   }
+//     default :
+//       {
+//     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Driver type unknown : can't create driver!"));
+//     break;
+//       }
+//     }
+
+  _drivers[current]->open();
+  _drivers[current]->read();
+  _drivers[current]->close();
+
+  END_OF(LOC);
+}
+
+/*!
+  Destructor.
+*/
+template <class T> FIELD<T>::~FIELD()
+{
   BEGIN_OF(" Destructeur FIELD<T>::~FIELD()");
+  SCRUTE(this);
   if (_value) delete _value;
   END_OF(" Destructeur FIELD<T>::~FIELD()");
 }
 
+/*!
+  
+*/
 template <class T> void FIELD<T>::allocValue(const int NumberOfComponents)
 {
-  BEGIN_OF("void FIELD<T>::allocValue(const int NumberOfComponents)");
+  const char* LOC = "FIELD<T>::allocValue(const int NumberOfComponents)" ;
+  BEGIN_OF(LOC);
 
   _numberOfComponents = NumberOfComponents ;
   if (_componentsTypes == NULL)
@@ -433,10 +1715,12 @@ template <class T> void FIELD<T>::allocValue(const int NumberOfComponents)
   }
 
   try {
-    int length = _support->getNumberOfElements(MED_ALL_ELEMENTS);
-    MESSAGE("FIELD : constructeur : "<<length <<" et "<< NumberOfComponents);
-    
-    _value = new MEDARRAY<T>::MEDARRAY(NumberOfComponents,length);
+    _numberOfValues = _support->getNumberOfElements(MED_ALL_ELEMENTS);
+    MESSAGE(LOC <<" : "<<_numberOfValues <<" et "<< NumberOfComponents);
+
+    _value = new MEDARRAY<T>(_numberOfComponents,_numberOfValues);
+
+    _isRead = true ;
   }
   catch (MEDEXCEPTION &ex) {
     MESSAGE("No value defined, problem with NumberOfComponents (and may be _support) size of MEDARRAY<T>::_value !");
@@ -447,6 +1731,9 @@ template <class T> void FIELD<T>::allocValue(const int NumberOfComponents)
   END_OF("void FIELD<T>::allocValue(const int NumberOfComponents)");
 }
 
+/*!
+  
+*/
 template <class T> void FIELD<T>::allocValue(const int NumberOfComponents, const int LengthValue)
 {
   BEGIN_OF("void FIELD<T>::allocValue(const int NumberOfComponents,const int LengthValue)");
@@ -467,18 +1754,24 @@ template <class T> void FIELD<T>::allocValue(const int NumberOfComponents, const
   }
 
   MESSAGE("FIELD : constructeur : "<<LengthValue <<" et "<< NumberOfComponents);
-    
-  _value = new MEDARRAY<T>::MEDARRAY(NumberOfComponents,LengthValue);
+  _numberOfValues = LengthValue ;
+  _value = new MEDARRAY<T>(_numberOfComponents,_numberOfValues);
+  _isRead = true ;
 
   SCRUTE(_value);
   END_OF("void FIELD<T>::allocValue(const int NumberOfComponents,const int LengthValue)");
 }
 
+/*!
+  
+*/
 template <class T> void FIELD<T>::deallocValue()
 {
   BEGIN_OF("void FIELD<T>::deallocValue()");
-
-  delete _value;
+  _numberOfValues = 0 ;
+  _numberOfComponents = 0 ;
+  if (_value != NULL)
+    delete _value;
 
   END_OF("void FIELD<T>::deallocValue()");
 }
@@ -487,149 +1780,417 @@ template <class T> void FIELD<T>::deallocValue()
 // Methodes Inline
 // -----------------
 
+/*!
+  Create the specified driver and return its index reference to path to 
+  read or write methods.
+*/
 
-template <class T>       FIELD<T>::INSTANCE_DE<MED_FIELD_RDWR_DRIVER<T> >     FIELD<T>::inst_med  ;
-template <class T> const FIELD<T>::INSTANCE * const FIELD<T>::instances[] = { &FIELD<T>::inst_med } ;
-
-
-template <class T> int FIELD<T>::addDriver(driverTypes driverType, 
-                                          const string & fileName="Default File Name.med",
-                                          const string & driverName="Default Field Name")
+template <class T> int FIELD<T>::addDriver(driverTypes driverType,
+                                          const string & fileName/*="Default File Name.med"*/,
+                                          const string & driverName/*="Default Field Name"*/,
+                                          MED_EN::med_mode_acces access)
 {
-  const char * LOC = "FIELD<T>::addDriver(driverTypes driverType, const string & fileName=\"Default File Name.med\",const string & driverName=\"Default Field Name\") : ";
-  
+  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) : ";
+
   GENDRIVER * driver;
-  int current;
 
   BEGIN_OF(LOC);
-  
-  driver = instances[driverType]->run(fileName, this) ;
+
+  SCRUTE(driverType);
+
+  driver = DRIVERFACTORY::buildDriverForField(driverType,fileName,this,access);
+
   _drivers.push_back(driver);
-  current = _drivers.size()-1;
-  
+
+  int current = _drivers.size()-1;
+
   _drivers[current]->setFieldName(driverName);
-  return current;
 
   END_OF(LOC);
 
+  return current;
 }
 
+
+/*!
+  Duplicate the given driver and return its index reference to path to 
+  read or write methods.
+*/
 template <class T> inline int FIELD<T>::addDriver (GENDRIVER & driver )
 {
   const char * LOC = "FIELD<T>::addDriver(GENDRIVER &) : ";
+  int current;
+
   BEGIN_OF(LOC);
 
-  _drivers.push_back(&driver);
-  return _drivers.size() -1 ;
+  // duplicate driver to delete it with destructor !
+  GENDRIVER * newDriver = driver.copy() ;
+
+  _drivers.push_back(newDriver);
 
+  current = _drivers.size()-1;
+  SCRUTE(current);
+  driver.setId(current); 
+
+  MESSAGE(LOC << " je suis la 1");
   END_OF(LOC);
+  MESSAGE(LOC << " je suis la 2");
+
+  return current ;
 };
 
-template <class T> void FIELD<T>::rmDriver (int index=0)
+/*!
+  Remove the driver referenced by its index.
+*/
+template <class T> void FIELD<T>::rmDriver (int index/*=0*/)
 {
   const char * LOC = "FIELD<T>::rmDriver (int index=0): ";
   BEGIN_OF(LOC);
-  
+
   if ( _drivers[index] ) {
-    //_drivers.erase(&_drivers[index]); 
+    //_drivers.erase(&_drivers[index]);
     // why not ????
     MESSAGE ("detruire");
   }
   else
-    throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
-                                     << "The index given is invalid, index must be between  0 and  |" 
-                                     << _drivers.size() 
+    throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
+                                     << "The <index given is invalid, index must be between  0 and  |"
+                                     << _drivers.size()
                                      )
-                          );   
-  
+                          );
+
   END_OF(LOC);
 }
-  
-template <class T> inline  void FIELD<T>::read(int index=0)  
-{  
+
+/*!
+  Read FIELD in the file specified in the driver given by its index.
+*/
+template <class T> inline  void FIELD<T>::read(int index/*=0*/)
+{
   const char * LOC = "FIELD<T>::read(int index=0) : ";
   BEGIN_OF(LOC);
 
   if ( _drivers[index] ) {
-    _drivers[index]->open();   
+    _drivers[index]->open();
     _drivers[index]->read();
     _drivers[index]->close();
   }
   else
-    throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
-                                     << "The index given is invalid, index must be between  0 and |" 
-                                     << _drivers.size() 
+    throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
+                                     << "The index given is invalid, index must be between  0 and |"
+                                     << _drivers.size()
                                      )
-                          ); 
+                          );
   END_OF(LOC);
 }
 
-template <class T> inline void FIELD<T>::write(int index=0, const string & driverName = "") 
-{ 
+/*!
+  Write FIELD in the file specified in the driver given by its index.
+*/
+template <class T> inline void FIELD<T>::write(int index/*=0*/, const string & driverName /*= ""*/)
+{
   const char * LOC = "FIELD<T>::write(int index=0, const string & driverName = \"\") : ";
   BEGIN_OF(LOC);
 
   if( _drivers[index] ) {
-    _drivers[index]->open();   
-    if (driverName != "") _drivers[index]->setFieldName(driverName); 
+    _drivers[index]->open();
+    if (driverName != "") _drivers[index]->setFieldName(driverName);
     _drivers[index]->write();
     _drivers[index]->close();
-  } 
+  }
+  else
+    throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
+                                     << "The index given is invalid, index must be between  0 and |"
+                                     << _drivers.size()
+                                     )
+                          );
+  END_OF(LOC);
+}
+
+/*!
+  Write FIELD in the file specified in the driver given by its index. Use this
+  method for ASCII drivers (e.g. VTK_DRIVER)
+*/
+template <class T> inline void FIELD<T>::writeAppend(int index/*=0*/, const string & driverName /*= ""*/)
+{
+  const char * LOC = "FIELD<T>::write(int index=0, const string & driverName = \"\") : ";
+  BEGIN_OF(LOC);
+
+  if( _drivers[index] ) {
+    _drivers[index]->openAppend();
+    if (driverName != "") _drivers[index]->setFieldName(driverName);
+    _drivers[index]->writeAppend();
+    _drivers[index]->close();
+  }
   else
-    throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
-                                     << "The index given is invalid, index must be between  0 and |" 
-                                     << _drivers.size() 
+    throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
+                                     << "The index given is invalid, index must be between  0 and |"
+                                     << _drivers.size()
                                      )
-                          ); 
+                          );
   END_OF(LOC);
 }
 
-template <class T> inline void FIELD<T>::write(const GENDRIVER & genDriver) 
-{ 
+/*!
+  \internal
+  Write FIELD with the driver which is equal to the given driver.
+
+  Use by MED object.
+*/
+template <class T> inline void FIELD<T>::write(const GENDRIVER & genDriver)
+{
   const char * LOC = " FIELD<T>::write(const GENDRIVER &) : ";
   BEGIN_OF(LOC);
 
-  for (int index=0; index < _drivers.size(); index++ )
-    if ( *_drivers[index] == genDriver ) { 
-      _drivers[index]->open();   
-      _drivers[index]->write(); 
+  for (unsigned int index=0; index < _drivers.size(); index++ )
+    if ( *_drivers[index] == genDriver ) {
+      _drivers[index]->open();
+      _drivers[index]->write();
       _drivers[index]->close();
     }
-  
+
   END_OF(LOC);
-} 
 
-template <class T> inline void FIELD<T>::setValue(MEDARRAY<T> *Value)  
-{ 
-  _value=Value ;  
 }
-template <class T> inline T* FIELD<T>::getValue(medModeSwitch Mode) const 
-{ 
-  return _value->get(Mode) ; 
+
+/*!
+  \internal
+  Write FIELD with the driver which is equal to the given driver.
+
+  Use by MED object. Use this method for ASCII drivers (e.g. VTK_DRIVER).
+*/
+template <class T> inline void FIELD<T>::writeAppend(const GENDRIVER & genDriver)
+{
+  const char * LOC = " FIELD<T>::write(const GENDRIVER &) : ";
+  BEGIN_OF(LOC);
+
+  for (unsigned int index=0; index < _drivers.size(); index++ )
+    if ( *_drivers[index] == genDriver ) {
+      _drivers[index]->openAppend();
+      _drivers[index]->writeAppend();
+      _drivers[index]->close();
+    }
+
+  END_OF(LOC);
+
 }
-template <class T> inline T* FIELD<T>::getValueI(medModeSwitch Mode,int i) const       
+
+/*!
+  \internal
+  Read FIELD with the driver which is equal to the given driver.
+
+  Use by MED object.
+*/
+template <class T> inline void FIELD<T>::read(const GENDRIVER & genDriver)
 {
-  return _value->getI(Mode,i) ; 
+  const char * LOC = " FIELD<T>::read(const GENDRIVER &) : ";
+  BEGIN_OF(LOC);
+
+  for (unsigned int index=0; index < _drivers.size(); index++ )
+    if ( *_drivers[index] == genDriver ) {
+      _drivers[index]->open();
+      _drivers[index]->read();
+      _drivers[index]->close();
+    }
+
+  END_OF(LOC);
+
+}
+
+/*!
+  \if developper
+  Destroy the MEDARRAY<T> in FIELD and put the new one without copy.
+  \endif
+*/
+template <class T> inline void FIELD<T>::setValue(MEDARRAY<T> *Value)
+{
+  if (NULL != _value) delete _value ;
+  _value=Value ;
+}
+
+/*!
+  \if developper
+  Return a reference to  the MEDARRAY<T> in FIELD.
+  \endif  
+*/
+template <class T> inline MEDARRAY<T>* FIELD<T>::getvalue() const
+{
+  return _value ;
+}
+
+/*!
+  Return the actual length of the reference to values array returned by getValue.
+*/
+template <class T> inline int FIELD<T>::getValueLength(MED_EN::medModeSwitch Mode) const{
+  return _numberOfComponents*_numberOfValues;
+}
+
+/*!
+  Return a reference to values array to read them.
+*/
+template <class T> inline const T* FIELD<T>::getValue(MED_EN::medModeSwitch Mode) const
+{
+  return _value->get(Mode) ;
+}
+
+/*!
+  Return a reference to i^{th} row or column - component - (depend on Mode value)
+  of FIELD values array.
+*/
+template <class T> inline const T* FIELD<T>::getValueI(MED_EN::medModeSwitch Mode,int i) const
+{
+ if ( Mode == MED_EN::MED_FULL_INTERLACE )
+ {
+        return _value->getRow(i) ;
+ }
+ ASSERT (  Mode == MED_EN::MED_NO_INTERLACE);
+ return _value->getColumn(i);
 }
-template <class T> inline T FIELD<T>::getValueIJ(int i,int j) const 
+
+/*!
+  Return the value of i^{th} element and j^{th} component.
+*/
+template <class T> inline T FIELD<T>::getValueIJ(int i,int j) const
 {
-  return _value->getIJ(i,j) ; 
+  return _value->getIJ(i,j) ;
 }
 
-template <class T> inline void FIELD<T>::setValue(medModeSwitch mode, T* value)
+/*!
+  Copy new values array in FIELD according to the given mode.
+
+  Array must have right size. If not results are unpredicable.
+*/
+template <class T> inline void FIELD<T>::setValue(MED_EN::medModeSwitch mode, T* value)
 {
   _value->set(mode,value);
 }
 
-template <class T> inline void FIELD<T>::setValueI(medModeSwitch mode, int i, T* value)
+/*!
+  Update values array in FIELD with the given ones according to specified mode.
+*/
+template <class T> inline void FIELD<T>::setValueI(MED_EN::medModeSwitch mode, int i, T* value)
 {
-  _value->setI(mode,i,value);
+  // PROVISOIRE :
+  if (MED_EN::MED_FULL_INTERLACE == mode)
+    _value->setI(i,value);
+  else if (MED_EN::MED_NO_INTERLACE == mode)
+    _value->setJ(i,value);
+  else
+    throw MEDEXCEPTION(LOCALIZED("FIELD<T>::setValueI : bad medModeSwitch")) ;
 }
 
+/*!
+  Set the value of i^{th} element and j^{th} component with the given one.
+*/
 template <class T> inline void FIELD<T>::setValueIJ(int i, int j, T value)
 {
   _value->setIJ(i,j,value);
 }
 
+/*
+  METHODS
+*/
+
+/*!
+  Fill values array with volume values.
+*/
+template <class T> void FIELD<T>::getVolume() const throw (MEDEXCEPTION)
+{
+  const char * LOC = "FIELD<double>::getVolume() const : ";
+  BEGIN_OF(LOC);
+
+  // The field has to be initilised by a non empty support and a
+  // number of components = 1 and its value type has to be set to MED_REEL64
+  // (ie a FIELD<double>)
+
+  if ((_support == (SUPPORT *) NULL) || (_numberOfComponents != 1) || (_valueType != MED_REEL64))
+      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"));
+
+  END_OF(LOC);
+}
+
+/*!
+  Fill values array with area values.
+*/
+template <class T> void FIELD<T>::getArea() const throw (MEDEXCEPTION)
+{
+  const char * LOC = "FIELD<double>::getArea() const : ";
+  BEGIN_OF(LOC);
+
+  // The field has to be initilised by a non empty support and a
+  // number of components = 1 and its value type has to be set to MED_REEL64
+  // (ie a FIELD<double>)
+
+  if ((_support == (SUPPORT *) NULL) || (_numberOfComponents != 1) || (_valueType != MED_REEL64))
+      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"));
+
+  END_OF(LOC);
+}
+
+/*!
+  Fill values array with length values.
+*/
+template <class T> void FIELD<T>::getLength() const throw (MEDEXCEPTION)
+{
+  const char * LOC = "FIELD<double>::getLength() const : ";
+  BEGIN_OF(LOC);
+
+  // The field has to be initilised by a non empty support and a
+  // number of components = 1 and its value type has to be set to MED_REEL64
+  // (ie a FIELD<double>)
+
+  if ((_support == (SUPPORT *) NULL) || (_numberOfComponents != 1) || (_valueType != MED_REEL64))
+      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"));
+
+  END_OF(LOC);
+}
+
+/*!
+  Fill values array with normal values.
+*/
+template <class T> void FIELD<T>::getNormal() const throw (MEDEXCEPTION)
+{
+  const char * LOC = "FIELD<double>::getNormal() const : ";
+  BEGIN_OF(LOC);
+
+  // The field has to be initilised by a non empty support and a
+  // number of components = 1 and its value type has to be set to MED_REEL64
+  // (ie a FIELD<double>)
+
+  if (_support == (SUPPORT *) NULL)
+      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"));
+
+  int dim_space = _support->getMesh()->getSpaceDimension();
+
+  if ((_numberOfComponents != dim_space) || (_valueType != MED_REEL64))
+      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"));
+
+  END_OF(LOC);
+}
+
+/*!
+  Fill values array with barycenter values.
+*/
+template <class T> void FIELD<T>::getBarycenter() const throw (MEDEXCEPTION)
+{
+  const char * LOC = "FIELD<double>::getBarycenter() const : ";
+  BEGIN_OF(LOC);
+
+  // The field has to be initilised by a non empty support and a number of
+  //components = space dimension and its value type has to be set to MED_REEL64
+  // (ie a FIELD<double>)
+
+  if (_support == (SUPPORT *) NULL)
+      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"));
+
+  int dim_space = _support->getMesh()->getSpaceDimension();
+
+  if ((_numberOfComponents != dim_space) || (_valueType != MED_REEL64))
+      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"));
+
+  END_OF(LOC);
+}
+
+}//End namespace MEDMEM
+
 #endif /* FIELD_HXX */