13 #include "utilities.h"
14 #include "MEDMEM_Exception.hxx"
15 #include "MEDMEM_define.hxx"
17 #include "MEDMEM_Support.hxx"
18 #include "MEDMEM_Unit.hxx"
19 #include "MEDMEM_Array.hxx"
20 #include "MEDMEM_GenDriver.hxx"
21 #include "MEDMEM_DriverFactory.hxx"
23 using namespace MED_EN;
27 This class contains all the informations related with a template class FIELD :
28 - Components descriptions
29 - Time step description
30 - Location of the values (a SUPPORT class)
36 template<class T> class FIELD;
38 class FIELD_ // GENERIC POINTER TO a template <class T> class FIELD
58 Pointer to the support the field deals with.
61 const SUPPORT * _support ;
65 Number of field's components.
68 int _numberOfComponents ;
71 Number of field's values.
78 Array of size _numberOfComponents. \n
79 (constant, scalar, vector, tensor)\n
80 We could use an array of integer to store
83 - space dimension for vector,\n
84 - space dimension square for tensor.\n
85 So numbers of values per entities would be
86 sum of _componentsTypes array.
88 Not implemented yet! All type are scalar !
91 int * _componentsTypes ;
94 Array of size _numberOfComponents
95 storing components names if any.
98 string * _componentsNames;
101 Array of size _numberOfComponents
102 storing components descriptions if any.
105 string * _componentsDescriptions;
108 Array of size _numberOfComponents
109 storing components units if any.
112 UNIT * _componentsUnits;
115 Array of size _numberOfComponents
116 storing components units if any.
119 string * _MEDComponentsUnits;
120 int _iterationNumber ;
124 // _valueType should be a static const. Here is an initialization exemple
125 // template < classType T > struct SET_VALUE_TYPE { static const med_type_champ _valueType = 0; }
126 // template < > struct SET_VALUE_TYPE<double> { static const med_type_champ _valueType = MED_EN::MED_REEL64; }
127 // template < > struct SET_VALUE_TYPE<int> { static const med_type_champ _valueType = MED_EN::MED_INT32; }
128 // static const med_type_champ _valueType = SET_VALUE_TYPE <T>::_valueType;
129 med_type_champ _valueType ;
131 vector<GENDRIVER *> _drivers; // Storage of the drivers currently in use
132 static void _checkFieldCompatibility(const FIELD_& m, const FIELD_& n ) throw (MEDEXCEPTION);
133 void _checkNormCompatibility(const FIELD<double>* p_field_volume=NULL) const throw (MEDEXCEPTION);
134 FIELD<double>* _getFieldSize() const;
138 friend class MED_MED_RDONLY_DRIVER;
139 friend class MED_MED_WRONLY_DRIVER;
140 friend class MED_MED_RDWR_DRIVER;
142 friend class VTK_MED_DRIVER;
151 FIELD_(const SUPPORT * Support, const int NumberOfComponents);
155 FIELD_(const FIELD_ &m);
162 // virtual void setIterationNumber (int IterationNumber);
163 // virtual void setOrderNumber (int OrderNumber);
164 // virtual void setFieldName (string& fieldName);
166 virtual void rmDriver(int index);
167 virtual int addDriver(driverTypes driverType,
168 const string & fileName="Default File Name.med",
169 const string & driverFieldName="Default Field Nam") ;
170 virtual int addDriver( GENDRIVER & driver);
171 virtual void read (const GENDRIVER &);
172 virtual void read(int index=0);
173 virtual void openAppend( void );
174 virtual void write(const GENDRIVER &);
175 virtual void write(int index=0, const string & driverName="");
177 virtual void writeAppend(const GENDRIVER &);
178 virtual void writeAppend(int index=0, const string & driverName="");
180 inline void setName(const string Name);
181 inline string getName() const;
182 inline void setDescription(const string Description);
183 inline string getDescription() const;
184 inline const SUPPORT * getSupport() const;
185 inline void setSupport(const SUPPORT * support);
186 inline void setNumberOfComponents(const int NumberOfComponents);
187 inline int getNumberOfComponents() const;
188 inline void setNumberOfValues(const int NumberOfValues);
189 inline int getNumberOfValues() const;
190 // inline void setComponentType(int *ComponentType);
191 // inline int * getComponentType() const;
192 // inline int getComponentTypeI(int i) const;
193 inline void setComponentsNames(const string * ComponentsNames);
194 inline void setComponentName(int i, const string ComponentName);
195 inline const string * getComponentsNames() const;
196 inline string getComponentName(int i) const;
197 inline void setComponentsDescriptions(const string * ComponentsDescriptions);
198 inline void setComponentDescription(int i, const string ComponentDescription);
199 inline const string * getComponentsDescriptions() const;
200 inline string getComponentDescription(int i) const;
202 // provisoire : en attendant de regler le probleme des unites !
203 inline void setComponentsUnits(const UNIT * ComponentsUnits);
204 inline const UNIT * getComponentsUnits() const;
205 inline const UNIT * getComponentUnit(int i) const;
206 inline void setMEDComponentsUnits(const string * MEDComponentsUnits);
207 inline void setMEDComponentUnit(int i, const string MEDComponentUnit);
208 inline const string * getMEDComponentsUnits() const;
209 inline string getMEDComponentUnit(int i) const;
211 inline void setIterationNumber(int IterationNumber);
212 inline int getIterationNumber() const;
213 inline void setTime(double Time);
214 inline double getTime() const;
215 inline void setOrderNumber(int OrderNumber);
216 inline int getOrderNumber() const;
218 inline void setValueType (const med_type_champ ValueType) ;
219 inline med_type_champ getValueType () const;
224 // ---------------------------------
225 // Implemented Methods : constructor
226 // ---------------------------------
227 using namespace MEDMEM;
235 inline void FIELD_::setName(const string Name)
242 inline string FIELD_::getName() const
247 Set FIELD description.
249 inline void FIELD_::setDescription(const string Description)
251 _description=Description;
254 Get FIELD description.
256 inline string FIELD_::getDescription() const
261 Set FIELD number of components.
263 inline void FIELD_::setNumberOfComponents(int NumberOfComponents)
265 _numberOfComponents=NumberOfComponents;
268 Get FIELD number of components.
270 inline int FIELD_::getNumberOfComponents() const
272 return _numberOfComponents ;
275 Set FIELD number of values.
277 It must be the same than in the associated SUPPORT object.
279 inline void FIELD_::setNumberOfValues(int NumberOfValues)
281 _numberOfValues=NumberOfValues;
284 Get FIELD number of value.
286 inline int FIELD_::getNumberOfValues() const
288 return _numberOfValues ;
291 // inline void FIELD_::setComponentType(int *ComponentType)
293 // _componentsTypes=ComponentType ;
295 // inline int * FIELD_::getComponentType() const
297 // return _componentsTypes ;
299 // inline int FIELD_::getComponentTypeI(int i) const
301 // return _componentsTypes[i-1] ;
305 Set FIELD components names.
307 Duplicate the ComponentsNames string array to put components names in
308 FIELD. ComponentsNames size must be equal to number of components.
310 inline void FIELD_::setComponentsNames(const string * ComponentsNames)
312 if (NULL == _componentsNames)
313 _componentsNames = new string[_numberOfComponents] ;
314 for (int i=0; i<_numberOfComponents; i++)
315 _componentsNames[i]=ComponentsNames[i] ;
318 Set FIELD i^th component name.
320 i must be >=1 and <= number of components.
322 inline void FIELD_::setComponentName(int i, const string ComponentName)
324 _componentsNames[i-1]=ComponentName ;
327 Get a reference to the string array which contain the components names.
329 This Array size is equal to number of components
331 inline const string * FIELD_::getComponentsNames() const
333 return _componentsNames ;
336 Get the name of the i^th component.
338 inline string FIELD_::getComponentName(int i) const
340 return _componentsNames[i-1] ;
343 Set FIELD components descriptions.
345 Duplicate the ComponentsDescriptions string array to put components
346 descriptions in FIELD.
347 ComponentsDescriptions size must be equal to number of components.
349 inline void FIELD_::setComponentsDescriptions(const string * ComponentsDescriptions)
351 if (NULL == _componentsDescriptions)
352 _componentsDescriptions = new string[_numberOfComponents] ;
353 for (int i=0; i<_numberOfComponents; i++)
354 _componentsDescriptions[i]=ComponentsDescriptions[i] ;
357 Set FIELD i^th component description.
359 i must be >=1 and <= number of components.
361 inline void FIELD_::setComponentDescription(int i,const string ComponentDescription)
363 _componentsDescriptions[i-1]=ComponentDescription ;
366 Get a reference to the string array which contain the components descriptions.
368 This Array size is equal to number of components
370 inline const string * FIELD_::getComponentsDescriptions() const
372 return _componentsDescriptions ;
375 Get the description of the i^th component.
377 inline string FIELD_::getComponentDescription(int i) const
379 return _componentsDescriptions[i-1];
384 Set FIELD components UNIT.
386 Duplicate the ComponentsUnits UNIT array to put components
388 ComponentsUnits size must be equal to number of components.
390 inline void FIELD_::setComponentsUnits(const UNIT * ComponentsUnits)
392 if (NULL == _componentsUnits)
393 _componentsUnits = new UNIT[_numberOfComponents] ;
394 for (int i=0; i<_numberOfComponents; i++)
395 _componentsUnits[i]=ComponentsUnits[i] ;
398 Get a reference to the UNIT array which contain the components units.
400 This Array size is equal to number of components
402 inline const UNIT * FIELD_::getComponentsUnits() const
404 return _componentsUnits ;
407 Get the UNIT of the i^th component.
409 inline const UNIT * FIELD_::getComponentUnit(int i) const
411 return &_componentsUnits[i-1] ;
414 Set FIELD components unit.
416 Duplicate the MEDComponentsUnits string array to put components
418 MEDComponentsUnits size must be equal to number of components.
421 inline void FIELD_::setMEDComponentsUnits(const string * MEDComponentsUnits)
423 if (NULL == _MEDComponentsUnits)
424 _MEDComponentsUnits = new string[_numberOfComponents] ;
425 for (int i=0; i<_numberOfComponents; i++)
426 _MEDComponentsUnits[i]=MEDComponentsUnits[i] ;
429 Set FIELD i^th component unit.
431 i must be >=1 and <= number of components.
433 inline void FIELD_::setMEDComponentUnit(int i, const string MEDComponentUnit)
435 _MEDComponentsUnits[i-1]=MEDComponentUnit ;
438 Get a reference to the string array which contain the components units.
440 This Array size is equal to number of components
442 inline const string * FIELD_::getMEDComponentsUnits() const
444 return _MEDComponentsUnits ;
447 Get the string for unit of the i^th component.
449 inline string FIELD_::getMEDComponentUnit(int i) const
451 return _MEDComponentsUnits[i-1] ;
454 Set the iteration number where FIELD has been calculated.
456 inline void FIELD_::setIterationNumber(int IterationNumber)
458 _iterationNumber=IterationNumber;
461 Get the iteration number where FIELD has been calculated.
463 inline int FIELD_::getIterationNumber() const
465 return _iterationNumber ;
468 Set the time (in second) where FIELD has been calculated.
470 inline void FIELD_::setTime(double Time)
475 Get the time (in second) where FIELD has been calculated.
477 inline double FIELD_::getTime() const
482 Set the order number where FIELD has been calculated.
484 It corresponds to internal iteration during one time step.
486 inline void FIELD_::setOrderNumber(int OrderNumber)
488 _orderNumber=OrderNumber ;
491 Get the order number where FIELD has been calculated.
493 inline int FIELD_::getOrderNumber() const
495 return _orderNumber ;
498 Get a reference to the SUPPORT object associated to FIELD.
500 inline const SUPPORT * FIELD_::getSupport() const
505 Set the reference to the SUPPORT object associated to FIELD.
507 Reference is not duplicate, so it must not be deleted.
509 inline void FIELD_::setSupport(const SUPPORT * support)
514 Get the FIELD med value type (MED_INT32 or MED_REEL64).
516 inline med_type_champ FIELD_::getValueType () const
521 Set the FIELD med value type (MED_INT32 or MED_REEL64).
523 inline void FIELD_::setValueType (const med_type_champ ValueType)
525 _valueType = ValueType ;
528 /////////////////////////
529 // END OF CLASS FIELD_ //
530 /////////////////////////
534 This template class contains informations related with a FIELD :
535 - Values of the field
541 template<class T2> class MED_FIELD_RDONLY_DRIVER;
542 template<class T2> class MED_FIELD_WRONLY_DRIVER;
543 template<class T2> class VTK_FIELD_DRIVER;
545 template <class T> class FIELD : public FIELD_
548 // ------ End of Drivers Management Part
550 // array of value of type T
551 MEDARRAY<T> *_value ;
554 void _operation(const FIELD& m,const FIELD& n, const medModeSwitch mode, char* Op);
555 void _operationInitialize(const FIELD& m,const FIELD& n, char* Op);
556 void _add_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode);
557 void _sub_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode);
558 void _mul_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode);
559 void _div_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode);
562 FIELD & operator=(const FIELD &m); // A FAIRE
565 FIELD(const FIELD &m);
566 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
567 FIELD(const SUPPORT * Support, driverTypes driverType,
568 const string & fileName="", const string & fieldName="",
569 const int iterationNumber = -1, const int orderNumber = -1)
570 throw (MEDEXCEPTION);
573 const FIELD operator+(const FIELD& m) const;
574 const FIELD operator-(const FIELD& m) const;
575 const FIELD operator*(const FIELD& m) const;
576 const FIELD operator/(const FIELD& m) const;
577 const FIELD operator-() const;
578 FIELD& operator+=(const FIELD& m);
579 FIELD& operator-=(const FIELD& m);
580 FIELD& operator*=(const FIELD& m);
581 FIELD& operator/=(const FIELD& m);
582 static FIELD* add(const FIELD& m, const FIELD& n);
583 static FIELD* sub(const FIELD& m, const FIELD& n);
584 static FIELD* mul(const FIELD& m, const FIELD& n);
585 static FIELD* div(const FIELD& m, const FIELD& n);
586 double normMax() const throw (MEDEXCEPTION);
587 double norm2() const throw (MEDEXCEPTION);
588 void applyLin(T a, T b);
589 template <T T_function(T)> void applyFunc();
590 static FIELD* scalarProduct(const FIELD& m, const FIELD& n);
591 double normL2(int component, const FIELD<double> * p_field_volume=NULL) const;
592 double normL2(const FIELD<double> * p_field_volume=NULL) const;
593 double normL1(int component, const FIELD<double> * p_field_volume=NULL) const;
594 double normL1(const FIELD<double> * p_field_volume=NULL) const;
596 friend class MED_FIELD_RDONLY_DRIVER<T>;
597 friend class MED_FIELD_WRONLY_DRIVER<T>;
598 friend class VTK_FIELD_DRIVER<T>;
599 //friend class MED_FIELD_RDWR_DRIVER <T>;
602 void rmDriver(int index=0);
603 int addDriver(driverTypes driverType,
604 const string & fileName="Default File Name.med",
605 const string & driverFieldName="Default Field Name") ;
606 int addDriver(GENDRIVER & driver);
608 void allocValue(const int NumberOfComponents);
609 void allocValue(const int NumberOfComponents, const int LengthValue);
613 inline void read(int index=0);
614 inline void read(const GENDRIVER & genDriver);
615 inline void write(int index=0, const string & driverName = "");
616 inline void write(const GENDRIVER &);
618 inline void writeAppend(int index=0, const string & driverName = "");
619 inline void writeAppend(const GENDRIVER &);
621 inline void setValue(MEDARRAY<T> *Value);
623 inline MEDARRAY<T>* getvalue() const;
624 inline int getValueLength(medModeSwitch Mode) const;
625 inline const T* getValue(medModeSwitch Mode) const;
626 inline const T* getValueI(medModeSwitch Mode,int i) const;
627 inline T getValueIJ(int i,int j) const;
629 inline void setValue(medModeSwitch mode, T* value);
630 inline void setValueI(medModeSwitch mode, int i, T* value);
631 inline void setValueIJ(int i, int j, T value);
634 This fonction feeds the FIELD<double> private attributs _value with the
635 volume of each cells belonging to the argument Support. The field has to be
636 initialised via the constructor FIELD<double>(const SUPPORT * , const int )
637 with Support as SUPPORT argument, 1 has the number of components, and Support
638 has be a SUPPORT on 3D cells. This initialisation could be done by the empty
639 constructor followed by a setSupport and setNumberOfComponents call but it has
640 be followed by a setValueType(MED_REEL64) call.
642 void getVolume() const throw (MEDEXCEPTION) ;
644 This fonction feeds the FIELD<double> private attributs _value with the
645 area of each cells (or faces) belonging to the attribut _support. The field
646 has to be initialised via the constructor FIELD<double>(const SUPPORT * ,
647 const int ) with 1 has the number of components, and _support has be a
648 SUPPORT on 2D cells or 3D faces. This initialisation could be done by the
649 empty constructor followed by a setSupport and setNumberOfComponents call but
650 it has be followed by a setValueType(MED_REEL64) call.
652 void getArea() const throw (MEDEXCEPTION) ;
654 This fonction feeds the FIELD<double> private attributs _value with the
655 length of each segments belonging to the attribut _support. The field has
656 to be initialised via the constructor FIELD<double>(const SUPPORT * ,
657 const int ) with 1 has the number of components, and _support has be a
658 SUPPORT on 3D edges or 2D faces. This initialisation could be done by the
659 empty constructor followed by a setSupport and setNumberOfComponents call but
660 it has be followed by a setValueType(MED_REEL64) call.
662 void getLength() const throw (MEDEXCEPTION) ;
664 This fonction feeds the FIELD<double> private attributs _value with the
665 normal vector of each faces belonging to the attribut _support. The field
666 has to be initialised via the constructor FIELD<double>(const SUPPORT * ,
667 const int ) with the space dimension has the number of components, and
668 _support has be a SUPPORT on 3D or 2D faces. This initialisation could be done
669 by the empty constructor followed by a setSupport and setNumberOfComponents
670 call but it has be followed by a setValueType(MED_REEL64) call.
672 void getNormal() const throw (MEDEXCEPTION) ;
674 This fonction feeds the FIELD<double> private attributs _value with the
675 barycenter of each faces or cells or edges belonging to the attribut _support.
676 The field has to be initialised via the constructor
677 FIELD<double>(const SUPPORT * ,const int ) with the space dimension has the
678 number of components, and _support has be a SUPPORT on 3D cells or 2D faces.
679 This initialisation could be done by the empty constructor followed by a
680 setSupport and setNumberOfComponents call but it has be followed by a
681 setValueType(MED_REEL64) call.
683 void getBarycenter() const throw (MEDEXCEPTION) ;
687 // --------------------
688 // Implemented Methods
689 // --------------------
690 using namespace MEDMEM;
693 Constructor with no parameter, most of the attribut members are set to NULL.
695 template <class T> FIELD<T>::FIELD():
696 _value((MEDARRAY<T>*)NULL)
698 MESSAGE("Constructeur FIELD sans parametre");
702 Constructor with parameters such that all attrribut are set but the _value
703 attribut is allocated but not set.
705 template <class T> FIELD<T>::FIELD(const SUPPORT * Support,
706 const int NumberOfComponents, const medModeSwitch Mode) throw (MEDEXCEPTION) :
707 FIELD_(Support, NumberOfComponents)
709 BEGIN_OF("FIELD<T>::FIELD(const SUPPORT * Support, const int NumberOfComponents, const medModeSwitch Mode)");
713 _numberOfValues = Support->getNumberOfElements(MED_ALL_ELEMENTS);
715 catch (MEDEXCEPTION &ex) {
716 MESSAGE("No value defined ! ("<<ex.what()<<")");
717 _value = (MEDARRAY<T>*)NULL ;
719 MESSAGE("FIELD : constructeur : "<< _numberOfValues <<" et "<< NumberOfComponents);
720 if (0<_numberOfValues) {
721 _value = new MEDARRAY<T>(_numberOfComponents,_numberOfValues,Mode);
724 _value = (MEDARRAY<T>*)NULL ;
726 END_OF("FIELD<T>::FIELD(const SUPPORT * Support, const int NumberOfComponents, const medModeSwitch Mode)");
733 template <class T> void FIELD<T>::init ()
740 template <class T> FIELD<T>::FIELD(const FIELD & m):
743 MESSAGE("Constructeur FIELD de recopie");
744 if (m._value != NULL)
746 // copie only default !
747 _value = new MEDARRAY<T>(* m._value,false);
750 _value = (MEDARRAY<T> *) NULL;
751 //_drivers = m._drivers;
759 template <class T> FIELD<T> & FIELD<T>::operator=(const FIELD &m)
761 MESSAGE("Appel de FIELD<T>::operator=") ;
762 // operator= on FIELD_
768 Overload addition operator.
769 This operation is authorized only for compatible fields that have the same support.
770 The compatibility checking includes equality tests of the folowing data members:\n
772 - _numberOfComponents
775 - _MEDComponentsUnits.
777 The data members of the returned field are initialized, based on the first field, except for the name,
778 which is the combination of the two field's names and the operator.
779 Advised Utilisation in C++ : <tt> FIELD<T> c = a + b; </tt> \n
780 In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
781 When using python, this operator calls the copy constructor in any case.
782 The user has to be aware that when using operator + in associatives expressions like
783 <tt> a = b + c + d +e; </tt> \n
784 no optimisation is performed : the evaluation of last expression requires the construction of
788 const FIELD<T> FIELD<T>::operator+(const FIELD & m) const
790 BEGIN_OF("FIELD<T>::operator+(const FIELD & m)");
791 FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
793 // Select mode : avoid if possible any calculation of other mode for fields m or *this
795 if(this->getvalue()->getMode()==m.getvalue()->getMode() || this->getvalue()->isOtherCalculated())
796 mode=m.getvalue()->getMode();
798 mode=this->getvalue()->getMode();
800 // Creation of the result - memory is allocated by FIELD constructor
801 FIELD<T> result(this->getSupport(),this->getNumberOfComponents(),mode);
802 //result._operation(*this,m,mode,"+"); // perform Atribute's initialization & addition
803 result._operationInitialize(*this,m,"+"); // perform Atribute's initialization
804 result._add_in_place(*this,m,mode); // perform addition
806 END_OF("FIELD<T>::operator+(const FIELD & m)");
810 /*! Overloaded Operator +=
811 * Operations are directly performed in the first field's array.
812 * This operation is authorized only for compatible fields that have the same support.
815 FIELD<T>& FIELD<T>::operator+=(const FIELD & m)
817 BEGIN_OF("FIELD<T>::operator+=(const FIELD & m)");
818 FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
820 // We choose to keep *this mode, even if it may cost a re-calculation for m
821 medModeSwitch mode=this->getvalue()->getMode();
822 const T* value1=m.getValue(mode); // get pointers to the values we are adding
824 // get a non const pointer to the inside array of values and perform operation
825 T * value=const_cast<T *> (getValue(mode));
826 const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
827 const T* endV=value+size; // pointer to the end of value
828 for(;value!=endV; value1++,value++)
830 // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
831 this->getvalue()->clearOtherMode();
832 END_OF("FIELD<T>::operator+=(const FIELD & m)");
837 /*! Addition of fields. Static member function.
838 * The function return a pointer to a new created field that holds the addition.
839 * Data members are checked for compatibility and initialized.
840 * The user is in charge of memory deallocation.
843 FIELD<T>* FIELD<T>::add(const FIELD& m, const FIELD& n)
845 BEGIN_OF("FIELD<T>::add(const FIELD & m, const FIELD& n)");
846 FIELD_::_checkFieldCompatibility(m, n); // may throw exception
848 // Select mode : avoid if possible any calculation of other mode for fields m or *this
850 if(m.getvalue()->getMode()==n.getvalue()->getMode() || n.getvalue()->isOtherCalculated())
851 mode=m.getvalue()->getMode();
853 mode=n.getvalue()->getMode();
855 // Creation of a new field
856 FIELD<T>* result = new FIELD<T>(m.getSupport(),m.getNumberOfComponents(),mode);
857 result->_operationInitialize(m,n,"+"); // perform Atribute's initialization
858 result->_add_in_place(m,n,mode); // perform addition
860 END_OF("FIELD<T>::add(const FIELD & m, const FIELD& n)");
865 Overload substraction operator.
866 This operation is authorized only for compatible fields that have the same support.
867 The compatibility checking includes equality tests of the folowing data members:\n
869 - _numberOfComponents
872 - _MEDComponentsUnits.
874 The data members of the returned field are initialized, based on the first field, except for the name,
875 which is the combination of the two field's names and the operator.
876 Advised Utilisation in C++ : <tt> FIELD<T> c = a - b; </tt> \n
877 In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
878 When using python, this operator calls the copy constructor in any case.
879 The user has to be aware that when using operator - in associatives expressions like
880 <tt> a = b - c - d -e; </tt> \n
881 no optimisation is performed : the evaluation of last expression requires the construction of
885 const FIELD<T> FIELD<T>::operator-(const FIELD & m) const
887 BEGIN_OF("FIELD<T>::operator-(const FIELD & m)");
888 FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
890 // Select mode : avoid if possible any calculation of other mode for fields m or *this
892 if(this->getvalue()->getMode()==m.getvalue()->getMode() || this->getvalue()->isOtherCalculated())
893 mode=m.getvalue()->getMode();
895 mode=this->getvalue()->getMode();
897 // Creation of the result - memory is allocated by FIELD constructor
898 FIELD<T> result(this->getSupport(),this->getNumberOfComponents(),mode);
899 //result._operation(*this,m,mode,"-"); // perform Atribute's initialization & substraction
900 result._operationInitialize(*this,m,"-"); // perform Atribute's initialization
901 result._sub_in_place(*this,m,mode); // perform substracion
903 END_OF("FIELD<T>::operator-(const FIELD & m)");
908 const FIELD<T> FIELD<T>::operator-() const
910 BEGIN_OF("FIELD<T>::operator-()");
912 medModeSwitch mode=this->getvalue()->getMode();
913 // Creation of the result - memory is allocated by FIELD constructor
914 FIELD<T> result(this->getSupport(),this->getNumberOfComponents(),mode);
915 // Atribute's initialization
916 result.setName("- "+getName());
917 result.setComponentsNames(getComponentsNames());
918 // not yet implemented setComponentType(getComponentType());
919 result.setComponentsDescriptions(getComponentsDescriptions());
920 result.setMEDComponentsUnits(getMEDComponentsUnits());
921 result.setComponentsUnits(getComponentsUnits());
922 result.setIterationNumber(getIterationNumber());
923 result.setTime(getTime());
924 result.setOrderNumber(getOrderNumber());
925 result.setValueType(getValueType());
927 const T* value1=getValue(mode);
928 // get a non const pointer to the inside array of values and perform operation
929 T * value=const_cast<T *> (result.getValue(mode));
930 const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
931 const T* endV=value+size; // pointer to the end of value
933 for(;value!=endV; value1++,value++)
935 END_OF("FIELD<T>::operator-=(const FIELD & m)");
939 /*! Overloaded Operator -=
940 * Operations are directly performed in the first field's array.
941 * This operation is authorized only for compatible fields that have the same support.
944 FIELD<T>& FIELD<T>::operator-=(const FIELD & m)
946 BEGIN_OF("FIELD<T>::operator-=(const FIELD & m)");
947 FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
949 // We choose to keep *this mode, even if it may cost a re-calculation for m
950 medModeSwitch mode=this->getvalue()->getMode();
951 const T* value1=m.getValue(mode); // get pointers to the values we are adding
953 // get a non const pointer to the inside array of values and perform operation
954 T * value=const_cast<T *> (getValue(mode));
955 const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
956 const T* endV=value+size; // pointer to the end of value
958 for(;value!=endV; value1++,value++)
960 // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
961 this->getvalue()->clearOtherMode();
962 END_OF("FIELD<T>::operator-=(const FIELD & m)");
967 /*! Substraction of fields. Static member function.
968 * The function return a pointer to a new created field that holds the substraction.
969 * Data members are checked for compatibility and initialized.
970 * The user is in charge of memory deallocation.
973 FIELD<T>* FIELD<T>::sub(const FIELD& m, const FIELD& n)
975 BEGIN_OF("FIELD<T>::sub(const FIELD & m, const FIELD& n)");
976 FIELD_::_checkFieldCompatibility(m, n); // may throw exception
978 // Select mode : avoid if possible any calculation of other mode for fields m or *this
980 if(m.getvalue()->getMode()==n.getvalue()->getMode() || n.getvalue()->isOtherCalculated())
981 mode=m.getvalue()->getMode();
983 mode=n.getvalue()->getMode();
985 // Creation of a new field
986 FIELD<T>* result = new FIELD<T>(m.getSupport(),m.getNumberOfComponents(),mode);
987 result->_operationInitialize(m,n,"-"); // perform Atribute's initialization
988 result->_sub_in_place(m,n,mode); // perform substraction
990 END_OF("FIELD<T>::sub(const FIELD & m, const FIELD& n)");
995 Overload multiplication operator.
996 This operation is authorized only for compatible fields that have the same support.
997 The compatibility checking includes equality tests of the folowing data members:\n
999 - _numberOfComponents
1002 - _MEDComponentsUnits.
1004 The data members of the returned field are initialized, based on the first field, except for the name,
1005 which is the combination of the two field's names and the operator.
1006 Advised Utilisation in C++ : <tt> FIELD<T> c = a * b; </tt> \n
1007 In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
1008 When using python, this operator calls the copy constructor in any case.
1009 The user has to be aware that when using operator * in associatives expressions like
1010 <tt> a = b * c * d *e; </tt> \n
1011 no optimisation is performed : the evaluation of last expression requires the construction of
1015 const FIELD<T> FIELD<T>::operator*(const FIELD & m) const
1017 BEGIN_OF("FIELD<T>::operator*(const FIELD & m)");
1018 FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
1020 // Select mode : avoid if possible any calculation of other mode for fields m or *this
1022 if(this->getvalue()->getMode()==m.getvalue()->getMode() || this->getvalue()->isOtherCalculated())
1023 mode=m.getvalue()->getMode();
1025 mode=this->getvalue()->getMode();
1027 // Creation of the result - memory is allocated by FIELD constructor
1028 FIELD<T> result(this->getSupport(),this->getNumberOfComponents(),mode);
1029 //result._operation(*this,m,mode,"*"); // perform Atribute's initialization & multiplication
1030 result._operationInitialize(*this,m,"*"); // perform Atribute's initialization
1031 result._mul_in_place(*this,m,mode); // perform multiplication
1033 END_OF("FIELD<T>::operator*(const FIELD & m)");
1037 /*! Overloaded Operator *=
1038 * Operations are directly performed in the first field's array.
1039 * This operation is authorized only for compatible fields that have the same support.
1042 FIELD<T>& FIELD<T>::operator*=(const FIELD & m)
1044 BEGIN_OF("FIELD<T>::operator*=(const FIELD & m)");
1045 FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
1047 // We choose to keep *this mode, even if it may cost a re-calculation for m
1048 medModeSwitch mode=this->getvalue()->getMode();
1049 const T* value1=m.getValue(mode); // get pointers to the values we are adding
1051 // get a non const pointer to the inside array of values and perform operation
1052 T * value=const_cast<T *> (getValue(mode));
1053 const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
1054 const T* endV=value+size; // pointer to the end of value
1056 for(;value!=endV; value1++,value++)
1058 // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
1059 this->getvalue()->clearOtherMode();
1060 END_OF("FIELD<T>::operator*=(const FIELD & m)");
1065 /*! Multiplication of fields. Static member function.
1066 * The function return a pointer to a new created field that holds the multiplication.
1067 * Data members are checked for compatibility and initialized.
1068 * The user is in charge of memory deallocation.
1071 FIELD<T>* FIELD<T>::mul(const FIELD& m, const FIELD& n)
1073 BEGIN_OF("FIELD<T>::mul(const FIELD & m, const FIELD& n)");
1074 FIELD_::_checkFieldCompatibility(m, n); // may throw exception
1076 // Select mode : avoid if possible any calculation of other mode for fields m or *this
1078 if(m.getvalue()->getMode()==n.getvalue()->getMode() || n.getvalue()->isOtherCalculated())
1079 mode=m.getvalue()->getMode();
1081 mode=n.getvalue()->getMode();
1083 // Creation of a new field
1084 FIELD<T>* result = new FIELD<T>(m.getSupport(),m.getNumberOfComponents(),mode);
1085 result->_operationInitialize(m,n,"*"); // perform Atribute's initialization
1086 result->_mul_in_place(m,n,mode); // perform multiplication
1088 END_OF("FIELD<T>::mul(const FIELD & m, const FIELD& n)");
1094 Overload division operator.
1095 This operation is authorized only for compatible fields that have the same support.
1096 The compatibility checking includes equality tests of the folowing data members:\n
1098 - _numberOfComponents
1101 - _MEDComponentsUnits.
1103 The data members of the returned field are initialized, based on the first field, except for the name,
1104 which is the combination of the two field's names and the operator.
1105 Advised Utilisation in C++ : <tt> FIELD<T> c = a / b; </tt> \n
1106 In this case, the (recent) compilators perform optimisation and don't call the copy constructor.
1107 When using python, this operator calls the copy constructor in any case.
1108 The user has to be aware that when using operator / in associatives expressions like
1109 <tt> a = b / c / d /e; </tt> \n
1110 no optimisation is performed : the evaluation of last expression requires the construction of
1114 const FIELD<T> FIELD<T>::operator/(const FIELD & m) const
1116 BEGIN_OF("FIELD<T>::operator/(const FIELD & m)");
1117 FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
1119 // Select mode : avoid if possible any calculation of other mode for fields m or *this
1121 if(this->getvalue()->getMode()==m.getvalue()->getMode() || this->getvalue()->isOtherCalculated())
1122 mode=m.getvalue()->getMode();
1124 mode=this->getvalue()->getMode();
1126 // Creation of the result - memory is allocated by FIELD constructor
1127 FIELD<T> result(this->getSupport(),this->getNumberOfComponents(),mode);
1128 //result._operation(*this,m,mode,"/"); // perform Atribute's initialization & division
1129 result._operationInitialize(*this,m,"/"); // perform Atribute's initialization
1130 result._div_in_place(*this,m,mode); // perform division
1132 END_OF("FIELD<T>::operator/(const FIELD & m)");
1137 /*! Overloaded Operator /=
1138 * Operations are directly performed in the first field's array.
1139 * This operation is authorized only for compatible fields that have the same support.
1142 FIELD<T>& FIELD<T>::operator/=(const FIELD & m)
1144 BEGIN_OF("FIELD<T>::operator/=(const FIELD & m)");
1145 FIELD_::_checkFieldCompatibility(*this, m); // may throw exception
1147 // We choose to keep *this mode, even if it may cost a re-calculation for m
1148 medModeSwitch mode=this->getvalue()->getMode();
1149 const T* value1=m.getValue(mode); // get pointers to the values we are adding
1151 // get a non const pointer to the inside array of values and perform operation
1152 T * value=const_cast<T *> (getValue(mode));
1153 const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
1154 const T* endV=value+size; // pointer to the end of value
1156 for(;value!=endV; value1++,value++)
1158 // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
1159 this->getvalue()->clearOtherMode();
1160 END_OF("FIELD<T>::operator/=(const FIELD & m)");
1165 /*! Division of fields. Static member function.
1166 * The function return a pointer to a new created field that holds the division.
1167 * Data members are checked for compatibility and initialized.
1168 * The user is in charge of memory deallocation.
1171 FIELD<T>* FIELD<T>::div(const FIELD& m, const FIELD& n)
1173 BEGIN_OF("FIELD<T>::div(const FIELD & m, const FIELD& n)");
1174 FIELD_::_checkFieldCompatibility(m, n); // may throw exception
1176 // Select mode : avoid if possible any calculation of other mode for fields m or *this
1178 if(m.getvalue()->getMode()==n.getvalue()->getMode() || n.getvalue()->isOtherCalculated())
1179 mode=m.getvalue()->getMode();
1181 mode=n.getvalue()->getMode();
1183 // Creation of a new field
1184 FIELD<T>* result = new FIELD<T>(m.getSupport(),m.getNumberOfComponents(),mode);
1185 result->_operationInitialize(m,n,"/"); // perform Atribute's initialization
1186 result->_div_in_place(m,n,mode); // perform division
1188 END_OF("FIELD<T>::div(const FIELD & m, const FIELD& n)");
1195 This internal method initialize the members of a new field created to hold the result of the operation Op .
1196 Initialization is based on the first field, except for the name, which is the combination of the two field's names
1201 void FIELD<T>::_operationInitialize(const FIELD& m,const FIELD& n, char* Op)
1203 MESSAGE("Appel methode interne _add" << Op);
1205 // Atribute's initialization (copy of the first field's attributes)
1206 // Other data members (_support, _numberOfValues) are initialized in the field's constr.
1207 setName(m.getName()+" "+Op+" "+n.getName());
1208 setComponentsNames(m.getComponentsNames());
1209 // not yet implemented setComponentType(m.getComponentType());
1210 setComponentsDescriptions(m.getComponentsDescriptions());
1211 setMEDComponentsUnits(m.getMEDComponentsUnits());
1213 // The following data member may differ from field m to n.
1214 // The initialization is done based on the first field.
1215 setComponentsUnits(m.getComponentsUnits());
1216 setIterationNumber(m.getIterationNumber());
1217 setTime(m.getTime());
1218 setOrderNumber(m.getOrderNumber());
1219 setValueType(m.getValueType());
1225 Internal method called by FIELD<T>::operator+ and FIELD<T>::add to perform addition "in place".
1226 This method is applied to a just created field with medModeSwitch mode.
1227 For this reason, the alternate mode doesn't need to be set to 0 after performing operation :
1232 void FIELD<T>::_add_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode)
1234 // get pointers to the values we are adding
1235 const T* value1=m.getValue(mode);
1236 const T* value2=n.getValue(mode);
1237 // get a non const pointer to the inside array of values and perform operation
1238 T * value=const_cast<T *> (getValue(mode));
1240 const int size=getNumberOfValues()*getNumberOfComponents();
1242 const T* endV1=value1+size;
1243 for(;value1!=endV1; value1++,value2++,value++)
1244 *value=(*value1)+(*value2);
1249 Internal method called by FIELD<T>::operator- and FIELD<T>::sub to perform substraction "in place".
1250 This method is applied to a just created field with medModeSwitch mode.
1251 For this reason, the alternate mode doesn't need to be set to 0 after performing operation :
1256 void FIELD<T>::_sub_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode)
1258 // get pointers to the values we are adding
1259 const T* value1=m.getValue(mode);
1260 const T* value2=n.getValue(mode);
1261 // get a non const pointer to the inside array of values and perform operation
1262 T * value=const_cast<T *> (getValue(mode));
1264 const int size=getNumberOfValues()*getNumberOfComponents();
1266 const T* endV1=value1+size;
1267 for(;value1!=endV1; value1++,value2++,value++)
1268 *value=(*value1)-(*value2);
1273 Internal method called by FIELD<T>::operator* and FIELD<T>::mul to perform multiplication "in place".
1274 This method is applied to a just created field with medModeSwitch mode.
1275 For this reason, the alternate mode doesn't need to be set to 0 after performing operation :
1280 void FIELD<T>::_mul_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode)
1282 // get pointers to the values we are adding
1283 const T* value1=m.getValue(mode);
1284 const T* value2=n.getValue(mode);
1285 // get a non const pointer to the inside array of values and perform operation
1286 T * value=const_cast<T *> (getValue(mode));
1288 const int size=getNumberOfValues()*getNumberOfComponents();
1290 const T* endV1=value1+size;
1291 for(;value1!=endV1; value1++,value2++,value++)
1292 *value=(*value1)*(*value2);
1297 Internal method called by FIELD<T>::operator/ and FIELD<T>::div to perform division "in place".
1298 This method is applied to a just created field with medModeSwitch mode.
1299 For this reason, the alternate mode doesn't need to be set to 0 after performing operation :
1304 void FIELD<T>::_div_in_place(const FIELD& m,const FIELD& n, const medModeSwitch mode)
1306 // get pointers to the values we are adding
1307 const T* value1=m.getValue(mode);
1308 const T* value2=n.getValue(mode);
1309 // get a non const pointer to the inside array of values and perform operation
1310 T * value=const_cast<T *> (getValue(mode));
1312 const int size=getNumberOfValues()*getNumberOfComponents();
1314 const T* endV1=value1+size;
1315 for(;value1!=endV1; value1++,value2++,value++)
1316 *value=(*value1)/(*value2);
1321 template <class T> double FIELD<T>::normMax() const throw (MEDEXCEPTION)
1323 const T* value=getValue(getvalue()->getMode()); // get pointer to the values
1324 const int size=getNumberOfValues()*getNumberOfComponents();
1325 if (size <= 0) // Size of array has to be strictly positive
1328 diagnosis="FIELD<T>::normMax() : cannot compute the norm of "+getName()+
1329 " : it size is non positive!";
1330 throw MEDEXCEPTION(diagnosis.c_str());
1332 const T* lastvalue=value+size; // get pointer just after last value
1333 const T* pMax=value; // pointer to the max value
1334 const T* pMin=value; // pointer to the min value
1336 // get pointers to the max & min value of array
1337 while ( ++value != lastvalue )
1339 if ( *pMin > *value )
1341 if ( *pMax < *value )
1345 T Max= *pMax>(T) 0 ? *pMax : -*pMax; // Max=abs(*pMax)
1346 T Min= *pMin>(T) 0 ? *pMin : -*pMin; // Min=abs(*pMin)
1348 return Max>Min ? static_cast<double>(Max) : static_cast<double>(Min);
1351 /*! Return Euclidien norm
1353 template <class T> double FIELD<T>::norm2() const throw (MEDEXCEPTION)
1355 const T* value=this->getValue(this->getvalue()->getMode()); // get const pointer to the values
1356 const int size=getNumberOfValues()*getNumberOfComponents(); // get size of array
1357 if (size <= 0) // Size of array has to be strictly positive
1360 diagnosis="FIELD<T>::norm2() : cannot compute the norm of "+getName()+
1361 " : it size is non positive!";
1362 throw MEDEXCEPTION(diagnosis.c_str());
1364 const T* lastvalue=value+size; // point just after last value
1366 T result((T)0); // init
1367 for( ; value!=lastvalue ; ++value)
1368 result += (*value) * (*value);
1370 return std::sqrt(static_cast<double> (result));
1374 /*! Apply to each (scalar) field component the template parameter T_function,
1375 * which is a pointer to function.
1376 * Since the pointer is known at compile time, the function is inlined into the inner loop!
1377 * calculation is done "in place".
1380 * \code myField.applyFunc<std::sqrt>(); // apply sqare root function \endcode
1381 * \code myField.applyFunc<myFunction>(); // apply your own created function \endcode
1383 template <class T> template <T T_function(T)>
1384 void FIELD<T>::applyFunc()
1386 medModeSwitch mode=getvalue()->getMode();
1388 // get a non const pointer to the inside array of values and perform operation
1389 T * value=const_cast<T *> (getValue(mode));
1390 const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
1392 if (size>0) // for a negative size, there is nothing to do
1394 const T* lastvalue=value+size; // pointer to the end of value
1395 for(;value!=lastvalue; ++value) // apply linear transformation
1396 *value = T_function(*value);
1397 // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
1398 getvalue()->clearOtherMode();
1403 /*! Apply to each (scalar) field component the linear function x -> ax+b.
1404 * calculation is done "in place".
1406 template <class T> void FIELD<T>::applyLin(T a, T b)
1408 medModeSwitch mode=getvalue()->getMode();
1410 // get a non const pointer to the inside array of values and perform operation in place
1411 T * value=const_cast<T *> (getValue(mode));
1412 const int size=getNumberOfValues()*getNumberOfComponents(); // size of array
1414 if (size>0) // for a negative size, there is nothing to do
1416 const T* lastvalue=value+size; // pointer to the end of value
1417 for(;value!=lastvalue; ++value) // apply linear transformation
1418 *value = a*(*value)+b;
1419 // if it exists, the alternate mode needs to be cleared because it is not up-to-date anymore
1420 getvalue()->clearOtherMode();
1426 * Return a pointer to a new field that holds the scalar product. Static member function.
1427 * This operation is authorized only for compatible fields that have the same support.
1428 * The compatibility checking includes equality tests of the folowing data members:\n
1430 * - _numberOfComponents
1432 * - _componentsTypes
1433 * - _MEDComponentsUnits.
1434 * Data members are initialized.
1435 * The new field point to the same support and has one component.
1436 * Each value of it is the scalar product of the two argument's fields.
1437 * The user is in charge of memory deallocation.
1439 template <class T> FIELD<T>* FIELD<T>::scalarProduct(const FIELD & m, const FIELD & n)
1441 FIELD_::_checkFieldCompatibility( m, n); // may throw exception
1442 // we need a MED_FULL_INTERLACE representation of m & n to compute the scalar product
1443 const medModeSwitch mode=MED_FULL_INTERLACE;
1445 const int numberOfElements=m.getNumberOfValues(); // strictly positive
1446 const int NumberOfComponents=m.getNumberOfComponents(); // strictly positive
1448 // Creation & init of a the result field on the same suppot, with one component
1449 FIELD<T>* result = new FIELD<T>(m.getSupport(),1,mode);
1450 result->setName( "scalarProduct ( " + m.getName() + " , " + n.getName() + " )" );
1451 result->setIterationNumber(m.getIterationNumber());
1452 result->setTime(m.getTime());
1453 result->setOrderNumber(m.getOrderNumber());
1454 result->setValueType(m.getValueType());
1456 const T* value1=m.getValue(mode); // get const pointer to the values
1457 const T* value2=n.getValue(mode); // get const pointer to the values
1458 // get a non const pointer to the inside array of values and perform operation
1459 T * value=const_cast<T *> (result->getValue(mode));
1461 const T* lastvalue=value+numberOfElements; // pointing just after last value of result
1462 for ( ; value!=lastvalue ; ++value ) // loop on all elements
1464 *value=(T)0; // initialize value
1465 const T* endofRow=value1+NumberOfComponents; // pointing just after end of row
1466 for ( ; value1 != endofRow; ++value1, ++value2) // computation of dot product
1467 *value += (*value1) * (*value2);
1472 /*! Return L2 Norm of the field's component.
1473 * Cannot be applied to a field with a support on nodes.
1474 * If the optional p_field_volume argument is furnished, the volume is not re-calculated.
1476 template <class T> double FIELD<T>::normL2(int component, const FIELD<double> * p_field_volume) const
1478 _checkNormCompatibility(p_field_volume); // may throw exception
1479 if ( component<1 || component>getNumberOfComponents() )
1480 throw MEDEXCEPTION(STRING("FIELD<T>::normL2() : The component argument should be between 1 and the number of components"));
1482 const FIELD<double> * p_field_size=p_field_volume;
1483 if(!p_field_volume) // if the user don't supply the volume
1484 p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
1486 // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
1487 const double* vol=p_field_size->getValue(MED_FULL_INTERLACE);
1488 const T* value=getValueI( MED_NO_INTERLACE, component); // get pointer to the component's values
1489 const T* lastvalue=value+getNumberOfValues(); // pointing just after the end of column
1491 double integrale=0.0;
1493 for (; value!=lastvalue ; ++value ,++vol)
1495 integrale += static_cast<double>((*value) * (*value)) * (*vol);
1499 if(!p_field_volume) // if the user didn't supply the volume
1500 delete p_field_size; // delete temporary volume field
1502 throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
1504 return integrale/totVol;
1507 /*! Return L2 Norm of the field.
1508 * Cannot be applied to a field with a support on nodes.
1509 * If the optional p_field_volume argument is furnished, the volume is not re-calculated.
1511 template <class T> double FIELD<T>::normL2(const FIELD<double> * p_field_volume) const
1513 _checkNormCompatibility(p_field_volume); // may throw exception
1514 const FIELD<double> * p_field_size=p_field_volume;
1515 if(!p_field_volume) // if the user don't supply the volume
1516 p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
1518 // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
1519 const double* vol=p_field_size->getValue(MED_FULL_INTERLACE);
1520 const double* lastvol=vol+getNumberOfValues(); // pointing just after the end of vol
1521 const T* value=getValue( MED_NO_INTERLACE); // get pointer to the field's values
1524 const double* p_vol=vol;
1525 for (p_vol=vol; p_vol!=lastvol ; ++p_vol) // calculate total volume
1528 double integrale=0.0;
1529 for (int i=1; i<=getNumberOfComponents(); ++i) // compute integral on all components
1530 for (p_vol=vol; p_vol!=lastvol ; ++value ,++p_vol)
1531 integrale += static_cast<double>((*value) * (*value)) * (*p_vol);
1533 if(!p_field_volume) // if the user didn't supply the volume
1534 delete p_field_size; // delete temporary volume field
1536 throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
1538 return integrale/totVol;
1541 /*! Return L1 Norm of the field's component.
1542 * Cannot be applied to a field with a support on nodes.
1543 * If the optional p_field_volume argument is furnished, the volume is not re-calculated.
1545 template <class T> double FIELD<T>::normL1(int component, const FIELD<double> * p_field_volume) const
1547 _checkNormCompatibility(p_field_volume); // may throw exception
1548 if ( component<1 || component>getNumberOfComponents() )
1549 throw MEDEXCEPTION(STRING("FIELD<T>::normL2() : The component argument should be between 1 and the number of components"));
1551 const FIELD<double> * p_field_size=p_field_volume;
1552 if(!p_field_volume) // if the user don't supply the volume
1553 p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
1555 // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
1556 const double* vol=p_field_size->getValue(MED_FULL_INTERLACE);
1557 const T* value=getValueI( MED_NO_INTERLACE, component); // get pointer to the component's values
1558 const T* lastvalue=value+getNumberOfValues(); // pointing just after the end of column
1560 double integrale=0.0;
1562 for (; value!=lastvalue ; ++value ,++vol)
1564 integrale += std::abs( static_cast<double>(*value) ) * (*vol);
1568 if(!p_field_volume) // if the user didn't supply the volume
1569 delete p_field_size; // delete temporary volume field
1571 throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
1573 return integrale/totVol;
1576 /*! Return L1 Norm of the field.
1577 * Cannot be applied to a field with a support on nodes.
1578 * If the optional p_field_volume argument is furnished, the volume is not re-calculated.
1580 template <class T> double FIELD<T>::normL1(const FIELD<double> * p_field_volume) const
1582 _checkNormCompatibility(p_field_volume); // may throw exception
1583 const FIELD<double> * p_field_size=p_field_volume;
1584 if(!p_field_volume) // if the user don't supply the volume
1585 p_field_size=_getFieldSize(); // we calculate the volume [PROVISOIRE, en attendant l'implémentation dans mesh]
1587 // get pointer to the element's volumes. MED_FULL_INTERLACE is the default mode for p_field_size
1588 const double* vol=p_field_size->getValue(MED_FULL_INTERLACE);
1589 const double* lastvol=vol+getNumberOfValues(); // pointing just after the end of vol
1590 const T* value=getValue( MED_NO_INTERLACE); // get pointer to the field's values
1593 const double* p_vol=vol;
1594 for (p_vol=vol; p_vol!=lastvol ; ++p_vol) // calculate total volume
1597 double integrale=0.0;
1598 for (int i=1; i<=getNumberOfComponents(); ++i) // compute integral on all components
1599 for (p_vol=vol; p_vol!=lastvol ; ++value ,++p_vol)
1600 integrale += std::abs( static_cast<double>(*value) ) * (*p_vol);
1602 if(!p_field_volume) // if the user didn't supply the volume
1603 delete p_field_size; // delete temporary volume field
1605 throw MEDEXCEPTION(STRING("cannot compute sobolev norm : volume is not positive!"));
1607 return integrale/totVol;
1614 Constructor with parameters; the object is set via a file and its associated
1615 driver. For the moment only the MED_DRIVER is considered and if the last two
1616 argument (iterationNumber and orderNumber) are not set; their default value
1617 is -1. If the field fieldDriverName with the iteration number
1618 iterationNumber and the order number orderNumber does not exist in the file
1619 fieldDriverName; the constructor raises an exception.
1621 template <class T> FIELD<T>::FIELD(const SUPPORT * Support,
1622 driverTypes driverType,
1623 const string & fileName/*=""*/,
1624 const string & fieldDriverName/*=""*/,
1625 const int iterationNumber,
1626 const int orderNumber)
1627 throw (MEDEXCEPTION)
1629 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) : ";
1638 _value = (MEDARRAY<T>*)NULL;
1640 _iterationNumber = iterationNumber;
1642 _orderNumber = orderNumber;
1648 MED_FIELD_RDONLY_DRIVER<T> myDriver(fileName,this);
1649 myDriver.setFieldName(fieldDriverName);
1650 current = addDriver(myDriver);
1653 // current = addDriver(driverType,fileName,fieldDriverName);
1654 // switch(_drivers[current]->getAccessMode() ) {
1655 // case MED_WRONLY : {
1656 // MESSAGE("FIELD<T>::FIELD(driverTypes driverType, .....) : driverType must have a MED_RDONLY or MED_RDWR accessMode");
1657 // rmDriver(current);
1664 throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Driver type unknown : can't create driver!"));
1669 _drivers[current]->open();
1670 _drivers[current]->read();
1671 _drivers[current]->close();
1679 template <class T> FIELD<T>::~FIELD()
1681 BEGIN_OF(" Destructeur FIELD<T>::~FIELD()");
1683 if (_value) delete _value;
1684 END_OF(" Destructeur FIELD<T>::~FIELD()");
1690 template <class T> void FIELD<T>::allocValue(const int NumberOfComponents)
1692 const char* LOC = "FIELD<T>::allocValue(const int NumberOfComponents)" ;
1695 _numberOfComponents = NumberOfComponents ;
1696 if (_componentsTypes == NULL)
1697 _componentsTypes = new int[NumberOfComponents] ;
1698 if (_componentsNames == NULL)
1699 _componentsNames = new string[NumberOfComponents];
1700 if (_componentsDescriptions == NULL)
1701 _componentsDescriptions = new string[NumberOfComponents];
1702 if (_componentsUnits == NULL)
1703 _componentsUnits = new UNIT[NumberOfComponents];
1704 if (_MEDComponentsUnits == NULL)
1705 _MEDComponentsUnits = new string[NumberOfComponents];
1706 for (int i=0;i<NumberOfComponents;i++) {
1707 _componentsTypes[i] = 0 ;
1711 _numberOfValues = _support->getNumberOfElements(MED_ALL_ELEMENTS);
1712 MESSAGE(LOC <<" : "<<_numberOfValues <<" et "<< NumberOfComponents);
1714 _value = new MEDARRAY<T>(_numberOfComponents,_numberOfValues);
1718 catch (MEDEXCEPTION &ex) {
1719 MESSAGE("No value defined, problem with NumberOfComponents (and may be _support) size of MEDARRAY<T>::_value !");
1720 _value = (MEDARRAY<T>*)NULL ;
1724 END_OF("void FIELD<T>::allocValue(const int NumberOfComponents)");
1730 template <class T> void FIELD<T>::allocValue(const int NumberOfComponents, const int LengthValue)
1732 BEGIN_OF("void FIELD<T>::allocValue(const int NumberOfComponents,const int LengthValue)");
1734 _numberOfComponents = NumberOfComponents ;
1735 if (_componentsTypes == NULL)
1736 _componentsTypes = new int[NumberOfComponents] ;
1737 if (_componentsNames == NULL)
1738 _componentsNames = new string[NumberOfComponents];
1739 if (_componentsDescriptions == NULL)
1740 _componentsDescriptions = new string[NumberOfComponents];
1741 if (_componentsUnits == NULL)
1742 _componentsUnits = new UNIT[NumberOfComponents];
1743 if (_MEDComponentsUnits == NULL)
1744 _MEDComponentsUnits = new string[NumberOfComponents];
1745 for (int i=0;i<NumberOfComponents;i++) {
1746 _componentsTypes[i] = 0 ;
1749 MESSAGE("FIELD : constructeur : "<<LengthValue <<" et "<< NumberOfComponents);
1750 _numberOfValues = LengthValue ;
1751 _value = new MEDARRAY<T>(_numberOfComponents,_numberOfValues);
1755 END_OF("void FIELD<T>::allocValue(const int NumberOfComponents,const int LengthValue)");
1761 template <class T> void FIELD<T>::deallocValue()
1763 BEGIN_OF("void FIELD<T>::deallocValue()");
1764 _numberOfValues = 0 ;
1765 _numberOfComponents = 0 ;
1769 END_OF("void FIELD<T>::deallocValue()");
1772 // -----------------
1774 // -----------------
1777 Create the specified driver and return its index reference to path to
1778 read or write methods.
1781 template <class T> int FIELD<T>::addDriver(driverTypes driverType,
1782 const string & fileName/*="Default File Name.med"*/,
1783 const string & driverName/*="Default Field Name"*/)
1785 const char * LOC = "FIELD<T>::addDriver(driverTypes driverType, const string & fileName=\"Default File Name.med\",const string & driverName=\"Default Field Name\") : ";
1793 driver = DRIVERFACTORY::buildDriverForField(driverType,fileName,this);
1795 _drivers.push_back(driver);
1797 int current = _drivers.size()-1;
1799 _drivers[current]->setFieldName(driverName);
1808 Duplicate the given driver and return its index reference to path to
1809 read or write methods.
1811 template <class T> inline int FIELD<T>::addDriver (GENDRIVER & driver )
1813 const char * LOC = "FIELD<T>::addDriver(GENDRIVER &) : ";
1818 // duplicate driver to delete it with destructor !
1819 GENDRIVER * newDriver = driver.copy() ;
1821 _drivers.push_back(newDriver);
1823 current = _drivers.size()-1;
1825 driver.setId(current);
1827 MESSAGE(LOC << " je suis la 1");
1829 MESSAGE(LOC << " je suis la 2");
1835 Remove the driver referenced by its index.
1837 template <class T> void FIELD<T>::rmDriver (int index/*=0*/)
1839 const char * LOC = "FIELD<T>::rmDriver (int index=0): ";
1842 if ( _drivers[index] ) {
1843 //_drivers.erase(&_drivers[index]);
1845 MESSAGE ("detruire");
1848 throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
1849 << "The <index given is invalid, index must be between 0 and |"
1858 Read FIELD in the file specified in the driver given by its index.
1860 template <class T> inline void FIELD<T>::read(int index/*=0*/)
1862 const char * LOC = "FIELD<T>::read(int index=0) : ";
1865 if ( _drivers[index] ) {
1866 _drivers[index]->open();
1867 _drivers[index]->read();
1868 _drivers[index]->close();
1871 throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
1872 << "The index given is invalid, index must be between 0 and |"
1880 Write FIELD in the file specified in the driver given by its index.
1882 template <class T> inline void FIELD<T>::write(int index/*=0*/, const string & driverName /*= ""*/)
1884 const char * LOC = "FIELD<T>::write(int index=0, const string & driverName = \"\") : ";
1887 if( _drivers[index] ) {
1888 _drivers[index]->open();
1889 if (driverName != "") _drivers[index]->setFieldName(driverName);
1890 _drivers[index]->write();
1891 _drivers[index]->close();
1894 throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
1895 << "The index given is invalid, index must be between 0 and |"
1903 Write FIELD in the file specified in the driver given by its index. Use this
1904 method for ASCII drivers (e.g. VTK_DRIVER)
1906 template <class T> inline void FIELD<T>::writeAppend(int index/*=0*/, const string & driverName /*= ""*/)
1908 const char * LOC = "FIELD<T>::write(int index=0, const string & driverName = \"\") : ";
1911 if( _drivers[index] ) {
1912 _drivers[index]->openAppend();
1913 if (driverName != "") _drivers[index]->setFieldName(driverName);
1914 _drivers[index]->writeAppend();
1915 _drivers[index]->close();
1918 throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
1919 << "The index given is invalid, index must be between 0 and |"
1928 Write FIELD with the driver which is equal to the given driver.
1932 template <class T> inline void FIELD<T>::write(const GENDRIVER & genDriver)
1934 const char * LOC = " FIELD<T>::write(const GENDRIVER &) : ";
1937 for (unsigned int index=0; index < _drivers.size(); index++ )
1938 if ( *_drivers[index] == genDriver ) {
1939 _drivers[index]->open();
1940 _drivers[index]->write();
1941 _drivers[index]->close();
1950 Write FIELD with the driver which is equal to the given driver.
1952 Use by MED object. Use this method for ASCII drivers (e.g. VTK_DRIVER).
1954 template <class T> inline void FIELD<T>::writeAppend(const GENDRIVER & genDriver)
1956 const char * LOC = " FIELD<T>::write(const GENDRIVER &) : ";
1959 for (unsigned int index=0; index < _drivers.size(); index++ )
1960 if ( *_drivers[index] == genDriver ) {
1961 _drivers[index]->openAppend();
1962 _drivers[index]->writeAppend();
1963 _drivers[index]->close();
1972 Read FIELD with the driver which is equal to the given driver.
1976 template <class T> inline void FIELD<T>::read(const GENDRIVER & genDriver)
1978 const char * LOC = " FIELD<T>::read(const GENDRIVER &) : ";
1981 for (unsigned int index=0; index < _drivers.size(); index++ )
1982 if ( *_drivers[index] == genDriver ) {
1983 _drivers[index]->open();
1984 _drivers[index]->read();
1985 _drivers[index]->close();
1994 Destroy the MEDARRAY<T> in FIELD and put the new one without copy.
1997 template <class T> inline void FIELD<T>::setValue(MEDARRAY<T> *Value)
1999 if (NULL != _value) delete _value ;
2005 Return a reference to the MEDARRAY<T> in FIELD.
2008 template <class T> inline MEDARRAY<T>* FIELD<T>::getvalue() const
2014 Return the actual length of the reference to values array returned by getValue.
2016 template <class T> inline int FIELD<T>::getValueLength(medModeSwitch Mode) const{
2017 return _numberOfComponents*_numberOfValues;
2021 Return a reference to values array to read them.
2023 template <class T> inline const T* FIELD<T>::getValue(medModeSwitch Mode) const
2025 return _value->get(Mode) ;
2029 Return a reference to i^{th} row or column - component - (depend on Mode value)
2030 of FIELD values array.
2032 template <class T> inline const T* FIELD<T>::getValueI(medModeSwitch Mode,int i) const
2034 if ( Mode == MED_FULL_INTERLACE )
2036 return _value->getRow(i) ;
2038 ASSERT ( Mode == MED_NO_INTERLACE);
2039 return _value->getColumn(i);
2043 Return the value of i^{th} element and j^{th} component.
2045 template <class T> inline T FIELD<T>::getValueIJ(int i,int j) const
2047 return _value->getIJ(i,j) ;
2051 Copy new values array in FIELD according to the given mode.
2053 Array must have right size. If not results are unpredicable.
2055 template <class T> inline void FIELD<T>::setValue(medModeSwitch mode, T* value)
2057 _value->set(mode,value);
2061 Update values array in FIELD with the given ones according to specified mode.
2063 template <class T> inline void FIELD<T>::setValueI(medModeSwitch mode, int i, T* value)
2066 if (MED_FULL_INTERLACE == mode)
2067 _value->setI(i,value);
2068 else if (MED_NO_INTERLACE == mode)
2069 _value->setJ(i,value);
2071 throw MEDEXCEPTION(LOCALIZED("FIELD<T>::setValueI : bad medModeSwitch")) ;
2075 Set the value of i^{th} element and j^{th} component with the given one.
2077 template <class T> inline void FIELD<T>::setValueIJ(int i, int j, T value)
2079 _value->setIJ(i,j,value);
2087 Fill values array with volume values.
2089 template <class T> void FIELD<T>::getVolume() const throw (MEDEXCEPTION)
2091 const char * LOC = "FIELD<double>::getVolume() const : ";
2094 // The field has to be initilised by a non empty support and a
2095 // number of components = 1 and its value type has to be set to MED_REEL64
2096 // (ie a FIELD<double>)
2098 if ((_support == (SUPPORT *) NULL) || (_numberOfComponents != 1) || (_valueType != MED_REEL64))
2099 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"));
2105 Fill values array with area values.
2107 template <class T> void FIELD<T>::getArea() const throw (MEDEXCEPTION)
2109 const char * LOC = "FIELD<double>::getArea() const : ";
2112 // The field has to be initilised by a non empty support and a
2113 // number of components = 1 and its value type has to be set to MED_REEL64
2114 // (ie a FIELD<double>)
2116 if ((_support == (SUPPORT *) NULL) || (_numberOfComponents != 1) || (_valueType != MED_REEL64))
2117 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"));
2123 Fill values array with length values.
2125 template <class T> void FIELD<T>::getLength() const throw (MEDEXCEPTION)
2127 const char * LOC = "FIELD<double>::getLength() const : ";
2130 // The field has to be initilised by a non empty support and a
2131 // number of components = 1 and its value type has to be set to MED_REEL64
2132 // (ie a FIELD<double>)
2134 if ((_support == (SUPPORT *) NULL) || (_numberOfComponents != 1) || (_valueType != MED_REEL64))
2135 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"));
2141 Fill values array with normal values.
2143 template <class T> void FIELD<T>::getNormal() const throw (MEDEXCEPTION)
2145 const char * LOC = "FIELD<double>::getNormal() const : ";
2148 // The field has to be initilised by a non empty support and a
2149 // number of components = 1 and its value type has to be set to MED_REEL64
2150 // (ie a FIELD<double>)
2152 if (_support == (SUPPORT *) NULL)
2153 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"));
2155 int dim_space = _support->getMesh()->getSpaceDimension();
2157 if ((_numberOfComponents != dim_space) || (_valueType != MED_REEL64))
2158 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"));
2164 Fill values array with barycenter values.
2166 template <class T> void FIELD<T>::getBarycenter() const throw (MEDEXCEPTION)
2168 const char * LOC = "FIELD<double>::getBarycenter() const : ";
2171 // The field has to be initilised by a non empty support and a number of
2172 //components = space dimension and its value type has to be set to MED_REEL64
2173 // (ie a FIELD<double>)
2175 if (_support == (SUPPORT *) NULL)
2176 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"));
2178 int dim_space = _support->getMesh()->getSpaceDimension();
2180 if ((_numberOfComponents != dim_space) || (_valueType != MED_REEL64))
2181 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"));
2186 #endif /* FIELD_HXX */