Salome HOME
correct a small bug appearing when using the gcc 3.2.1.
[modules/med.git] / src / MEDMEM / MEDMEM_Field.hxx
index 419c10a4dff73742efa841bc05fd942eff878fe4..f086d493af8a2a425f7e495ed249493c8990ed76 100644 (file)
@@ -1,29 +1,3 @@
-//  MED MEDMEM : MED files in memory
-//
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
-//
-//
-//
-//  File   : MEDMEM_Field.hxx
-//  Module : MED
-
 /*
  File Field.hxx
  $Header$
@@ -33,6 +7,8 @@
 #define FIELD_HXX
 
 #include <vector>
+#include <algorithm>
+#include <cmath>
 
 #include "utilities.h"
 #include "MEDMEM_Exception.hxx"
@@ -46,6 +22,9 @@
 #include "MEDMEM_MedFieldDriver.hxx"
 #include "MEDMEM_MedMedDriver.hxx"
 
+#include "MEDMEM_VtkFieldDriver.hxx"
+#include "MEDMEM_VtkMedDriver.hxx"
+
 using namespace MED_EN;
 
 /*!
@@ -57,6 +36,7 @@ using namespace MED_EN;
 
 */
 
+namespace MEDMEM {
 class FIELD_    // GENERIC POINTER TO a template <class T> class FIELD
 {
 protected:
@@ -143,9 +123,17 @@ protected:
   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_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:
 
@@ -153,6 +141,8 @@ public:
   friend class MED_MED_WRONLY_DRIVER;
   friend class MED_MED_RDWR_DRIVER;
 
+  friend class VTK_MED_DRIVER;
+
   /*!
     Constructor.
   */
@@ -169,7 +159,7 @@ public:
   /*!
     Destructor.
   */
-  ~FIELD_();
+  virtual ~FIELD_();
 
 //    virtual  void     setIterationNumber (int IterationNumber);
 //    virtual  void     setOrderNumber     (int OrderNumber);
@@ -182,37 +172,41 @@ public:
   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="");
 
-  inline void     setName(string Name);
+  virtual  void     writeAppend(const GENDRIVER &);
+  virtual  void     writeAppend(int index=0, const string & driverName="");
+
+  inline void     setName(const string Name);
   inline string   getName() const;
-  inline void     setDescription(string Description);
+  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(int NumberOfValues);
+  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 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 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 void     setComponentsUnits(const UNIT * ComponentsUnits);
   inline const UNIT *   getComponentsUnits() const;
   inline const UNIT *   getComponentUnit(int i) const;
-  inline void     setMEDComponentsUnits(string * MEDComponentsUnits);
-  inline void     setMEDComponentUnit(int i, string MEDComponentUnit);
+  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;
 
@@ -223,14 +217,16 @@ public:
   inline void     setOrderNumber(int OrderNumber);
   inline int      getOrderNumber() const;
 
-  inline void     setValueType (med_type_champ ValueType) ;
+  inline void     setValueType (const med_type_champ ValueType) ;
   inline med_type_champ getValueType () const;
 
 };
+};
 
 // ---------------------------------
 // Implemented Methods : constructor
 // ---------------------------------
+using namespace MEDMEM;
 
 // -----------------
 // Methodes Inline
@@ -238,7 +234,7 @@ public:
 /*!
   Set FIELD name.
 */
-inline void FIELD_::setName(string Name)
+inline void FIELD_::setName(const string Name)
 {
   _name=Name;
 }
@@ -252,7 +248,7 @@ inline string FIELD_::getName() const
 /*!
   Set FIELD description.
 */
-inline void FIELD_::setDescription(string Description)
+inline void FIELD_::setDescription(const string Description)
 {
   _description=Description;
 }
@@ -313,7 +309,7 @@ inline int FIELD_::getNumberOfValues() const
   Duplicate the ComponentsNames string array to put components names in
   FIELD. ComponentsNames size must be equal to number of components.
 */
