Skip to content
Snippets Groups Projects
Select Git revision
  • ebeb8263d661db7e97449728ce5aa7ba3bad181d
  • master default
  • cgnsUnstructured
  • partitioning
  • poppler
  • HighOrderBLCurving
  • gmsh_3_0_4
  • gmsh_3_0_3
  • gmsh_3_0_2
  • gmsh_3_0_1
  • gmsh_3_0_0
  • gmsh_2_16_0
  • gmsh_2_15_0
  • gmsh_2_14_1
  • gmsh_2_14_0
  • gmsh_2_13_2
  • gmsh_2_13_1
  • gmsh_2_12_0
  • gmsh_2_11_0
  • gmsh_2_10_1
  • gmsh_2_10_0
  • gmsh_2_9_3
  • gmsh_2_9_2
  • gmsh_2_9_1
  • gmsh_2_9_0
  • gmsh_2_8_6
26 results

LuaBindings.cpp

Blame
  • Forked from gmsh / gmsh
    Source project has a limited visibility.
    Cal_Quantity.cpp 43.75 KiB
    // GetDP - Copyright (C) 1997-2017 P. Dular and C. Geuzaine, University of Liege
    //
    // See the LICENSE.txt file for license information. Please report all
    // bugs and problems to the public mailing list <getdp@onelab.info>.
    
    #include <string.h>
    #include <math.h>
    #include <map>
    #include "ProData.h"
    #include "GeoData.h"
    #include "DofData.h"
    #include "F.h"
    #include "Cal_Quantity.h"
    #include "Cal_Value.h"
    #include "Get_Geometry.h"
    #include "Pos_FemInterpolation.h"
    #include "Pos_Search.h"
    #include "Get_FunctionValue.h"
    #include "MallocUtils.h"
    #include "Message.h"
    #include "ProParser.h"
    #include "Pos_Format.h"
    
    extern struct Problem Problem_S ;
    extern struct CurrentData Current ;
    extern int TreatmentStatus ;
    
    /* ------------------------------------------------------------------------ */
    /*  G e t _ V a l u e O f E x p r e s s i o n                               */
    /* ------------------------------------------------------------------------ */
    
    void  Get_ValueOfExpression(struct Expression * Expression_P,
    			    struct QuantityStorage * QuantityStorage_P0,
    			    double u, double v, double w,
    			    struct Value * Value,
    			    int    NbrArguments,
    			    char   *CallingExpressionName)
    {
      static char *Flag_WarningUndefined = NULL ;
    
      switch (Expression_P->Type) {
    
      case CONSTANT :
        if (Current.NbrHar == 1) {
          Value->Val[0] = Expression_P->Case.Constant ;
        }
        else {
          for (int k = 0 ; k < Current.NbrHar ; k += 2) {
    	Value->Val[MAX_DIM* k   ] = Expression_P->Case.Constant ;
    	Value->Val[MAX_DIM*(k+1)] = 0. ;
          }
        }
        Value->Type = SCALAR ;
        break ;
    
      case WHOLEQUANTITY :
        Cal_WholeQuantity(Current.Element, QuantityStorage_P0,
    		      Expression_P->Case.WholeQuantity,
    		      u,v,w, -1, 0, Value, NbrArguments,
    		      CallingExpressionName ?
    		          CallingExpressionName : Expression_P->Name) ;
        break ;
    
      case PIECEWISEFUNCTION :
        struct Expression * NextExpression_P;
        struct ExpressionPerRegion  * ExpressionPerRegion_P ;
    
        if (Current.Region == Expression_P->Case.PieceWiseFunction.NumLastRegion) {
          NextExpression_P = Expression_P->Case.PieceWiseFunction.ExpressionForLastRegion;
        }
        else {
          if ((ExpressionPerRegion_P = (struct ExpressionPerRegion*)
    	   List_PQuery(Expression_P->Case.PieceWiseFunction.ExpressionPerRegion,
    		       &Current.Region, fcmp_int))) {
    	Expression_P->Case.PieceWiseFunction.NumLastRegion = Current.Region ;
    	NextExpression_P =
              Expression_P->Case.PieceWiseFunction.ExpressionForLastRegion =
    	  (struct Expression*)List_Pointer(Problem_S.Expression,
    					   ExpressionPerRegion_P->ExpressionIndex) ;
          }
          else if (Expression_P->Case.PieceWiseFunction.ExpressionIndex_Default >= 0) {
            NextExpression_P =
    	  (struct Expression*)
              List_Pointer(Problem_S.Expression,
                           Expression_P->Case.PieceWiseFunction.ExpressionIndex_Default) ;
          }
          else {
            NextExpression_P = NULL;
    	if(Current.Region == NO_REGION)
    	  Message::Error("Function '%s' undefined in expressions without support",
                             Expression_P->Name);
    	else
    	  Message::Error("Function '%s' undefined in Region %d",
                             Expression_P->Name, Current.Region);
          }
        }
    
        Get_ValueOfExpression
          (NextExpression_P,
           QuantityStorage_P0, u, v, w, Value, NbrArguments, Expression_P->Name) ;
        break ;
    
      case PIECEWISEFUNCTION2 :
        //    struct Expression * NextExpression_P;
        struct ExpressionPerRegion2  * ExpressionPerRegion2_P ;
        int twoRegions[2];
    
        if (Current.Region == Expression_P->Case.PieceWiseFunction2.NumLastRegion[0] &&
            Current.SubRegion == Expression_P->Case.PieceWiseFunction2.NumLastRegion[1]) {
          NextExpression_P = Expression_P->Case.PieceWiseFunction2.ExpressionForLastRegion;
        }
        else {
          twoRegions[0] = Current.Region;
          twoRegions[1] = Current.SubRegion;
          if ((ExpressionPerRegion2_P = (struct ExpressionPerRegion2*)
    	   List_PQuery(Expression_P->Case.PieceWiseFunction2.ExpressionPerRegion,
    		       twoRegions, fcmp_Integer2))) {
    	Expression_P->Case.PieceWiseFunction2.NumLastRegion[0] = Current.Region ;
    	Expression_P->Case.PieceWiseFunction2.NumLastRegion[1] = Current.SubRegion ;
    	NextExpression_P =
              Expression_P->Case.PieceWiseFunction2.ExpressionForLastRegion =
    	  (struct Expression*)List_Pointer(Problem_S.Expression,
    					   ExpressionPerRegion2_P->ExpressionIndex) ;
          }
          else if (Expression_P->Case.PieceWiseFunction.ExpressionIndex_Default >= 0) {
            NextExpression_P =
    	  (struct Expression*)
              List_Pointer(Problem_S.Expression,
                           Expression_P->Case.PieceWiseFunction.ExpressionIndex_Default) ;
          }
          else {
            NextExpression_P = NULL;
    	if(Current.Region == NO_REGION)
    	  Message::Error("Function '%s' undefined in expressions without support",
                             Expression_P->Name);
    	else
    	  Message::Error("Function '%s' undefined in [ Region %d, SubRegion %d ]",
                             Expression_P->Name, Current.Region, Current.SubRegion);
          }
        }
    
        Get_ValueOfExpression
          (NextExpression_P,
           QuantityStorage_P0, u, v, w, Value, NbrArguments, Expression_P->Name) ;
        break ;
    
      case UNDEFINED_EXP :
        if(!Flag_WarningUndefined || strcmp(Flag_WarningUndefined, Expression_P->Name)){
          Message::Warning("Undefined expression '%s' (assuming zero)", Expression_P->Name) ;
          Flag_WarningUndefined = Expression_P->Name;
        }
        Cal_ZeroValue(Value);
        Value->Type = SCALAR ;
        break;
    
      default :
        Message::Error("Unknown type (%d) of Expression (%s)",
                       Expression_P->Type, Expression_P->Name) ;
        break;
      }
    }
    
    /* ------------------------------------------------------------------------ */
    /*  G e t _ V a l u e O f E x p r e s s i o n B y I n d e x                 */
    /* ------------------------------------------------------------------------ */
    
    void Get_ValueOfExpressionByIndex(int Index_Expression,
                                      struct QuantityStorage * QuantityStorage_P0,
                                      double u, double v, double w,
                                      struct Value * Value) {
      Get_ValueOfExpression
        ((struct Expression *)List_Pointer(Problem_S.Expression, Index_Expression),
         QuantityStorage_P0,  u, v, w, Value) ;
    }
    
    bool Is_ExpressionConstant(struct Expression * Expression_P)
    {
      if(Expression_P->Type == CONSTANT) return true;
      if(Expression_P->Type == WHOLEQUANTITY){
        for(int i = 0; i < List_Nbr(Expression_P->Case.WholeQuantity); i++){
          struct WholeQuantity *WholeQuantity_P = (struct WholeQuantity*)
            List_Pointer(Expression_P->Case.WholeQuantity, i);
          if(WholeQuantity_P->Type != WQ_CONSTANT)
            return false;
        }
        return true;
      }
      return false;
    }
    
    /* ------------------------------------------------------------------------ */
    /*  C a l _ S o l i d A n g l e                                             */
    /* ------------------------------------------------------------------------ */
    
    void Cal_SolidAngle(int Source, struct Element *Element,
    		    struct QuantityStorage *QuantityStorage,
    		    int Nbr_Dof, int Index,
    		    struct Value **Stack)
    {
      struct Element     *Elt ;
      struct Geo_Element *GeoElement ;
      struct Geo_Node    *GeoNode1, *GeoNode2, *GeoNode3 ;
    
      double X, Y, Atan ;
      int    In, TypEnt, NumNode, NbrElements, *NumElements ;
      int    i, j ;
    
      if(Nbr_Dof != QuantityStorage->NbrElementaryBasisFunction){
        Message::Error("Uncompatible Quantity (%s) in SolidAngle computation",
                       QuantityStorage->DefineQuantity->Name);
        return;
      }
    
      if(Source){
        Elt = Element->ElementSource ;
        In  = Current.SourceIntegrationSupportIndex ;
      }
      else{
        Elt = Element ;
        In  = Current.IntegrationSupportIndex ;
      }
    
      if (Elt->NumLastElementForSolidAngle == Elt->Num) {
        for(i=0 ; i<Nbr_Dof ; i++) {
          Stack[i][Index].Type = SCALAR ;
          Stack[i][Index].Val[0] = Elt->angle[i] ;
        }
        return;
      }
    
      for(i=0 ; i<Nbr_Dof ; i++){
    
        Stack[i][Index].Type = SCALAR ;
    
        TypEnt = ((struct Group*)
    	      List_Pointer(Problem_S.Group,
    			   QuantityStorage->BasisFunction[i].
    			   BasisFunction->EntityIndex))->FunctionType ;
    
        if(TypEnt != NODESOF){
    
          if(Elt->Type == LINE){
    	Stack[i][Index].Val[0] = M_PI ;
          }
          else{
    	Stack[i][Index].Val[0] = 2.*M_PI ;
          }
    
        }
    
        else{
    
          NumNode = Elt->GeoElement->
    	NumNodes[QuantityStorage->BasisFunction[i].NumEntityInElement] ;
    
          Geo_CreateNodesXElements(NumNode, In, &NbrElements, &NumElements) ;
    
          if(NbrElements != 2){
    	Message::Error("SolidAngle not done for incidence != 2 (%d)", NbrElements);
            return;
          }
    
          GeoNode2 = Geo_GetGeoNodeOfNum(NumNode) ;
          GeoElement = Geo_GetGeoElementOfNum(abs(NumElements[0])) ;
    
          if(GeoElement->Type != LINE){
    	Message::Error("SolidAngle not done for Elements other than LINE");
            return;
          }
    
          if(NumElements[0]>0){
    	GeoNode1 = Geo_GetGeoNodeOfNum(GeoElement->NumNodes[0]) ;
    	GeoElement = Geo_GetGeoElementOfNum(abs(NumElements[1])) ;
    	GeoNode3 = Geo_GetGeoNodeOfNum(GeoElement->NumNodes[1]) ;
    
          }
          else{
    	GeoNode3 = Geo_GetGeoNodeOfNum(GeoElement->NumNodes[1]) ;
    	GeoElement = Geo_GetGeoElementOfNum(NumElements[1]) ;
    	GeoNode1 = Geo_GetGeoNodeOfNum(GeoElement->NumNodes[0]) ;
          }
    
          Y = (GeoNode1->y - GeoNode2->y) * (GeoNode3->x - GeoNode2->x) -
    	  (GeoNode1->x - GeoNode2->x) * (GeoNode3->y - GeoNode2->y) ;
          X = (GeoNode1->x - GeoNode2->x) * (GeoNode3->x - GeoNode2->x) +
    	  (GeoNode1->y - GeoNode2->y) * (GeoNode3->y - GeoNode2->y) ;
    
          Atan = atan2(Y,X) ;
    
          Stack[i][Index].Val[0] = (Atan >= 0) ? Atan : (Atan+2.*M_PI) ;
    
          if(Message::GetVerbosity() > 5){
    	printf("Solid angle=%g node=%d, region=%s, elms=",
    	       Stack[i][Index].Val[0] * 180/M_PI, NumNode,
    	       ((struct Group*)List_Pointer(Problem_S.Group, In))->Name);
    	for(j=0 ; j<NbrElements ; j++) printf("%d ", NumElements[j]);
    	printf("\n");
          }
    
        }
    
      }
    
      if (Elt->NumLastElementForSolidAngle != Elt->Num) {
        Elt->NumLastElementForSolidAngle = Elt->Num ;
        for(i=0 ; i<Nbr_Dof ; i++) Elt->angle[i] = Stack[i][Index].Val[0] ;
      }
    }
    
    /* ------------------------------------------------------------------------ */
    /*  C a l _ W h o l e Q u a n t i t y                                       */
    /* ------------------------------------------------------------------------ */
    
    #define CAST3V    void(*)(struct Value*, struct Value*, struct Value*)
    #define CAST1V    void(*)(struct Value*)
    #define CASTF2V   void(*)(struct Function*, struct Value*, struct Value*)
    
    // There can be at max one "Dof{op qty}" per WholeQuantity, but as
    // many {op qty} as you want.
    
    static std::map<int, struct Value> ValueSaved ;
    static std::map<std::string, struct Value> NamedValueSaved ;
    
    void Cal_WholeQuantity(struct Element * Element,
    		       struct QuantityStorage * QuantityStorage_P0,
    		       List_T * WholeQuantity_L,
    		       double u, double v, double w,
    		       int DofIndexInWholeQuantity,
    		       int Nbr_Dof, struct Value DofValue[],
    		       int NbrArguments, char *ExpressionName) {
    
      static int Flag_WarningMissSolForDt = 0 ;
      static int Flag_WarningMissSolForTime_ntime = 0 ;
      static int Flag_InfoForTime_ntime = 0 ;
    
      int     i_WQ, j, k, Flag_True, Index, DofIndex, Multi[MAX_STACK_SIZE] ;
      int     Save_NbrHar, Save_Region, Type_Dimension, ntime ;
      double  Save_Time, Save_TimeImag, Save_TimeStep, X, Y, Z, Order ;
      double  Save_x, Save_y, Save_z ;
    
      struct WholeQuantity   *WholeQuantity_P0, *WholeQuantity_P ;
      struct DofData         *Save_DofData ;
      struct Solution        *Solution_P0, *Solution_PN ;
    
      struct Element* Save_CurrentElement ;
    
      // we could make this dynamic (with std::vector) to reduce stack usage, but
      // the performance hit is important
      struct Value Stack[8][MAX_STACK_SIZE] ;
    
      WholeQuantity_P0 = (struct WholeQuantity*)List_Pointer(WholeQuantity_L, 0) ;
    
      Index     = 0 ;
      DofIndex  = -1 ;
    
      for (i_WQ = 0 ; i_WQ < List_Nbr(WholeQuantity_L) ; i_WQ++) {
    
        if(Index >= MAX_STACK_SIZE){
          Message::Error("Stack size exceeded (%d)", MAX_STACK_SIZE);
          return;
        }
    
        WholeQuantity_P = WholeQuantity_P0 + i_WQ ;
    
        switch (WholeQuantity_P->Type) {
    
        case WQ_OPERATORANDQUANTITY : /* {op qty}  Dof{op qty}  BF{op qty} */
          Save_Region = Current.Region ;
          Save_CurrentElement = Current.Element ;
          if (i_WQ != DofIndexInWholeQuantity){ /* Attention!!! || TreatmentStatus == _POS){  */
    	Pos_FemInterpolation
    	  (Element,
    	   QuantityStorage_P0,
    	   QuantityStorage_P0 + WholeQuantity_P->Case.OperatorAndQuantity.Index,
    	   WholeQuantity_P->Case.OperatorAndQuantity.TypeQuantity,
    	   WholeQuantity_P->Case.OperatorAndQuantity.TypeOperator, -1, 0,
    	   u, v, w, 0, 0, 0, Stack[0][Index].Val, &Stack[0][Index].Type, 1) ;
    	Multi[Index] = 0 ;
          }
          else {
    	DofIndex = Index ;
          }
          Index++ ;
          Current.Element = Save_CurrentElement ;
          Current.Region = Save_Region ;
          break ;
    
        case WQ_ORDER : /* Order[{qty}] */
          Order = Cal_InterpolationOrder
    	(Element, QuantityStorage_P0 + WholeQuantity_P->Case.OperatorAndQuantity.Index) ;
          for (k = 0 ; k < Current.NbrHar ; k += 2) {
    	Stack[0][Index].Val[MAX_DIM* k   ] = Order ;
    	Stack[0][Index].Val[MAX_DIM*(k+1)] = 0. ;
          }
          Stack[0][Index].Type = SCALAR ;
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_OPERATORANDQUANTITYEVAL :
          Save_Region = Current.Region ;
          Save_CurrentElement = Current.Element ;
          /* {op qty}[x,y,z], {op qty}[x,y,z,dimension]
    	 or {op qty}[Vector[x,y,x],dimension]
    	 or {op qty}[ntime] */
          if (i_WQ != DofIndexInWholeQuantity || TreatmentStatus == _POS){
    	j = WholeQuantity_P->Case.OperatorAndQuantity.NbrArguments;
    	if (j == 2 || j == 3 || j == 4) {
    	  if (j == 3 || j == 4) {
    	    Index -= j ;
    	    X = Stack[0][Index  ].Val[0] ;
    	    Y = Stack[0][Index+1].Val[0] ;
    	    Z = Stack[0][Index+2].Val[0] ;
    	    if(j == 4)
    	      Type_Dimension = (int)Stack[0][Index+3].Val[0] ;
    	    else
    	      Type_Dimension = -1 ;
    	  }
    	  else { /* j==2 */
    	    Index -= j ;
    	    X = Stack[0][Index  ].Val[0] ;
    	    Y = Stack[0][Index  ].Val[1] ;
    	    Z = Stack[0][Index  ].Val[2] ;
    	    Type_Dimension = (int)Stack[0][Index+1].Val[0] ;
    	  }
    	  Pos_FemInterpolation
    	    (Element,
    	     QuantityStorage_P0,
    	     QuantityStorage_P0 + WholeQuantity_P->Case.OperatorAndQuantity.Index,
    	     WholeQuantity_P->Case.OperatorAndQuantity.TypeQuantity,
    	     WholeQuantity_P->Case.OperatorAndQuantity.TypeOperator, Type_Dimension, 1,
    	     u, v, w, X, Y, Z, Stack[0][Index].Val, &Stack[0][Index].Type, 1) ;
    	  Multi[Index] = 0 ;
    	  Index++ ;
    	}
    	else if (j == 1) {
    	  Index -= j ;
    	  ntime = (int)Stack[0][Index].Val[0] ;
    
    	  for (k = 0 ; k < Current.NbrSystem ; k++){
    	    Solution_P0 = (struct Solution*)List_Pointer((Current.DofData_P0+k)->Solutions, 0);
    	    if(((Current.DofData_P0+k)->CurrentSolution - Solution_P0) >= ntime){
    	      ((Current.DofData_P0+k)->CurrentSolution) -= ntime ;
    	      if (Flag_InfoForTime_ntime != List_Nbr((Current.DofData_P0+k)->Solutions)) {
    		Message::Debug("Accessing solution from %d time steps ago", ntime);
    		Message::Debug("  -> System %d/%d: TimeStep = %d, Time = %g + i * %g",
                                   k+1, Current.NbrSystem,
                                   (Current.DofData_P0+k)->CurrentSolution->TimeStep,
                                   (Current.DofData_P0+k)->CurrentSolution->Time,
                                   (Current.DofData_P0+k)->CurrentSolution->TimeImag);
    		Flag_InfoForTime_ntime = List_Nbr((Current.DofData_P0+k)->Solutions);
    	      }
    	    }
    	    else {
    	      if (!Flag_WarningMissSolForTime_ntime) {
    		Message::Warning("Missing solution for time step -%d computation (System #%d/%d)",
                                     ntime, k+1, Current.NbrSystem);
    		Flag_WarningMissSolForTime_ntime = 1 ;
    	      }
    	    }
    	  }
    
    	  Pos_FemInterpolation
    	    (Element,
    	     QuantityStorage_P0,
    	     QuantityStorage_P0 + WholeQuantity_P->Case.OperatorAndQuantity.Index,
    	     WholeQuantity_P->Case.OperatorAndQuantity.TypeQuantity,
    	     WholeQuantity_P->Case.OperatorAndQuantity.TypeOperator, -1, 0,
    	     u, v, w, 0, 0, 0, Stack[0][Index].Val, &Stack[0][Index].Type, 1) ;
    
    	  Multi[Index] = 0 ;
    	  Index++ ;
    
    	  for (k = 0 ; k < Current.NbrSystem ; k++){
    	    Solution_PN = (struct Solution*)
    	      List_Pointer((Current.DofData_P0+k)->Solutions,
    			   List_Nbr((Current.DofData_P0+k)->Solutions)-1);
    	    if((Solution_PN - (Current.DofData_P0+k)->CurrentSolution) >= ntime)
    	      ((Current.DofData_P0+k)->CurrentSolution) += ntime ;
    	  }
    
    	}
    	else
    	  Message::Error("Explicit (x,y,z,time) evaluation not implemented");
          }
          else{
    	Message::Error("Explicit Dof{} evaluation out of context");
          }
          Current.Element = Save_CurrentElement ;
          Current.Region = Save_Region ;
          break ;
    
        case WQ_TRACE : /* Trace[WholeQuantity, Group] */
          Save_Region = Current.Region ;
    
          if(!Element->ElementTrace){
    	Message::Error("Trace must act on discrete quantity (and not in post-processing)");
            break;
          }
    
          Current.Region = Element->ElementTrace->Region ;
    
          if(WholeQuantity_P->Case.Trace.DofIndexInWholeQuantity >= 0){
    	Cal_WholeQuantity(Element->ElementTrace, QuantityStorage_P0,
    			  WholeQuantity_P->Case.Trace.WholeQuantity,
    			  Current.ut, Current.vt, Current.wt,
    			  WholeQuantity_P->Case.Trace.DofIndexInWholeQuantity,
    			  Nbr_Dof, DofValue, NbrArguments, ExpressionName) ;
    	DofIndexInWholeQuantity = DofIndex = Index ;
          }
          else{
    	Current.x = Current.y = Current.z = 0. ;
    	for (j = 0 ; j < Element->GeoElement->NbrNodes ; j++) {
    	  Current.x += Element->x[j] * Element->n[j] ;
    	  Current.y += Element->y[j] * Element->n[j] ;
    	  Current.z += Element->z[j] * Element->n[j] ;
    	}
    	xyz2uvwInAnElement(Element->ElementTrace, Current.x, Current.y, Current.z,
    			   &Current.ut, &Current.vt, &Current.wt) ;
    	for (j=0; j<NbrArguments; j++) {
              Cal_CopyValue(DofValue + j, &Stack[0][Index]) ;
              Multi[Index] = 0 ;
              Index++ ;
            }
            Index -= NbrArguments ;
    	Cal_WholeQuantity(Element->ElementTrace, QuantityStorage_P0,
    			  WholeQuantity_P->Case.Trace.WholeQuantity,
    			  Current.ut, Current.vt, Current.wt,
    			  -1, 0, &Stack[0][Index], NbrArguments, ExpressionName) ;
          }
    
          Current.Region = Save_Region ;
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_SOLIDANGLE : /* SolidAngle[{qty}] */
          Cal_SolidAngle(0, Element, QuantityStorage_P0 +
    		     WholeQuantity_P->Case.OperatorAndQuantity.Index,
    		     Nbr_Dof, Index, (struct Value **)Stack);
          Multi[Index] = 1 ;
          Index++ ;
          break ;
    
        case WQ_BINARYOPERATOR : /* + - * x / % ^ < > <= >= == != && || */
          if (Index-2 != DofIndex && Index-1 != DofIndex){
    	if(!Multi[Index-1] && !Multi[Index-2])
    	  ((CAST3V)WholeQuantity_P->Case.Operator.Function)
    	    (&Stack[0][Index-2], &Stack[0][Index-1], &Stack[0][Index-2]) ;
    	else if(Multi[Index-1] && Multi[Index-2])
    	  for(j=0 ; j<Nbr_Dof ; j++)
    	    ((CAST3V)WholeQuantity_P->Case.Operator.Function)
    	      (&Stack[j][Index-2], &Stack[j][Index-1], &Stack[j][Index-2]) ;
    	else if(Multi[Index-2])
    	  for(j=0 ; j<Nbr_Dof ; j++)
    	    ((CAST3V)WholeQuantity_P->Case.Operator.Function)
    	      (&Stack[j][Index-2], &Stack[0][Index-1], &Stack[j][Index-2]) ;
    	else {
    	  for(j=0 ; j<Nbr_Dof ; j++)
    	    ((CAST3V)WholeQuantity_P->Case.Operator.Function)
    	      (&Stack[0][Index-2], &Stack[j][Index-1], &Stack[j][Index-2]) ;
    	  Multi[Index-2] = 1 ;
    	}
          }
          else if (Index-1 == DofIndex) {
    	if(Multi[Index-2])
    	  for (j = 0 ; j < Nbr_Dof ; j++)
    	    ((CAST3V)WholeQuantity_P->Case.Operator.Function)
    	      (&Stack[j][Index-2], &DofValue[j], &DofValue[j]) ;
    	else
    	  for (j = 0 ; j < Nbr_Dof ; j++)
    	    ((CAST3V)WholeQuantity_P->Case.Operator.Function)
    	      (&Stack[0][Index-2], &DofValue[j], &DofValue[j]) ;
    	DofIndex-- ;
          }
          else { /* Index-2 == DofIndex */
    	if(Multi[Index-1])
    	  for (j = 0 ; j < Nbr_Dof ; j++)
    	    ((CAST3V)WholeQuantity_P->Case.Operator.Function)
    	      (&DofValue[j], &Stack[j][Index-1], &DofValue[j]) ;
    	else
    	  for (j = 0 ; j < Nbr_Dof ; j++)
    	    ((CAST3V)WholeQuantity_P->Case.Operator.Function)
    	      (&DofValue[j], &Stack[0][Index-1], &DofValue[j]) ;
          }
          Index-- ;
          break ;
    
        case WQ_UNARYOPERATOR : /* + - ! */
          if (Index-1 == DofIndex)
    	for (j = 0 ; j < Nbr_Dof ; j++)
    	  ((CAST1V)WholeQuantity_P->Case.Operator.Function)(&DofValue[j]) ;
          else if(Multi[Index-1])
    	for(j=0 ; j<Nbr_Dof ; j++)
    	  ((CAST1V)WholeQuantity_P->Case.Operator.Function)(&Stack[j][Index-1]) ;
          else
    	((CAST1V)WholeQuantity_P->Case.Operator.Function)(&Stack[0][Index-1]) ;
          break ;
    
          /* WARNING: all the rest assumes 0 multi status */
    
        case WQ_TEST :
          Flag_True = (Stack[0][Index-1].Val[0] != 0.) ;
          for (j=0; j<NbrArguments; j++) {
            Cal_CopyValue(DofValue + j, &Stack[0][Index-1]) ;
            Multi[Index-1] = 0 ;
            Index++ ;
          }
          Index -= NbrArguments ;
          Cal_WholeQuantity(Element, QuantityStorage_P0,
    			(Flag_True) ? WholeQuantity_P->Case.Test.WholeQuantity_True :
    		 	              WholeQuantity_P->Case.Test.WholeQuantity_False,
    			u, v, w, -1, 0, &Stack[0][Index-1], NbrArguments, ExpressionName) ;
          break ;
    
        case WQ_EXPRESSION :
          Index -= WholeQuantity_P->Case.Expression.NbrArguments ;
          Get_ValueOfExpression
    	((struct Expression*)List_Pointer
    	 (Problem_S.Expression, WholeQuantity_P->Case.Expression.Index),
    	 QuantityStorage_P0, u, v, w, &Stack[0][Index],
    	 WholeQuantity_P->Case.Expression.NbrArguments) ;
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_BUILTINFUNCTION :
          Index -= WholeQuantity_P->Case.Function.NbrArguments ;
    
          if (Index != DofIndex)
    	((CASTF2V)WholeQuantity_P->Case.Function.Fct)
    	  (&WholeQuantity_P->Case.Function, &Stack[0][Index], &Stack[0][Index]) ;
          else /* Dof must be the only argument, only valid with linear functions */
    	for (j = 0 ; j < Nbr_Dof ; j++) {
    	  Current.NumEntity = Current.NumEntities[j]; /* temp */
    	  ((CASTF2V)WholeQuantity_P->Case.Function.Fct)
    	    (&WholeQuantity_P->Case.Function, &DofValue[j], &DofValue[j]) ;
    	}
    
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_EXTERNBUILTINFUNCTION :
          ((CASTF2V)WholeQuantity_P->Case.Function.Fct)
    	(&WholeQuantity_P->Case.Function, DofValue, &Stack[0][Index]) ;
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_CONSTANT :
          if (Current.NbrHar == 1) {
    	Stack[0][Index].Val[0] = WholeQuantity_P->Case.Constant ;
          }
          else {
    	for (k = 0 ; k < Current.NbrHar ; k += 2) {
    	  Stack[0][Index].Val[MAX_DIM* k   ] = WholeQuantity_P->Case.Constant ;
    	  Stack[0][Index].Val[MAX_DIM*(k+1)] = 0. ;
    	}
          }
          Stack[0][Index].Type = SCALAR ;
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_CURRENTVALUE :
          if (Current.NbrHar == 1) {
    	Stack[0][Index].Val[0] = *(WholeQuantity_P->Case.CurrentValue.Value) ;
          }
          else {
    	for (k = 0 ; k < Current.NbrHar ; k += 2) {
    	  Stack[0][Index].Val[MAX_DIM* k   ] = *(WholeQuantity_P->Case.CurrentValue.Value) ;
    	  Stack[0][Index].Val[MAX_DIM*(k+1)] = 0. ;
    	}
          }
          Stack[0][Index].Type = SCALAR ;
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_ARGUMENT :
          if (WholeQuantity_P->Case.Argument.Index > NbrArguments){
            Message::Error("Function %s called with too few arguments.", ExpressionName);
          }
          Cal_CopyValue(DofValue + WholeQuantity_P->Case.Argument.Index - 1,
    		    &Stack[0][Index]) ;
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_TIMEDERIVATIVE :
          if (Current.TypeTime == TIME_GEAR) {
            for (j=0; j<NbrArguments; j++) {
              Cal_CopyValue(DofValue + j, &Stack[0][Index]) ;
              Multi[Index] = 0 ;
              Index++ ;
            }
            Index -= NbrArguments ;
            Cal_WholeQuantity(Element, QuantityStorage_P0,
                              WholeQuantity_P->Case.TimeDerivative.WholeQuantity,
                              u, v, w, -1, 0, &Stack[0][Index], NbrArguments, ExpressionName);
    
            for (k = 0 ; k < Current.NbrSystem ; k++)
              (Current.DofData_P0+k)->Save_CurrentSolution =
                (Current.DofData_P0+k)->CurrentSolution;
            Save_TimeStep = Current.TimeStep ;
            Save_Time = Current.Time ;
            Save_TimeImag = Current.TimeImag ;
    
            for (int n = 0; n < Current.CorrOrder; n++) {
    
              for (k = 0 ; k < Current.NbrSystem ; k++){
                Solution_P0 = (struct Solution*)List_Pointer
                  ((Current.DofData_P0+k)->Solutions, 0);
                if(((Current.DofData_P0+k)->CurrentSolution - Solution_P0) > 0)
                  ((Current.DofData_P0+k)->CurrentSolution) -= 1 ;
                else{
                  Message::Error("Too few solutions for Dt with Gear's method");
                  break;
                }
              }
    
              Current.TimeStep = Current.DofData->CurrentSolution->TimeStep ;
              Current.Time = Current.DofData->CurrentSolution->Time ;
              Current.TimeImag = Current.DofData->CurrentSolution->TimeImag ;
    
              for (j=0; j<NbrArguments; j++) {
                Cal_CopyValue(DofValue + j, &Stack[0][Index+1]) ;
                Multi[Index+1] = 0 ;
                Index++ ;
              }
              Index -= NbrArguments ;
              Cal_WholeQuantity(Element, QuantityStorage_P0,
                                WholeQuantity_P->Case.TimeDerivative.WholeQuantity,
                                u, v, w, -1, 0, &Stack[0][Index+1], NbrArguments, ExpressionName);
              Cal_AddMultValue(&Stack[0][Index], &Stack[0][Index+1],
                               -Current.aCorrCoeff[n], &Stack[0][Index]);
    
            }
    
            Cal_MultValue(&Stack[0][Index], 1./(Current.bCorrCoeff*Current.DTime),
                          &Stack[0][Index]);
    
            for (k = 0 ; k < Current.NbrSystem ; k++)
              (Current.DofData_P0+k)->CurrentSolution =
                  (Current.DofData_P0+k)->Save_CurrentSolution;
            Current.TimeStep = Save_TimeStep ;
            Current.Time = Save_Time ;
            Current.TimeImag = Save_TimeImag ;
          }
          else if (Current.NbrHar == 1) {
            for (j=0; j<NbrArguments; j++) {
              Cal_CopyValue(DofValue + j, &Stack[0][Index]) ;
              Multi[Index] = 0 ;
              Index++ ;
            }
            Index -= NbrArguments ;
    	Cal_WholeQuantity(Element, QuantityStorage_P0,
    			  WholeQuantity_P->Case.TimeDerivative.WholeQuantity,
    			  u, v, w, -1, 0, &Stack[0][Index], NbrArguments, ExpressionName) ;
    
    	for (k = 0 ; k < Current.NbrSystem ; k++){
    	  (Current.DofData_P0+k)->Save_CurrentSolution =
    	   (Current.DofData_P0+k)->CurrentSolution;
    
    	  if(List_Nbr((Current.DofData_P0+k)->Solutions) > 1){
    	    Solution_P0 = (struct Solution*)List_Pointer
                  ((Current.DofData_P0+k)->Solutions, 0);
    	    if ((Current.DofData_P0+k)->CurrentSolution != Solution_P0)
    	      ((Current.DofData_P0+k)->CurrentSolution) -- ;
    	  }
    	  else {
    	    if (!Flag_WarningMissSolForDt) {
    	      Message::Warning("Missing solution for time derivative computation "
                                   "(Sys#%d/%d)", k+1, Current.NbrSystem);
    	      Flag_WarningMissSolForDt = 1 ;
    	    }
    	  }
    	}
    
            Save_TimeStep = Current.TimeStep ;
            Save_Time = Current.Time ;
            Save_TimeImag = Current.TimeImag ;
    
            Current.TimeStep = Current.DofData->CurrentSolution->TimeStep ;
            Current.Time = Current.DofData->CurrentSolution->Time ;
            Current.TimeImag = Current.DofData->CurrentSolution->TimeImag ;
    	for (j=0; j<NbrArguments; j++) {
              Cal_CopyValue(DofValue + j, &Stack[0][Index+1]) ;
              Multi[Index+1] = 0 ;
              Index++ ;
            }
            Index -= NbrArguments ;
    	Cal_WholeQuantity(Element, QuantityStorage_P0,
    			  WholeQuantity_P->Case.TimeDerivative.WholeQuantity,
    			  u, v, w, -1, 0, &Stack[0][Index+1], NbrArguments, ExpressionName) ;
    	Cal_SubstractValue(&Stack[0][Index], &Stack[0][Index+1], &Stack[0][Index]) ;
    	Stack[0][Index+1].Val[0] = Save_Time - Current.Time ;
    	Stack[0][Index+1].Type = SCALAR ;
    	if(Stack[0][Index+1].Val[0])
    	  Cal_DivideValue(&Stack[0][Index], &Stack[0][Index+1], &Stack[0][Index]) ;
    	else
    	  Cal_ZeroValue(&Stack[0][Index]);
    
    	for (k = 0 ; k < Current.NbrSystem ; k++)
    	  (Current.DofData_P0+k)->CurrentSolution =
    	    (Current.DofData_P0+k)->Save_CurrentSolution;
            Current.TimeStep = Save_TimeStep ;
            Current.Time = Save_Time ;
            Current.TimeImag = Save_TimeImag ;
          }
          else {
            for (j=0; j<NbrArguments; j++) {
              Cal_CopyValue(DofValue + j, &Stack[0][Index]) ;
              Multi[Index] = 0 ;
              Index++ ;
            }
            Index -= NbrArguments ;
    	Cal_WholeQuantity(Element, QuantityStorage_P0,
    			  WholeQuantity_P->Case.TimeDerivative.WholeQuantity,
    			  u, v, w, -1, 0, &Stack[0][Index], NbrArguments, ExpressionName) ;
    	for (k = 0 ; k < Current.NbrHar ; k += 2) {
    	  Stack[0][Index+1].Val[MAX_DIM* k   ] = 0. ;
    	  Stack[0][Index+1].Val[MAX_DIM*(k+1)] = Current.DofData->Val_Pulsation[k/2] ;
    	}
    	Stack[0][Index+1].Type = SCALAR ;
    	Cal_ProductValue(&Stack[0][Index], &Stack[0][Index+1], &Stack[0][Index]) ;
          }
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_ATANTERIORTIMESTEP :
          ntime = WholeQuantity_P->Case.AtAnteriorTimeStep.TimeStep ;
    
          for (k = 0 ; k < Current.NbrSystem ; k++){
    	Solution_P0 = (struct Solution*)List_Pointer((Current.DofData_P0+k)->Solutions, 0);
    	if(((Current.DofData_P0+k)->CurrentSolution - Solution_P0) >= ntime){
    	  ((Current.DofData_P0+k)->CurrentSolution) -= ntime ;
    	  if (Flag_InfoForTime_ntime != List_Nbr((Current.DofData_P0+k)->Solutions)) {
    	    Message::Info("Accessing solution from %d time steps ago", ntime);
    	    Message::Info("  -> System %d/%d: TimeStep = %d, Time = %g + i * %g",
                              k+1, Current.NbrSystem,
                              (Current.DofData_P0+k)->CurrentSolution->TimeStep,
                              (Current.DofData_P0+k)->CurrentSolution->Time,
                              (Current.DofData_P0+k)->CurrentSolution->TimeImag);
    	    Flag_InfoForTime_ntime = List_Nbr((Current.DofData_P0+k)->Solutions);
    	  }
    	}
    	else {
    	  if (!Flag_WarningMissSolForTime_ntime) {
    	    Message::Warning("Missing solution for time step -%d computation "
                                 "(System #%d/%d)", ntime, k+1, Current.NbrSystem);
    	    Flag_WarningMissSolForTime_ntime = 1 ;
    	  }
    	}
          }
    
          Save_TimeStep = Current.TimeStep ;
          Save_Time = Current.Time ;
          Save_TimeImag = Current.TimeImag ;
          Current.TimeStep = Current.DofData->CurrentSolution->TimeStep ;
          Current.Time = Current.DofData->CurrentSolution->Time ;
          Current.TimeImag = Current.DofData->CurrentSolution->TimeImag ;
    
          for (j=0; j<NbrArguments; j++) {
            Cal_CopyValue(DofValue + j, &Stack[0][Index]) ;
            Multi[Index] = 0 ;
            Index++ ;
          }
          Index -= NbrArguments ;
          Cal_WholeQuantity(Element, QuantityStorage_P0,
    			WholeQuantity_P->Case.AtAnteriorTimeStep.WholeQuantity,
    			u, v, w, -1, 0, &Stack[0][Index], NbrArguments, ExpressionName) ;
    
          Current.TimeStep = Save_TimeStep ;
          Current.Time = Save_Time ;
          Current.TimeImag = Save_TimeImag ;
    
          for (k = 0 ; k < Current.NbrSystem ; k++){
    	Solution_PN = (struct Solution*)
    	  List_Pointer((Current.DofData_P0+k)->Solutions,
    		       List_Nbr((Current.DofData_P0+k)->Solutions)-1);
    	if((Solution_PN - (Current.DofData_P0+k)->CurrentSolution) >= ntime)
    	  ((Current.DofData_P0+k)->CurrentSolution) += ntime ;
          }
    
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
    
        case WQ_MAXOVERTIME :
          if (Current.NbrHar == 1) {
            double time_init = WholeQuantity_P->Case.MaxOverTime.TimeInit;
            double time_final = WholeQuantity_P->Case.MaxOverTime.TimeFinal;
            /*
    	for (k = 0 ; k < Current.NbrSystem ; k++)
    	  (Current.DofData_P0+k)->Save_CurrentSolution =
    	   (Current.DofData_P0+k)->CurrentSolution;
            */
            Save_TimeStep = Current.TimeStep ;
            Save_Time = Current.Time ;
            Save_TimeImag = Current.TimeImag ;
    
            for (j=0; j<NbrArguments; j++) {
              Cal_CopyValue(DofValue + j, &Stack[0][Index]) ;
              Multi[Index] = 0 ;
              Index++ ;
            }
            Index -= NbrArguments ;
    
            double val_maxInTime = -1.e99;
    
            for (j=1; j<List_Nbr((Current.DofData)->Solutions); j++) {
    
             Current.DofData->CurrentSolution =
                (struct Solution*)List_Pointer((Current.DofData)->Solutions, j);
    
              //++++ Add: also for other systems!
    
              Current.TimeStep = Current.DofData->CurrentSolution->TimeStep ;
              Current.Time = Current.DofData->CurrentSolution->Time ;
              Current.TimeImag = Current.DofData->CurrentSolution->TimeImag ;
    
              //++++ test to do more accurately!
              if (Current.Time >= time_init && Current.Time <= time_final) {
                Cal_WholeQuantity(Element, QuantityStorage_P0,
                                  WholeQuantity_P->Case.MaxOverTime.WholeQuantity,
                                  u, v, w, -1, 0, &Stack[0][Index], NbrArguments, ExpressionName) ;
    
                if (Stack[0][Index].Type == SCALAR) {
                  if (Stack[0][Index].Val[0] > val_maxInTime){
                    val_maxInTime = Stack[0][Index].Val[0];
                  }
                }
                else {
                  Message::Error("MaxOverTime can only be applied on scalar values") ;
                }
              }
            }
            Stack[0][Index].Val[0] = val_maxInTime;
            /*
    	for (k = 0 ; k < Current.NbrSystem ; k++)
    	  (Current.DofData_P0+k)->CurrentSolution =
    	    (Current.DofData_P0+k)->Save_CurrentSolution;
            */
            Current.TimeStep = Save_TimeStep ;
            Current.Time = Save_Time ;
            Current.TimeImag = Save_TimeImag ;
    
            Multi[Index] = 0 ;
            Index++ ;
          }
          else {
            Message::Error("MaxOverTime can only be used in time domain") ;
            break;
          }
          break ;
    
        case WQ_FOURIERSTEINMETZ :
          if (Current.NbrHar == 1) {
            double time_init = WholeQuantity_P->Case.FourierSteinmetz.TimeInit;
            double time_final = WholeQuantity_P->Case.FourierSteinmetz.TimeFinal;
            int nbrFrequencyInFormula = WholeQuantity_P->Case.FourierSteinmetz.NbrFrequency;
            double exponent_f = WholeQuantity_P->Case.FourierSteinmetz.Exponent_f;
            double exponent_b = WholeQuantity_P->Case.FourierSteinmetz.Exponent_b;
    
            /*
    	for (k = 0 ; k < Current.NbrSystem ; k++)
    	  (Current.DofData_P0+k)->Save_CurrentSolution =
    	   (Current.DofData_P0+k)->CurrentSolution;
            */
            Save_TimeStep = Current.TimeStep ;
            Save_Time = Current.Time ;
            Save_TimeImag = Current.TimeImag ;
    
            for (j=0; j<NbrArguments; j++) {
              Cal_CopyValue(DofValue + j, &Stack[0][Index]) ;
              Multi[Index] = 0 ;
              Index++ ;
            }
            Index -= NbrArguments ;
    
            int i_Solution_init = -1, i_Solution_final = -1;
            int NbrTimeStep, Size=-1;
    
            for (j=0; j<List_Nbr((Current.DofData)->Solutions); j++) {
              Current.DofData->CurrentSolution =
                (struct Solution*)List_Pointer((Current.DofData)->Solutions, j);
              Current.Time = Current.DofData->CurrentSolution->Time ;
              if (Current.Time >= time_init && i_Solution_init < 0)
                i_Solution_init = j;
              if (Current.Time <= time_final) {
                i_Solution_final = j;
              }
              if (Current.Time > time_final) {
                break;
              }
            }
            NbrTimeStep = i_Solution_final-i_Solution_init+1;
            if (NbrTimeStep < 2)
              Message::Error("Wrong time interval in Function FourierSteinmetz (%d,%d)",
                             i_Solution_init, i_Solution_final) ;
    
            double *Times = (double *)Malloc(NbrTimeStep*sizeof(double));
            struct Value *TmpValues = (struct Value *)Malloc(NbrTimeStep*sizeof(struct Value));
    
            for (j=0; j<NbrTimeStep; j++) {
              Current.DofData->CurrentSolution =
                (struct Solution*)List_Pointer((Current.DofData)->Solutions,
                                               i_Solution_init+j);
    
              //++++ Add: also for other systems!
    
              Current.TimeStep = Current.DofData->CurrentSolution->TimeStep ;
              Current.Time = Current.DofData->CurrentSolution->Time ;
              Current.TimeImag = Current.DofData->CurrentSolution->TimeImag ;
    
              Cal_WholeQuantity(Element, QuantityStorage_P0,
                                WholeQuantity_P->Case.MaxOverTime.WholeQuantity,
                                u, v, w, -1, 0, &Stack[0][Index], NbrArguments, ExpressionName) ;
              Times[j] = Current.Time ;
              Cal_CopyValue(&Stack[0][Index], &TmpValues[j]) ;
              if (Stack[0][Index].Type == SCALAR)
                Size = 1;
              else if (Stack[0][Index].Type == VECTOR)
                Size = 3;
              else
                Message::Error("FourierSteinmetz can only be applied on scalar or vector values") ;
            }
    
            // FourierTransform
            int NbrFreq ;
            double *Frequencies;
            struct Value *FourierValues;
    
            Pos_FourierTransform(NbrTimeStep, 1, Times, TmpValues, Size,
                                 2, nbrFrequencyInFormula,
                                 &NbrFreq, &Frequencies, &FourierValues);
    
            /*
              we calculate the Sum for all frequencies of frequency_i^exponent_f *
              b_i^exponent_b
            */
    
            if (nbrFrequencyInFormula > NbrFreq-1)
              Message::Error("FourierSteinmetz: too many frequencies asked "
                             "(%d asked and only %d available)",
                             nbrFrequencyInFormula, NbrFreq-1) ;
    
            double val=0.;
            for (j=0; j<nbrFrequencyInFormula; j++) {
              if (Size==1) {
                val += pow(Frequencies[j+1], exponent_f) *
                  pow(FourierValues[j+1].Val[0], exponent_b);
              }
              else {
                val +=
                  pow(Frequencies[j+1], exponent_f) *
                  pow(sqrt(FourierValues[j+1].Val[0]*FourierValues[j+1].Val[0]
                           + FourierValues[j+1].Val[1]*FourierValues[j+1].Val[1]
                           + FourierValues[j+1].Val[2]*FourierValues[j+1].Val[2]),
                      exponent_b);
              }
            }
            Stack[0][Index].Type = SCALAR;
            Stack[0][Index].Val[0] = val;
    
            Free(Frequencies);
            Free(FourierValues);
    
            Free(Times); Free(TmpValues) ;
    
            /*
    	for (k = 0 ; k < Current.NbrSystem ; k++)
    	  (Current.DofData_P0+k)->CurrentSolution =
    	    (Current.DofData_P0+k)->Save_CurrentSolution;
            */
            Current.TimeStep = Save_TimeStep ;
            Current.Time = Save_Time ;
            Current.TimeImag = Save_TimeImag ;
    
            Multi[Index] = 0 ;
            Index++ ;
          }
          else {
            Message::Error("FourierSteinmetz can only be used in time domain") ;
            break;
          }
          break ;
    
        case WQ_MHTRANSFORM :
          if(Current.NbrHar == 1){
    	Message::Error("MHTransform can only be used in complex (multi-harmonic)"
                           " calculations") ;
            break;
          }
    
          for (j=0; j<NbrArguments; j++) {
            Cal_CopyValue(DofValue + j, &Stack[0][Index]) ;
            Multi[Index] = 0 ;
            Index++ ;
          }
    
          Index -= NbrArguments ;
          Cal_WholeQuantity(Element, QuantityStorage_P0,
    			WholeQuantity_P->Case.MHTransform.WholeQuantity,
    			u, v, w, -1, 0, &Stack[0][Index], NbrArguments, ExpressionName) ;
    
          MHTransform(Element, QuantityStorage_P0, u, v, w, &Stack[0][Index],
    		  (struct Expression *)List_Pointer(Problem_S.Expression,
    						    WholeQuantity_P->Case.MHTransform.Index),
    		  WholeQuantity_P->Case.MHTransform.NbrPoints) ;
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_CAST :
          /* This should be changed... */
          Save_NbrHar = Current.NbrHar ;
          Save_DofData = Current.DofData ;
    
          if (!WholeQuantity_P->Case.Cast.NbrHar){
    	Current.DofData =
    	  ((struct FunctionSpace *)
    	   List_Pointer(Problem_S.FunctionSpace,
    			WholeQuantity_P->Case.Cast.FunctionSpaceIndexForType))
    	  ->DofData ;
    
    	Current.NbrHar = Current.DofData->NbrHar ;
          }
          else{
    	Current.NbrHar = WholeQuantity_P->Case.Cast.NbrHar ;
          }
    
          for (j=0; j<NbrArguments; j++) {
            Cal_CopyValue(DofValue + j, &Stack[0][Index]) ;
            Multi[Index] = 0 ;
            Index++ ;
          }
          Index -= NbrArguments ;
          Cal_WholeQuantity(Element, QuantityStorage_P0,
    			WholeQuantity_P->Case.Cast.WholeQuantity,
    			u, v, w, -1, 0, &Stack[0][Index], NbrArguments, ExpressionName) ;
    
          if (Current.NbrHar < Save_NbrHar)  /* ne plus a completer ...?? */
          	Cal_SetZeroHarmonicValue(&Stack[0][Index], Save_NbrHar) ;
    
          Current.NbrHar = Save_NbrHar ;
          Current.DofData = Save_DofData ;
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_CHANGECURRENTPOSITION :
          Save_x = Current.x ; Save_y = Current.y ; Save_z = Current.z ;
    
          Current.x = Stack[0][Index-1].Val[0] ;
          Current.y = Stack[0][Index-1].Val[1] ;
          Current.z = Stack[0][Index-1].Val[2] ;
    
          for (j=0; j<NbrArguments; j++) {
            Cal_CopyValue(DofValue + j, &Stack[0][Index-1]) ;
            Multi[Index-1] = 0 ;
            Index++ ;
          }
          Index -= NbrArguments ;
          Cal_WholeQuantity(Element, QuantityStorage_P0,
    			WholeQuantity_P->Case.ChangeCurrentPosition.WholeQuantity,
    			u, v, w, -1, 0, &Stack[0][Index-1], NbrArguments, ExpressionName) ;
    
          Current.x = Save_x ; Current.y = Save_y ; Current.z = Save_z ;
          break ;
    
        case WQ_SAVEVALUE :
          Cal_CopyValue(&Stack[0][Index-1],
    		    &ValueSaved[WholeQuantity_P->Case.SaveValue.Index]) ;
          break ;
    
        case WQ_VALUESAVED :
          if(ValueSaved.count(WholeQuantity_P->Case.ValueSaved.Index))
            Cal_CopyValue(&ValueSaved[WholeQuantity_P->Case.ValueSaved.Index],
                          &Stack[0][Index]) ;
          else{
            if(TreatmentStatus != _PRE)
              Message::Warning("Empty register %d: assuming zero value",
                               WholeQuantity_P->Case.ValueSaved.Index + 1);
            Cal_ZeroValue(&Stack[0][Index]);
            Stack[0][Index].Type = SCALAR ;
          }
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_SAVENAMEDVALUE :
          Cal_CopyValue(&Stack[0][Index-1],
    		    &NamedValueSaved[WholeQuantity_P->Case.NamedValue.Name]) ;
          break ;
    
        case WQ_NAMEDVALUESAVED :
          if(NamedValueSaved.count(WholeQuantity_P->Case.NamedValue.Name))
            Cal_CopyValue(&NamedValueSaved[WholeQuantity_P->Case.NamedValue.Name],
                          &Stack[0][Index]) ;
          else{
            if(TreatmentStatus != _PRE)
              Message::Warning("Unknown current value '$%s': assuming zero value",
                               WholeQuantity_P->Case.NamedValue.Name);
            Cal_ZeroValue(&Stack[0][Index]);
            Stack[0][Index].Type = SCALAR ;
          }
          Multi[Index] = 0 ;
          Index++ ;
          break ;
    
        case WQ_SHOWVALUE :
          if (Index-1 == DofIndex) {
    	for(j=0 ; j<Nbr_Dof ; j++){
    	  fprintf(stderr, "##%d Dof %d ", WholeQuantity_P->Case.ShowValue.Index, j+1);
    	  Show_Value(&DofValue[j]);
    	}
          }
          else {
    	fprintf(stderr, "##%d ", WholeQuantity_P->Case.ShowValue.Index);
    	Show_Value(&Stack[0][Index-1]);
          }
          break ;
    
        default :
          Message::Error("Unknown type of WholeQuantity (%d)", WholeQuantity_P->Type);
          break;
        }
      }
    
      if (DofIndexInWholeQuantity < 0) Cal_CopyValue(&Stack[0][0], &DofValue[0]) ;
    }
    
    /* ------------------------------------------------------------------------ */
    /*  C a l _ S t o r e I n R e g i s t e r                                   */
    /* ------------------------------------------------------------------------ */
    
    void Cal_StoreInRegister(struct  Value  *Value, int RegisterIndex)
    {
      Cal_CopyValue(Value, &ValueSaved[RegisterIndex]) ;
    }
    
    /* ------------------------------------------------------------------------ */
    /*  C a l _ S t o r e I n V a r i a b l e                                   */
    /* ------------------------------------------------------------------------ */
    
    void Cal_StoreInVariable(struct  Value  *Value, const char *name)
    {
      Cal_CopyValue(Value, &NamedValueSaved[name]) ;
      Export_Value(Value, GetDPNumbers[name], 0, false); // don't append
    }
    
    void Cal_GetValueSaved(struct  Value  *Value, const char *name)
    {
      if(NamedValueSaved.count(name))
        Cal_CopyValue(&NamedValueSaved[name], Value) ;
      else{
        Message::Warning("Unknown current value '$%s': assuming zero value", name);
        Cal_ZeroValue(Value);
        Value->Type = SCALAR ;
      }
    }
    
    std::map<std::string, struct Value> &Get_AllValueSaved()
    {
      return NamedValueSaved;
    }