-inline void FIELD_::setComponentsNames(string * ComponentsNames)
+inline void FIELD_::setComponentsNames(const string * ComponentsNames)
 {
   if (NULL == _componentsNames)
     _componentsNames = new string[_numberOfComponents] ;
@@ -325,7 +321,7 @@ inline void FIELD_::setComponentsNames(string * ComponentsNames)
 
   i must be >=1 and <= number of components.
 */
-inline void FIELD_::setComponentName(int i, string ComponentName)
+inline void FIELD_::setComponentName(int i, const string ComponentName)
 {
   _componentsNames[i-1]=ComponentName ;
 }
@@ -352,7 +348,7 @@ inline string FIELD_::getComponentName(int i) const
   descriptions in FIELD.
   ComponentsDescriptions size must be equal to number of components.
 */
-inline void FIELD_::setComponentsDescriptions(string *ComponentsDescriptions)
+inline void FIELD_::setComponentsDescriptions(const string * ComponentsDescriptions)
 {
   if (NULL == _componentsDescriptions)
     _componentsDescriptions = new string[_numberOfComponents] ;
@@ -364,7 +360,7 @@ inline void FIELD_::setComponentsDescriptions(string *ComponentsDescriptions)
 
   i must be >=1 and <= number of components.
 */
-inline void FIELD_::setComponentDescription(int i,string ComponentDescription)
+inline void FIELD_::setComponentDescription(int i,const string ComponentDescription)
 {
   _componentsDescriptions[i-1]=ComponentDescription ;
 }
@@ -393,7 +389,7 @@ inline string FIELD_::getComponentDescription(int i) const
   units in FIELD.
   ComponentsUnits size must be equal to number of components.
 */
-inline void FIELD_::setComponentsUnits(UNIT * ComponentsUnits)
+inline void FIELD_::setComponentsUnits(const UNIT * ComponentsUnits)
 {
   if (NULL == _componentsUnits)
     _componentsUnits = new UNIT[_numberOfComponents] ;
@@ -424,7 +420,7 @@ inline const UNIT * FIELD_::getComponentUnit(int i) const
   MEDComponentsUnits size must be equal to number of components.
   
 */
-inline void FIELD_::setMEDComponentsUnits(string * MEDComponentsUnits)
+inline void FIELD_::setMEDComponentsUnits(const string * MEDComponentsUnits)
 {
   if (NULL == _MEDComponentsUnits)
     _MEDComponentsUnits = new string[_numberOfComponents] ;
@@ -436,7 +432,7 @@ inline void FIELD_::setMEDComponentsUnits(string * MEDComponentsUnits)
 
   i must be >=1 and <= number of components.
 */
-inline void FIELD_::setMEDComponentUnit(int i, string MEDComponentUnit)
+inline void FIELD_::setMEDComponentUnit(int i, const string MEDComponentUnit)
 {
   _MEDComponentsUnits[i-1]=MEDComponentUnit ;
 }
@@ -512,7 +508,7 @@ inline  const SUPPORT * FIELD_::getSupport() const
 
   Reference is not duplicate, so it must not be deleted.
 */
-inline void FIELD_::setSupport(SUPPORT * support)
+inline void FIELD_::setSupport(const SUPPORT * support)
 {
   _support = support ;
 }
@@ -526,7 +522,7 @@ inline med_type_champ FIELD_::getValueType () const
 /*!
   Set the FIELD med value type (MED_INT32 or MED_REEL64).
 */
-inline void FIELD_::setValueType (med_type_champ ValueType)
+inline void FIELD_::setValueType (const med_type_champ ValueType)
 {
   _valueType = ValueType ;
 }
@@ -542,6 +538,7 @@ inline void FIELD_::setValueType (med_type_champ ValueType)
 
 */
 
+namespace MEDMEM {
 template <class T> class FIELD : public FIELD_
 {
 
@@ -569,6 +566,8 @@ protected:
 
   //    static INSTANCE_DE<MED_FIELD_RDONLY_DRIVER> inst_med_rdonly ;
   static INSTANCE_DE<MED_FIELD_RDWR_DRIVER<T> >   inst_med ;
+  static INSTANCE_DE<VTK_FIELD_DRIVER<T> >   inst_vtk ;
+
   static const INSTANCE * const instances[] ;
 
   // ------ End of Drivers Management Part
@@ -577,19 +576,52 @@ protected:
   MEDARRAY<T> *_value ;
 
 private:
+  void _operation(const FIELD& m,const FIELD& n, const 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 medModeSwitch mode);
+  void _sub_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode);
+  void _mul_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode);
+  void _div_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode);
   //setValueType() ;
 
 public:
   FIELD();
   FIELD(const FIELD &m);
   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(const SUPPORT * Support, const int NumberOfComponents, const medModeSwitch Mode=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 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 VTK_FIELD_DRIVER<T>;
   //friend class MED_FIELD_RDWR_DRIVER  <T>;
 
   void init ();
@@ -609,6 +641,9 @@ public:
   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 MEDARRAY<T>* getvalue() const;
@@ -672,13 +707,15 @@ public:
    */
   void getBarycenter() const throw (MEDEXCEPTION) ;
 };
+};
 
 // --------------------
 // Implemented Methods
 // --------------------
+using namespace MEDMEM;
 
 /*!
-  Constructor.
+  Constructor with no parameter, most of the attribut members are set to NULL.
 */
 template <class T>  FIELD<T>::FIELD():
  _value((MEDARRAY<T>*)NULL)
@@ -687,13 +724,15 @@ template <class T>  FIELD<T>::FIELD():
 }
 
 /*!
-  Constructor.
+  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 medModeSwitch Mode) throw (MEDEXCEPTION) :
   FIELD_(Support, NumberOfComponents)
 {
-  BEGIN_OF("FIELD<T>::FIELD(const SUPPORT * Support, const int NumberOfComponents)");
+  BEGIN_OF("FIELD<T>::FIELD(const SUPPORT * Support, const int NumberOfComponents, const medModeSwitch Mode)");
+  SCRUTE(this);
 
   try {
     _numberOfValues = Support->getNumberOfElements(MED_ALL_ELEMENTS);
@@ -704,12 +743,12 @@ template <class T>  FIELD<T>::FIELD(const SUPPORT * Support,
   }
   MESSAGE("FIELD : constructeur : "<< _numberOfValues <<" et "<< NumberOfComponents);
   if (0<_numberOfValues) {
-    _value = new MEDARRAY<T>::MEDARRAY(_numberOfComponents,_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)");
 }
 
 /*!
@@ -726,10 +765,11 @@ template <class T> void FIELD<T>::init ()
 template <class T> FIELD<T>::FIELD(const FIELD & m):
   FIELD_((FIELD_) m)
 {
+  MESSAGE("Constructeur FIELD de recopie");
   if (m._value != NULL)
     {
       // copie only default !
-      _value = new MEDARRAY<T>::MEDARRAY(* m._value,false);
+      _value = new MEDARRAY<T>(* m._value,false);
     }
   else
     _value = (MEDARRAY<T> *) NULL;
@@ -741,17 +781,872 @@ template <class T> FIELD<T>::FIELD(const FIELD & m):
 */
 template <class T> FIELD<T> & FIELD<T>::operator=(const FIELD &m)
 {
+  MESSAGE("Appel de FIELD<T>::operator=");
+}
+
+/*!
+     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
+    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;
+}
+
+/*!  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
+    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;
+}
+
+
+/*! 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
+    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
+
+    // Select mode : avoid if possible any calculation of other mode for fields m or *this
+    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-()");
+
+    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
+    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
+    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
+    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
+    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
+    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
+    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
+    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
+    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 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 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 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 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);
+}
+
+/*!  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()
+{
+    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)
+{
+    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();
+    }
+}
+
 
 /*!
-  Constructor.
+ *   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 medModeSwitch mode=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 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 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;
 
@@ -762,9 +1657,19 @@ template <class T> FIELD<T>::FIELD(const SUPPORT * Support,
   _support = Support;
   _value = (MEDARRAY<T>*)NULL;
 
-  MED_FIELD_RDONLY_DRIVER<T> myDriver(fileName,this);
-  myDriver.setFieldName(fieldDriverName);
-  current = addDriver(myDriver);
+  _iterationNumber = iterationNumber;
+  _time = 0.0;
+  _orderNumber = orderNumber;
+
+  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 : {
@@ -774,6 +1679,13 @@ template <class T> FIELD<T>::FIELD(const SUPPORT * Support,
 //   default : {
 //   }
 //   }
+    default :
+      {
+       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Driver type unknown : can't create driver!"));
+       break;
+      }
+    }
+
   _drivers[current]->open();
   _drivers[current]->read();
   _drivers[current]->close();
@@ -787,6 +1699,7 @@ template <class T> FIELD<T>::FIELD(const SUPPORT * Support,
 template <class T> FIELD<T>::~FIELD()
 {
   BEGIN_OF(" Destructeur FIELD<T>::~FIELD()");
+  SCRUTE(this);
   if (_value) delete _value;
   END_OF(" Destructeur FIELD<T>::~FIELD()");
 }
@@ -818,7 +1731,7 @@ template <class T> void FIELD<T>::allocValue(const int NumberOfComponents)
     _numberOfValues = _support->getNumberOfElements(MED_ALL_ELEMENTS);
     MESSAGE(LOC <<" : "<<_numberOfValues <<" et "<< NumberOfComponents);
 
-    _value = new MEDARRAY<T>::MEDARRAY(_numberOfComponents,_numberOfValues);
+    _value = new MEDARRAY<T>(_numberOfComponents,_numberOfValues);
 
     _isRead = true ;
   }
@@ -855,7 +1768,7 @@ template <class T> void FIELD<T>::allocValue(const int NumberOfComponents, const
 
   MESSAGE("FIELD : constructeur : "<<LengthValue <<" et "<< NumberOfComponents);
   _numberOfValues = LengthValue ;
-  _value = new MEDARRAY<T>::MEDARRAY(_numberOfComponents,_numberOfValues);
+  _value = new MEDARRAY<T>(_numberOfComponents,_numberOfValues);
   _isRead = true ;
 
   SCRUTE(_value);
@@ -882,13 +1795,17 @@ template <class T> void FIELD<T>::deallocValue()
 
 
 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>       FIELD<T>::INSTANCE_DE<VTK_FIELD_DRIVER<T> >     FIELD<T>::inst_vtk  ;
+
+template <class T> const typename FIELD<T>::INSTANCE * const FIELD<T>::instances[] = { &FIELD<T>::inst_med,  &FIELD<T>::inst_vtk} ;
 
 
 /*!
   Create the specified driver and return its index reference to path to 
   read or write methods.
 */
+
 template <class T> int FIELD<T>::addDriver(driverTypes driverType,
                                           const string & fileName/*="Default File Name.med"*/,
                                           const string & driverName/*="Default Field Name"*/)
@@ -897,18 +1814,51 @@ template <class T> int FIELD<T>::addDriver(driverTypes driverType,
 
   GENDRIVER * driver;
   int current;
+  int itDriver = (int) NO_DRIVER;
 
   BEGIN_OF(LOC);
 
-  driver = instances[driverType]->run(fileName, this) ;
+  SCRUTE(driverType);
+
+  SCRUTE(instances[driverType]);
+
+  switch(driverType)
+    {
+    case MED_DRIVER : {
+      itDriver = (int) driverType ;
+      break ;
+    }
+
+    case VTK_DRIVER : {
+      itDriver = 1 ;
+      break ;
+    }
+
+    case GIBI_DRIVER : {
+      throw MED_EXCEPTION (LOCALIZED(STRING(LOC)<< "driverType other than MED_DRIVER and VTK_DRIVER has been specified to the method which is not allowed for the object FIELD"));
+      break;
+    }
+
+    case NO_DRIVER : {
+      throw MED_EXCEPTION (LOCALIZED(STRING(LOC)<< "driverType other than MED_DRIVER and VTK_DRIVER has been specified to the method which is not allowed for the object FIELD"));
+      break;
+    }
+    }
+
+  if (itDriver == ((int) NO_DRIVER))
+    throw MED_EXCEPTION (LOCALIZED(STRING(LOC)<< "driverType other than MED_DRIVER and VTK_DRIVER has been specified to the method which is not allowed for the object FIELD"));
+
+  driver = instances[itDriver]->run(fileName, this) ;
+
   _drivers.push_back(driver);
+
   current = _drivers.size()-1;
 
   _drivers[current]->setFieldName(driverName);
-  return current;
 
   END_OF(LOC);
 
+  return current;
 }
 
 
@@ -926,7 +1876,7 @@ template <class T> inline int FIELD<T>::addDriver (GENDRIVER & driver )
 
   _drivers.push_back(newDriver);
   return _drivers.size() -1 ;
-  
+
   END_OF(LOC);
 };
 
@@ -945,7 +1895,7 @@ template <class T> void FIELD<T>::rmDriver (int index/*=0*/)
   }
   else
     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
-                                     << "The index given is invalid, index must be between  0 and  |"
+                                     << "The <index given is invalid, index must be between  0 and  |"
                                      << _drivers.size()
                                      )
                           );
@@ -998,6 +1948,30 @@ template <class T> inline void FIELD<T>::write(int index/*=0*/, const string & d
   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()
+                                     )
+                          );
+  END_OF(LOC);
+}
+
 /*!
   \internal
   Write FIELD with the driver which is equal to the given driver.
@@ -1009,7 +1983,7 @@ 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++ )
+  for (unsigned int index=0; index < _drivers.size(); index++ )
     if ( *_drivers[index] == genDriver ) {
       _drivers[index]->open();
       _drivers[index]->write();
@@ -1020,6 +1994,28 @@ 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. 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);
+
+}
+
 /*!
   \internal
   Read FIELD with the driver which is equal to the given driver.
@@ -1031,7 +2027,7 @@ template <class T> inline void FIELD<T>::read(const GENDRIVER & genDriver)
   const char * LOC = " FIELD<T>::read(const GENDRIVER &) : ";
   BEGIN_OF(LOC);
 
-  for (int index=0; index < _drivers.size(); index++ )
+  for (unsigned int index=0; index < _drivers.size(); index++ )
     if ( *_drivers[index] == genDriver ) {
       _drivers[index]->open();
       _drivers[index]->read();