Jean Fromentin il y a 2 ans
Parent
commit
6c0ade1ed8
53 fichiers modifiés avec 2061 ajouts et 224 suppressions
  1. 2 2
      Makefile
  2. BIN
      inputs/test.input
  3. 25 16
      moc/input.cpp
  4. 25 11
      moc/input_view.cpp
  5. BIN
      obj/geometry.o
  6. BIN
      obj/initial_state.o
  7. BIN
      obj/kernel.o
  8. BIN
      obj/math/algo.o
  9. BIN
      obj/math/poly3.o
  10. BIN
      obj/math/spline.o
  11. BIN
      obj/physics.o
  12. BIN
      obj/qt/input.o
  13. BIN
      obj/qt/input_geometry_curves.o
  14. BIN
      obj/qt/input_physics.o
  15. BIN
      obj/qt/input_time.o
  16. BIN
      obj/qt/mainwindow.o
  17. BIN
      obj/qt/view_solution.o
  18. BIN
      obj/qt/view_solution_geometry.o
  19. BIN
      obj/source.o
  20. BIN
      obj/time.o
  21. 56 76
      src/geometry.cpp
  22. 14 9
      src/geometry.hpp
  23. 127 0
      src/initial_state.cpp
  24. 31 1
      src/initial_state.hpp
  25. 12 6
      src/physics.cpp
  26. 16 10
      src/physics.hpp
  27. 70 16
      src/qt/input.cpp
  28. 16 4
      src/qt/input.hpp
  29. 150 0
      src/qt/input_cloud.cpp
  30. 88 0
      src/qt/input_cloud.hpp
  31. 67 0
      src/qt/input_clouds_tab.cpp
  32. 49 0
      src/qt/input_clouds_tab.hpp
  33. 3 4
      src/qt/input_geometry.cpp
  34. 26 1
      src/qt/input_geometry.hpp
  35. 69 2
      src/qt/input_initial_state.cpp
  36. 33 2
      src/qt/input_initial_state.hpp
  37. 4 6
      src/qt/input_physics.cpp
  38. 4 0
      src/qt/input_physics.hpp
  39. 226 0
      src/qt/input_pump.cpp
  40. 108 0
      src/qt/input_pump.hpp
  41. 67 0
      src/qt/input_pump_tab.cpp
  42. 50 0
      src/qt/input_pump_tab.hpp
  43. 120 0
      src/qt/input_tank.cpp
  44. 68 0
      src/qt/input_tank.hpp
  45. 3 1
      src/qt/input_time.hpp
  46. 227 11
      src/qt/input_view.cpp
  47. 58 8
      src/qt/input_view.hpp
  48. 4 9
      src/qt/mainwindow.cpp
  49. 6 3
      src/qt/mainwindow.hpp
  50. 29 18
      src/qt/view.cpp
  51. 7 7
      src/qt/view.hpp
  52. 147 0
      src/source.cpp
  53. 54 1
      src/source.hpp

+ 2 - 2
Makefile

@@ -4,8 +4,8 @@ QT_MOC		= moc
 GPP		= g++
 FLAGS 		= -g -O3 -Isrc
 
-QT_FILES	= mainwindow input input_physics input_time input_geometry input_geometry_curves view_solution view_solution_geometry input_initial_state input_sources input_view view
-QT_MOC_FILES	= mainwindow input_physics input  view_solution input_view input_geometry
+QT_FILES	= mainwindow input input_physics input_time input_geometry input_initial_state input_view view input_tank input_pump input_pump_tab input_cloud input_clouds_tab
+QT_MOC_FILES	= mainwindow input_physics input input_view input_geometry input_initial_state input_tank input_pump_tab input_pump input_cloud input_clouds_tab
 MATH_FILES	= poly3 algo spline
 SRC_FILES	= physics time geometry kernel initial_state source
 

BIN
inputs/test.input


+ 25 - 16
moc/input.cpp

@@ -22,8 +22,8 @@ QT_BEGIN_MOC_NAMESPACE
 QT_WARNING_PUSH
 QT_WARNING_DISABLE_DEPRECATED
 struct qt_meta_stringdata_QtInput_t {
-    QByteArrayData data[10];
-    char stringdata0[84];
+    QByteArrayData data[12];
+    char stringdata0[116];
 };
 #define QT_MOC_LITERAL(idx, ofs, len) \
     Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
@@ -41,12 +41,15 @@ QT_MOC_LITERAL(5, 36, 4), // "save"
 QT_MOC_LITERAL(6, 41, 6), // "cancel"
 QT_MOC_LITERAL(7, 48, 14), // "changeTabIndex"
 QT_MOC_LITERAL(8, 63, 5), // "index"
-QT_MOC_LITERAL(9, 69, 14) // "updateGeometry"
+QT_MOC_LITERAL(9, 69, 14), // "updateGeometry"
+QT_MOC_LITERAL(10, 84, 18), // "updateInitialState"
+QT_MOC_LITERAL(11, 103, 12) // "updateSource"
 
     },
     "QtInput\0run_signal\0\0exit_signal\0run\0"
     "save\0cancel\0changeTabIndex\0index\0"
-    "updateGeometry"
+    "updateGeometry\0updateInitialState\0"
+    "updateSource"
 };
 #undef QT_MOC_LITERAL
 
@@ -56,7 +59,7 @@ static const uint qt_meta_data_QtInput[] = {
        8,       // revision
        0,       // classname
        0,    0, // classinfo
-       7,   14, // methods
+       9,   14, // methods
        0,    0, // properties
        0,    0, // enums/sets
        0,    0, // constructors
@@ -64,15 +67,17 @@ static const uint qt_meta_data_QtInput[] = {
        2,       // signalCount
 
  // signals: name, argc, parameters, tag, flags
-       1,    0,   49,    2, 0x06 /* Public */,
-       3,    0,   50,    2, 0x06 /* Public */,
+       1,    0,   59,    2, 0x06 /* Public */,
+       3,    0,   60,    2, 0x06 /* Public */,
 
  // slots: name, argc, parameters, tag, flags
-       4,    0,   51,    2, 0x08 /* Private */,
-       5,    0,   52,    2, 0x08 /* Private */,
-       6,    0,   53,    2, 0x08 /* Private */,
-       7,    1,   54,    2, 0x08 /* Private */,
-       9,    0,   57,    2, 0x08 /* Private */,
+       4,    0,   61,    2, 0x08 /* Private */,
+       5,    0,   62,    2, 0x08 /* Private */,
+       6,    0,   63,    2, 0x08 /* Private */,
+       7,    1,   64,    2, 0x08 /* Private */,
+       9,    0,   67,    2, 0x08 /* Private */,
+      10,    0,   68,    2, 0x08 /* Private */,
+      11,    0,   69,    2, 0x08 /* Private */,
 
  // signals: parameters
     QMetaType::Void,
@@ -83,6 +88,8 @@ static const uint qt_meta_data_QtInput[] = {
     QMetaType::Void,
     QMetaType::Void,
     QMetaType::Void, QMetaType::Int,    8,
+    QMetaType::Void,
+    QMetaType::Void,
     QMetaType::Void,
 
        0        // eod
@@ -101,6 +108,8 @@ void QtInput::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, voi
         case 4: _t->cancel(); break;
         case 5: _t->changeTabIndex((*reinterpret_cast< int(*)>(_a[1]))); break;
         case 6: _t->updateGeometry(); break;
+        case 7: _t->updateInitialState(); break;
+        case 8: _t->updateSource(); break;
         default: ;
         }
     } else if (_c == QMetaObject::IndexOfMethod) {
@@ -151,13 +160,13 @@ int QtInput::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
     if (_id < 0)
         return _id;
     if (_c == QMetaObject::InvokeMetaMethod) {
-        if (_id < 7)
+        if (_id < 9)
             qt_static_metacall(this, _c, _id, _a);
-        _id -= 7;
+        _id -= 9;
     } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        if (_id < 7)
+        if (_id < 9)
             *reinterpret_cast<int*>(_a[0]) = -1;
-        _id -= 7;
+        _id -= 9;
     }
     return _id;
 }

+ 25 - 11
moc/input_view.cpp

@@ -22,8 +22,8 @@ QT_BEGIN_MOC_NAMESPACE
 QT_WARNING_PUSH
 QT_WARNING_DISABLE_DEPRECATED
 struct qt_meta_stringdata_QtInputView_t {
-    QByteArrayData data[3];
-    char stringdata0[28];
+    QByteArrayData data[7];
+    char stringdata0[70];
 };
 #define QT_MOC_LITERAL(idx, ofs, len) \
     Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
@@ -34,10 +34,16 @@ static const qt_meta_stringdata_QtInputView_t qt_meta_stringdata_QtInputView = {
     {
 QT_MOC_LITERAL(0, 0, 11), // "QtInputView"
 QT_MOC_LITERAL(1, 12, 14), // "updateGeometry"
-QT_MOC_LITERAL(2, 27, 0) // ""
+QT_MOC_LITERAL(2, 27, 0), // ""
+QT_MOC_LITERAL(3, 28, 18), // "updateInitialState"
+QT_MOC_LITERAL(4, 47, 12), // "updateSource"
+QT_MOC_LITERAL(5, 60, 7), // "setTime"
+QT_MOC_LITERAL(6, 68, 1) // "v"
 
     },
-    "QtInputView\0updateGeometry\0"
+    "QtInputView\0updateGeometry\0\0"
+    "updateInitialState\0updateSource\0setTime\0"
+    "v"
 };
 #undef QT_MOC_LITERAL
 
@@ -47,7 +53,7 @@ static const uint qt_meta_data_QtInputView[] = {
        8,       // revision
        0,       // classname
        0,    0, // classinfo
-       1,   14, // methods
+       4,   14, // methods
        0,    0, // properties
        0,    0, // enums/sets
        0,    0, // constructors
@@ -55,10 +61,16 @@ static const uint qt_meta_data_QtInputView[] = {
        0,       // signalCount
 
  // slots: name, argc, parameters, tag, flags
-       1,    0,   19,    2, 0x0a /* Public */,
+       1,    0,   34,    2, 0x0a /* Public */,
+       3,    0,   35,    2, 0x0a /* Public */,
+       4,    0,   36,    2, 0x0a /* Public */,
+       5,    1,   37,    2, 0x0a /* Public */,
 
  // slots: parameters
     QMetaType::Void,
+    QMetaType::Void,
+    QMetaType::Void,
+    QMetaType::Void, QMetaType::Int,    6,
 
        0        // eod
 };
@@ -70,10 +82,12 @@ void QtInputView::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
         (void)_t;
         switch (_id) {
         case 0: _t->updateGeometry(); break;
+        case 1: _t->updateInitialState(); break;
+        case 2: _t->updateSource(); break;
+        case 3: _t->setTime((*reinterpret_cast< int(*)>(_a[1]))); break;
         default: ;
         }
     }
-    (void)_a;
 }
 
 QT_INIT_METAOBJECT const QMetaObject QtInputView::staticMetaObject = { {
@@ -105,13 +119,13 @@ int QtInputView::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
     if (_id < 0)
         return _id;
     if (_c == QMetaObject::InvokeMetaMethod) {
-        if (_id < 1)
+        if (_id < 4)
             qt_static_metacall(this, _c, _id, _a);
-        _id -= 1;
+        _id -= 4;
     } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        if (_id < 1)
+        if (_id < 4)
             *reinterpret_cast<int*>(_a[0]) = -1;
-        _id -= 1;
+        _id -= 4;
     }
     return _id;
 }

BIN
obj/geometry.o


BIN
obj/initial_state.o


BIN
obj/kernel.o


BIN
obj/math/algo.o


BIN
obj/math/poly3.o


BIN
obj/math/spline.o


BIN
obj/physics.o


BIN
obj/qt/input.o


BIN
obj/qt/input_geometry_curves.o


BIN
obj/qt/input_physics.o


BIN
obj/qt/input_time.o


BIN
obj/qt/mainwindow.o


BIN
obj/qt/view_solution.o


BIN
obj/qt/view_solution_geometry.o


BIN
obj/source.o


BIN
obj/time.o


+ 56 - 76
src/geometry.cpp

@@ -15,111 +15,91 @@ Geometry::Geometry(){
   Z=nullptr;
 }
 
-// Obsolete, we must add hsat
-Geometry::Geometry(double _lX,size_t _nX,size_t _nZ,Func _hsoil,Func _dhsoil,Func _hbot,Func _dhbot){
-  lX=_lX;
-  nX=_nX;
-  dX=lX/nX;
-  hsoil=new double[nX];
-  dhsoil=new double[nX];
-  hbot=new double[nX];
-  dhbot=new double[nX];
-  double hs_max=-inf,hb_min=inf;
-  double v;
-  for(size_t k=0;k<nX;++k){
-    double x=k*dX;
-    v=hsoil[k]=_hsoil(x);
-    hs_max=max(v,hs_max);
-    dhsoil[k]=_dhsoil(x);
-    v=hbot[k]=_hbot(x);
-    hb_min=min(v,hb_min);
-    dhbot[k]=_dhbot(x);
-  }
-  double dZ_avg=(hs_max-hb_min)/_nZ;
-  initZ(dZ_avg);
-}
-
-
-/*Geometry::Geometry(double _lX,size_t _nX,double depth,size_t _nZ,Spline& Ssoil,Spline& Sbot){
-  lX=_lX;
-  nX=_nX;
-  dX=lX/nX;
-  hsoil=new double[nX];
-  dhsoil=new double[nX];
-  hbot=new double[nX];
-  dhbot=new double[nX];
-  double hs_max=-inf,hb_min=inf;
-  double v;
-  for(size_t k=0;k<nX;++k){
-    double x=k*dX/lX;
-    v=hsoil[k]=1-Ssoil(x);
-    hs_max=max(v,hs_max);
-    dhsoil[k]=-Ssoil.derivate(x);
-    v=hbot[k]=1-Sbot(x);
-    hb_min=min(v,hb_min);
-    dhbot[k]=-Sbot.derivate(x);
-  }
-  double dZ_avg=(hs_max-hb_min)/_nZ;
-  initZ(dZ_avg);
-  }*/
-
 void
-Geometry::initZ(double dZ_avg){
-  nZ=new size_t[nX];
-  dZ=new double[nX];
-  Z=new double*[nX];
+Geometry::initZ(double dZ_avg,bool init){
+  if(init){
+    nZ=new size_t[nX];
+    dZ=new double[nX];
+    Z=new double*[nX];
+  }
   for(size_t k=0;k<nX;++k){
     double d=hsoil[k]-hbot[k];
     size_t n=d/dZ_avg;
     double dz=d/n;
     dZ[k]=dz;
-    nZ[k]=n;
-    Z[k]=new double[n];
-    for(size_t j=0;j<n;++j){
-      Z[k][j]=hbot[k]+j*dz;
+    nZ[k]=n+1;
+    if(init) Z[k]=new double[n+1];
+    for(size_t j=0;j<n+1;++j){
+      Z[k][j]=factor*(hbot[k]+j*dz);
     }
   }
 }
 
 void
 Geometry::initDefault(){
-  lX=20;
+  lX=10;
   nX=100;
+  nX_max=nmax_Qt;
   dX=lX/(nX-1);
-  hsoil=new double[nX];
-  dhsoil=new double[nX];
-  hbot=new double[nX];
-  dhbot=new double[nX];
+  hsoil=new double[nmax_Qt];
+  dhsoil=new double[nmax_Qt];
+  hbot=new double[nmax_Qt];
+  dhbot=new double[nmax_Qt];
+  nZ=new size_t[nmax_Qt];
+  dZ=new double[nmax_Qt];
+  Z=new double*[nmax_Qt];
+  for(size_t i=0;i<nmax_Qt;++i){
+    Z[i]=new double[nmax_Qt];
+  }
   for(size_t i=0;i<nX;++i){
-    hsoil[i]=0.7;
-    hbot[i]=0.3;
+    hsoil[i]=0.8;
+    hbot[i]=0.2;
     dhsoil[i]=0;
     dhbot[i]=0;
   }
-  depth=0.7-0.3;
+  depth=5;
   nZ_max=100;
-  initZ(depth/nZ_max);
+  factor=5/0.6;
+  initZ(depth/nZ_max,false);
 }
 
 void
-Geometry::update(double _lX,size_t _nX,double _depth,size_t _nZ_max){
+Geometry::update(double _lX,size_t _nX,double _depth,size_t _nZ_max,Spline& Ssoil,Spline& Sbot){
   lX=_lX;
   depth=_depth;
-  if(_nX!=nX or _nZ_max!=nZ_max){
+  nX=_nX;
+  nZ_max=_nZ_max;
+  dX=lX/(nX-1);
+  double hs_max=-inf,hb_min=inf;
+  double v;
+  for(size_t k=0;k<nX;++k){
+    double x=k*dX/lX;
+    v=hsoil[k]=Ssoil(x);
+    hs_max=max(v,hs_max);
+    dhsoil[k]=Ssoil.derivate(x);
+    v=hbot[k]=Sbot(x);
+    hb_min=min(v,hb_min);
+    dhbot[k]=Sbot.derivate(x);
+  }
+  double dZ_avg=(hs_max-hb_min)/_nZ_max;
+  factor=depth/(hs_max-hb_min);
+  initZ(dZ_avg,false);
+}
+
+Geometry::~Geometry(){
+  if(hsoil!=nullptr){
     delete[] hsoil;
     delete[] dhsoil;
     delete[] hbot;
     delete[] dhbot;
-    delete[] nZ;
     delete[] dZ;
-    for(size_t i=0;i<nX;++i) delete[] Z[i];
+    delete[] nZ;
+    for(size_t i=0;i<nX_max;++i){
+      delete[] Z[i];
+    }
     delete[] Z;
-    nX=_nX;
-    nZ_max=_nZ_max;
-    hsoil=new double[nX];
-    dhsoil=new double[nX];
-    hbot=new double[nX];
-    dhbot=new double[nX];
-    initZ(depth/nZ_max);
+
   }
+
+
 }

+ 14 - 9
src/geometry.hpp

@@ -10,25 +10,29 @@ using namespace std;
 
 using Func = double (*)(double);
 
-extern double inf; 
+extern double inf;
 
 //! The Geometry class contains all geometric parameters of the domain.
 class Geometry{
 public:
+
+  static constexpr size_t const nmax_Qt=400;
   //!
   Geometry();
-  
+
   //! Geometry constructor
   Geometry(double _lX,size_t _nX,size_t _nZ,Func _hsoil,Func _dhsoil,Func _hbot,Func _dhbot);
 
+  ~Geometry();
 
   void initDefault();
-  
+
   //! Horizontal length of the domain
   double lX;
 
   //! Number of horizontal steps
   size_t nX;
+  size_t nX_max;
 
   //! Horizontal step
   double dX;
@@ -37,7 +41,7 @@ public:
 
   double depth;
 
-  
+
   //! Level of the soil depending on X, e.g, hsoil[k]=level of the soil at X=k*dX.
   //! Vector of size nX.
   double* hsoil;
@@ -52,19 +56,20 @@ public:
   //! Derivative of the bottom depending on X, vector of size nX.
   double* dhbot;
 
-  
+
   //! Number of vertical step at a given X, vector of size nX.
   size_t* nZ;
-  
+
   //! Vertical step at a given X, vector of size nX.
   double* dZ;
 
   //! Vertical considered positions at a given X, vector of vectors of size nX. For each k, Z[k] is a vector of size nZ[k]
   double** Z;
 
-  
-  void initZ(double dZ_avg);
+  double factor;
+
+  void initZ(double dZ_avg,bool init=true);
 
-  void update(double _lX,size_t _nX,double _depth,size_t _nZ_max);
+  void update(double _lX,size_t _nX,double _depth,size_t _nZ_max,Spline& hbot,Spline& hsoil);
 };
 #endif

+ 127 - 0
src/initial_state.cpp

@@ -1 +1,128 @@
 #include "initial_state.hpp"
+
+Tank::Tank(){
+  saturation=0.8;
+  left=0.4;right=0.6;
+  bottom=0.6;top=0.7;
+  delta_left=0.05;
+  delta_right=0.05;
+  delta_bottom=0.05;
+  delta_top=0.05;
+}
+
+
+
+
+InitialState::InitialState(){
+  hsat=nullptr;
+  Pinit=nullptr;
+}
+
+void
+InitialState::update(Geometry& _geometry,Spline& _Ssat){
+  Ssat=&_Ssat;
+  geometry=&_geometry;
+  if(hsat!=nullptr){
+    delete[] hsat;
+    for(size_t i=0;i<geometry->nX;++i){
+      delete[] Pinit[i];
+    }
+    delete[] Pinit;
+  }
+  hsat=new double[geometry->nX];
+  Pinit=new double*[geometry->nX];
+
+  for(size_t i=0;i<geometry->nX;++i){
+    size_t nZ=geometry->nZ[i];
+    Pinit[i]=new double[nZ];
+  }
+  updatePressure();
+}
+Tank*
+InitialState::addTank(){
+  Tank* tank=new Tank;
+  tanks.push_back(tank);
+  return tank;
+  updatePressure();
+}
+
+void
+InitialState::removeTank(Tank* tank){
+  for(auto it=tanks.begin();it!=tanks.end();++it){
+    if(*it==tank){
+      delete *it;
+      tanks.erase(it);
+      return;
+    }
+  }
+  updatePressure();
+}
+
+
+InitialState::~InitialState(){
+  if(hsat!=nullptr){
+    delete[] hsat;
+    for(size_t i=0;i<geometry->nX;++i){
+      delete[] Pinit[i];
+    }
+    delete[] Pinit;
+  }
+  for(auto it=tanks.begin();it!=tanks.end();++it){
+    delete(*it);
+  }
+}
+
+void
+InitialState::updatePressure(){
+
+  for(size_t i=0;i<geometry->nX;++i){
+    double x=double(i)/(geometry->nX-1);
+    hsat[i]=(*Ssat)(x)*geometry->factor;
+    size_t nZ=geometry->nZ[i];
+    double temp=hsat[i]+Physics::model_data[0]/(Physics::g*Physics::rho); //TODO : replace Physics::model_data[0] by Psat in future
+    for(size_t j=0;j<nZ;++j){
+      double z=geometry->Z[i][j];
+      Pinit[i][j]=Physics::rho*Physics::g*(temp-z);
+      for(auto it=tanks.begin();it!=tanks.end();++it){
+        Tank* tank=*it;
+        double S=tank->saturation;
+        double l=tank->left;
+        double r=tank->right;
+        double t=tank->top;
+        double b=tank->bottom;
+        double dl=tank->delta_left;
+        double dr=tank->delta_right;
+        double dt=tank->delta_top;
+        double db=tank->delta_bottom;
+
+        double Ps=Physics::s_inv(S);
+      cout<<S<<" "<<Ps<<endl;
+      double Px,Pz;
+      double zn=z/geometry->factor;
+      if(x<=l){
+        Px=(Ps-Physics::Psec)*(x-l)/dl+Ps;
+      }
+      else if(x>=r){
+        Px=(Physics::Psec-Ps)*(x-r)/dr+Ps;
+      }
+      else{
+        Px=Ps;
+      }
+      if(zn<=b){
+        Pz=(Ps-Physics::Psec)*(zn-b)/db+Ps;
+      }
+      else if(zn>=t){
+        Pz=(Physics::Psec-Ps)*(zn-t)/dt+Ps;
+      }
+      else{
+        Pz=Ps;
+      }
+      Pinit[i][j]=max(max(min(Px,Pz),Pinit[i][j]),Physics::Psec);
+    }
+
+
+
+      //TODO : voir considrer max avec psec
+    }
+  }
+}

+ 31 - 1
src/initial_state.hpp

@@ -1,10 +1,40 @@
 #ifndef INITIAL_STATE_HPP
 #define INITIAL_STATE_HPP
 
+#include <list>
+#include "physics.hpp"
+#include "geometry.hpp"
+#include "math/spline.hpp"
+
+using namespace std;
+
+class Tank{
+public:
+  double saturation;
+  double left,right,bottom,top;
+  double delta_left,delta_right,delta_bottom,delta_top;
+  Tank();
+};
+
+
+
 class InitialState{
 private:
+
+  Spline* Ssat;
+  Geometry* geometry;
 public:
-  
+  double* hsat;
+  double** Pinit;
+  list<Tank*> tanks;
+  InitialState();
+  ~InitialState();
+  void update(Geometry& geometry,Spline& Ssat);
+  Tank* addTank();
+  void removeTank(Tank* tank);
+
+  void updatePressure();
 };
 
+
 #endif

+ 12 - 6
src/physics.cpp

@@ -9,14 +9,16 @@ namespace Physics{
   double phi=0.3;
   double k0=3e-5;
   double nivrivsat=0.01;
+  double Psec=-10000;
   double (*s)(double)=&s_BC;
   double (*ds)(double)=&ds_BC;
   void (*s_ds)(double,double&,double&)=&s_ds_BC;
+  double (*s_inv)(double)=&s_inv_BC;
   double (*kr)(double)=&kr_BC;
   double (*dkr)(double)=&dkr_BC;
   void (*kr_dkr)(double,double&,double&)=&kr_dkr_BC;
   double model_data[6]={-2000,0,3,11,0,0};
-  
+
 #define Psat model_data[0]
 #define sres model_data[1]
 #define lambda model_data[2]
@@ -40,20 +42,19 @@ namespace Physics{
       assert(false);
     };
   }
-  
-  
+
   double
   s_BC(double P){
     if(P>=Psat) return 1;
     return sres+(1-sres)*pow(Psat/P,lambda);
   }
-  
+
   double
   ds_BC(double P){
     if(P>=Psat) return 0;
     return ((sres-1)*lambda*pow(Psat/P,lambda))/P;
   }
-  
+
   void
   s_ds_BC(double P,double& v,double& dv){
     if(P>=Psat){
@@ -66,7 +67,12 @@ namespace Physics{
       dv=-(lambda*t)/P;
     }
   }
-  
+
+  double
+  s_inv_BC(double S){
+    return pow((S-sres)/(1-sres),-1/lambda)*Psat;
+  }
+
   double
   kr_BC(double P){
     if(P>=Psat) return 1;

+ 16 - 10
src/physics.hpp

@@ -8,20 +8,21 @@
 namespace Physics{
 
   enum Model{BrooksCorey};
-  
+
   //! Set physics model
   void setModel(Model model);
-  
+
   //! Gravity acceleration (m.s^-2)
   extern double g;
   //! Fluid density (g.l^(-1))
   extern double rho;
-  
+
   //! Porosity of the soil
   extern double phi;
   //! Conductivity of the saturated soil
   extern double k0;
 
+  extern double Psec;
   //! Characterise the water pressure at the bottom of the overland water
   extern double nivrivsat;
 
@@ -31,31 +32,34 @@ namespace Physics{
   extern double (*ds)(double);
   //! Set the saturation and its derivative in function of the pressure
   extern void (*s_ds)(double,double&,double&);
-  
+
+  extern double (*s_inv)(double);
+
   //! Return the relative conductivity in function of the pressure
   extern double(*kr)(double);
   //! Return the derivtive of the relative conductivity in function of the pressure
   extern double (*dkr)(double);
   //! Set the relative conductivity and its derivative in function of the pressure
   extern void (*kr_dkr)(double,double&,double&);
-  
+
 
   //---------------------
-  // Models descriptions 
+  // Models descriptions
   //---------------------
-  
+
   //! Datas used to define the model
   extern double model_data[6];
 
   //------------------------
   // Brooks and Corey model
   //------------------------
-  
+
   //model_data[0] -> psat : minimal pressure such that s(psat)=1
   //model_data[1] -> sres : residual pressure
-  //model_data[2] -> lambda 
+
+  //model_data[2] -> lambda
   //model_data[3] -> alpha
-  
+
   //! Brooks and Corey saturation map
   double s_BC(double P);
   //! Brooks and Corey derivative of the saturation map
@@ -63,6 +67,8 @@ namespace Physics{
   //! Brooks and Corey saturation and its derivative setter
   void (s_ds_BC)(double P,double& v,double& dv);
 
+  double s_inv_BC(double s);
+
   //! Brooks and Corey relative conductivity map
   double kr_BC(double P);
   //! Brooks and Corey derivative of the relative conductivity map

+ 70 - 16
src/qt/input.cpp

@@ -3,7 +3,9 @@
 QtInput::QtInput():QWidget(){
   geometry=new Geometry;
   geometry->initDefault();
-  
+  initial_state=new InitialState;
+  source=new Source;
+
   main_layout=new QVBoxLayout;
   button_layout=new QHBoxLayout;
   tab_widget=new QTabWidget;
@@ -12,23 +14,26 @@ QtInput::QtInput():QWidget(){
   button_cancel=new QPushButton("Cancel");
   button_run=new QPushButton("Run");
 
-  input_view=new QtInputView;
   input_physics=new QtInputPhysics;
   input_time=new QtInputTime;
   input_geometry=new QtInputGeometry(geometry);
-  input_initial_state=new QtInputInitialState;
-  input_sources=new QtInputSources;
+  input_initial_state=new QtInputInitialState(initial_state);
+  input_pump_tab=new QtInputPumpTab(source);
+  input_clouds_tab=new QtInputCloudsTab(source);
+  input_view=new QtInputView(input_geometry,geometry,initial_state,source);
+
+  time_bar=new QScrollBar(Qt::Horizontal);
+//  input_view->setGeometry(geometry);
+//  input_view->updateGeometry();
 
-  input_view->setGeometry(geometry);
-  input_view->updateGeometry();
-  
   //Tab
   tab_widget->addTab(input_physics,"Physics");
   tab_widget->addTab(input_time,"Time");
   tab_widget->addTab(input_geometry,"Geometry");
   tab_widget->addTab(input_initial_state,"Initial state");
-  tab_widget->addTab(input_sources,"Sources");
-  
+  tab_widget->addTab(input_pump_tab,"Pumps");
+  tab_widget->addTab(input_clouds_tab,"Clouds");
+
   //Buttons
   button_layout->addWidget(button_run);
   button_layout->addWidget(button_save);
@@ -38,6 +43,7 @@ QtInput::QtInput():QWidget(){
   //Main
   main_layout->addWidget(tab_widget);
   main_layout->addWidget(input_view,2);
+  main_layout->addWidget(time_bar);
   main_layout->addWidget(button_widget);
   setLayout(main_layout);
 
@@ -47,7 +53,10 @@ QtInput::QtInput():QWidget(){
   connect(button_run,&QPushButton::clicked,this,&QtInput::run);
   connect(input_geometry,&QtInputGeometry::geometryChanged,this,&QtInput::updateGeometry);
   connect(tab_widget,&QTabWidget::currentChanged,this,&QtInput::changeTabIndex);
-
+  connect(input_initial_state,&QtInputInitialState::initialStateChanged,this,&QtInput::updateInitialState);
+  connect(time_bar,&QScrollBar::valueChanged,input_view,&QtInputView::setTime);
+  connect(input_pump_tab,&QtInputPumpTab::sourcesChanged,this,&QtInput::updateSource);
+  connect(input_clouds_tab,&QtInputCloudsTab::sourcesChanged,this,&QtInput::updateSource);
   previous_index=-1;
 
 }
@@ -56,8 +65,6 @@ QtInput::QtInput(QString filename):QtInput(){
   load(filename.toStdString());
 }
 
-QtInput::~QtInput(){
-}
 
 bool
 QtInput::validate(){
@@ -88,7 +95,16 @@ QtInput::validate(){
     widget->setFocus();
     return false;
   }
-  return true;  
+  widget=input_initial_state->validate();
+  if(widget!=nullptr){
+    QMessageBox msgBox;
+    msgBox.setText("Incorrect initial entry");
+    msgBox.exec();
+    tab_widget->setCurrentWidget(input_initial_state);
+    widget->setFocus();
+    return false;
+  }
+  return true;
 }
 
 void
@@ -97,7 +113,7 @@ QtInput::save(){
     QString filename=QFileDialog::getSaveFileName(this,"Save input","inputs/","QT input file (*.input)");
     if(not filename.isEmpty()){
       if(filename.indexOf(".input")==-1){
-	filename.append(".input");
+        filename.append(".input");
       }
       save_input(filename.toStdString());
     }
@@ -118,6 +134,9 @@ QtInput::save_input(string filename){
   input_physics->save(file);
   input_time->save(file);
   input_geometry->save(file);
+  input_initial_state->save(file);
+  //input_pump_tab->save(file);
+  //input_clouds_tab->save(file);
   file.close();
 }
 
@@ -138,11 +157,35 @@ QtInput::load(string filename){
 
 void
 QtInput::changeTabIndex(int index){
-  if(previous_index==2){
+  if(not validate()) return;
+  switch(index){
+    case 2:
+    input_view->setStatus(QtInputView::Geom);
+    break;
+    case 3:
+    input_view->setStatus(QtInputView::Init);
+    break;
+    case 4:
+    input_view->setStatus(QtInputView::Sources);
+    break;
+    default:
+    input_view->setStatus(QtInputView::Other);
+    break;
+  }
+  switch(previous_index){
+    case 2:
     updateGeometry();
+    break;
+    case 3:
+    updateInitialState();
+    break;
+    default:
+    break;
+
   }
   previous_index=index;
-  
+  input_view->update();
+
 }
 
 void
@@ -159,3 +202,14 @@ QtInput::updateGeometry(){
     input_view->updateGeometry();
   }
 }
+
+void
+QtInput::updateInitialState(){
+  initial_state->updatePressure();
+  input_view->updateInitialState();
+}
+
+void
+QtInput::updateSource(){
+  input_view->updateSource();
+}

+ 16 - 4
src/qt/input.hpp

@@ -7,13 +7,15 @@
 #include <QPushButton>
 #include <QMessageBox>
 #include <QFileDialog>
+#include <QScrollBar>
 #include <fstream>
 
 #include "input_physics.hpp"
 #include "input_time.hpp"
 #include "input_geometry.hpp"
 #include "input_initial_state.hpp"
-#include "input_sources.hpp"
+#include "input_pump_tab.hpp"
+#include "input_clouds_tab.hpp"
 #include "input_view.hpp"
 #include "geometry.hpp"
 
@@ -24,7 +26,8 @@ class QtInput:public QWidget{
 private:
   int previous_index;
   Geometry* geometry;
-  
+  InitialState* initial_state;
+  Source* source;
   QVBoxLayout* main_layout;
   QHBoxLayout* button_layout;
   QTabWidget* tab_widget;
@@ -36,9 +39,11 @@ private:
   QtInputTime* input_time;
   QtInputGeometry* input_geometry;
   QtInputInitialState* input_initial_state;
-  QtInputSources* input_sources;
+  QtInputPumpTab* input_pump_tab;
+  QtInputCloudsTab* input_clouds_tab;
   QtInputView* input_view;
- 
+  QScrollBar* time_bar;
+
   bool validate();
   void load(string filename);
 public:
@@ -56,7 +61,14 @@ private slots:
   void cancel();
   void changeTabIndex(int index);
   void updateGeometry();
+  void updateInitialState();
+  void updateSource();
 };
 
+inline QtInput::~QtInput(){
+  delete geometry;
+  delete initial_state;
+  delete source;
+}
 
 #endif

+ 150 - 0
src/qt/input_cloud.cpp

@@ -0,0 +1,150 @@
+#include "input_cloud.hpp"
+
+QtInputCloud::QtInputCloud(Source* _source){
+  source=_source;
+  cloud=source->addCloud();
+
+
+  init_groupbox=new QGroupBox("Initial values");
+  amplitude_init_widget=new QWidget;
+  left_right_init_widget=new QWidget;
+
+  final_groupbox=new QGroupBox("Final values");
+  amplitude_final_widget=new QWidget;
+  left_right_final_widget=new QWidget;
+
+  init_final_widget=new QWidget;
+
+  main_layout=new QVBoxLayout;
+  init_final_layout=new QHBoxLayout;
+  init_layout=new QVBoxLayout;
+  final_layout=new QVBoxLayout;
+  amplitude_init_layout=new QHBoxLayout;
+  left_right_init_layout=new QHBoxLayout;
+  amplitude_final_layout=new QHBoxLayout;
+  left_right_final_layout=new QHBoxLayout;
+
+  amplitude_init_label=new QLabel("Amplitude: ");
+  amplitude_init_input=new QLineEdit(QString::number(cloud->amplitude_init));
+  amplitude_init_layout->addWidget(amplitude_init_label);
+  amplitude_init_layout->addWidget(amplitude_init_input);
+  amplitude_init_widget->setLayout(amplitude_init_layout);
+
+  left_init_label=new QLabel("Left: ");
+  delta_left_init_label=new QLabel("  Left delta: ");
+  left_init_input=new QLineEdit(QString::number(cloud->left_init));
+  delta_left_init_input=new QLineEdit(QString::number(cloud->delta_left_init));
+  right_init_label=new QLabel("  Right: ");
+  delta_right_init_label=new QLabel("  Right delta: ");
+  right_init_input=new QLineEdit(QString::number(cloud->right_init));
+  delta_right_init_input=new QLineEdit(QString::number(cloud->delta_right_init));
+
+  left_right_init_layout->addWidget(left_init_label);
+  left_right_init_layout->addWidget(left_init_input,1);
+  left_right_init_layout->addWidget(delta_left_init_label);
+  left_right_init_layout->addWidget(delta_left_init_input,1);
+  left_right_init_layout->addWidget(right_init_label);
+  left_right_init_layout->addWidget(right_init_input,1);
+  left_right_init_layout->addWidget(delta_right_init_label);
+  left_right_init_layout->addWidget(delta_right_init_input,1);
+  left_right_init_widget->setLayout(left_right_init_layout);
+
+  init_layout->addWidget(amplitude_init_widget);
+  init_layout->addWidget(left_right_init_widget);
+  init_groupbox->setLayout(init_layout);
+
+
+  amplitude_final_label=new QLabel("Amplitude: ");
+  amplitude_final_input=new QLineEdit(QString::number(cloud->amplitude_final));
+  amplitude_final_layout->addWidget(amplitude_final_label);
+  amplitude_final_layout->addWidget(amplitude_final_input);
+  amplitude_final_widget->setLayout(amplitude_final_layout);
+
+  left_final_label=new QLabel("Left: ");
+  delta_left_final_label=new QLabel("  Left delta: ");
+  left_final_input=new QLineEdit(QString::number(cloud->left_final));
+  delta_left_final_input=new QLineEdit(QString::number(cloud->delta_left_final));
+  right_final_label=new QLabel("  Right: ");
+  delta_right_final_label=new QLabel("  Right delta: ");
+  right_final_input=new QLineEdit(QString::number(cloud->right_final));
+  delta_right_final_input=new QLineEdit(QString::number(cloud->delta_right_final));
+
+  left_right_final_layout->addWidget(left_final_label);
+  left_right_final_layout->addWidget(left_final_input,1);
+  left_right_final_layout->addWidget(delta_left_final_label);
+  left_right_final_layout->addWidget(delta_left_final_input,1);
+  left_right_final_layout->addWidget(right_final_label);
+  left_right_final_layout->addWidget(right_final_input,1);
+  left_right_final_layout->addWidget(delta_right_final_label);
+  left_right_final_layout->addWidget(delta_right_final_input,1);
+  left_right_final_widget->setLayout(left_right_final_layout);
+
+  final_layout->addWidget(amplitude_final_widget);
+  final_layout->addWidget(left_right_final_widget);
+  final_groupbox->setLayout(final_layout);
+
+  init_final_layout->addWidget(init_groupbox);
+  init_final_layout->addWidget(final_groupbox);
+
+  init_final_widget->setLayout(init_final_layout);
+
+  remove_button=new QPushButton("Remove",this);
+  main_layout->addWidget(init_final_widget);
+  main_layout->addWidget(remove_button);
+
+  double_validator=new QDoubleValidator;
+  double_amplitude_validator=new QDoubleValidator;
+  double_validator->setBottom(0);
+  double_validator->setTop(1);
+
+  amplitude_init_input->setValidator(double_amplitude_validator);
+  left_init_input->setValidator(double_validator);
+  right_init_input->setValidator(double_validator);
+  delta_left_init_input->setValidator(double_validator);
+  delta_right_init_input->setValidator(double_validator);
+
+  amplitude_final_input->setValidator(double_amplitude_validator);
+  left_final_input->setValidator(double_validator);
+  right_final_input->setValidator(double_validator);
+  delta_left_final_input->setValidator(double_validator);
+  delta_right_final_input->setValidator(double_validator);
+
+  setLayout(main_layout);
+  setFrameShape(QFrame::Box);
+
+  connect(remove_button,&QPushButton::clicked,this,&QtInputCloud::emitRemove);
+}
+
+
+QWidget*
+QtInputCloud::validate(){
+  if(not amplitude_init_input->hasAcceptableInput()) return amplitude_init_input;
+  if(not left_init_input->hasAcceptableInput()) return left_init_input;
+  if(not right_init_input->hasAcceptableInput()) return right_init_input;
+  if(not delta_left_init_input->hasAcceptableInput()) return delta_left_init_input;
+  if(not delta_right_init_input->hasAcceptableInput()) return delta_right_init_input;
+  if(not amplitude_final_input->hasAcceptableInput()) return amplitude_final_input;
+  if(not left_final_input->hasAcceptableInput()) return left_final_input;
+  if(not right_final_input->hasAcceptableInput()) return right_final_input;
+  if(not delta_left_final_input->hasAcceptableInput()) return delta_left_final_input;
+  if(not delta_right_final_input->hasAcceptableInput()) return delta_right_final_input;
+
+  double li,lf,ri,rf;
+  li=left_init_input->text().toDouble();
+  lf=left_final_input->text().toDouble();
+  ri=right_init_input->text().toDouble();
+  rf=right_final_input->text().toDouble();
+  if(li>=ri) return right_init_input;
+  if(lf>=rf) return right_final_input;
+  cloud->left_init=li;
+  cloud->right_init=ri;
+  cloud->left_final=lf;
+  cloud->right_final=rf;
+  cloud->amplitude_init=amplitude_init_input->text().toDouble();
+  cloud->amplitude_final=amplitude_final_input->text().toDouble();
+  cloud->delta_left_init=delta_left_init_input->text().toDouble();
+  cloud->delta_right_init=delta_right_init_input->text().toDouble();
+  cloud->delta_left_final=delta_left_final_input->text().toDouble();
+  cloud->delta_right_final=delta_right_final_input->text().toDouble();
+  return nullptr;
+}

+ 88 - 0
src/qt/input_cloud.hpp

@@ -0,0 +1,88 @@
+#ifndef QT_INPUT_CLOUD_HPP
+#define QT_INPUT_CLOUD_HPP
+
+
+#include <QFrame>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QGroupBox>
+#include <QDoubleValidator>
+
+#include "source.hpp"
+
+class QtInputCloud:public QFrame{
+  Q_OBJECT
+private:
+  Source* source;
+  Cloud* cloud;
+  QGroupBox* init_groupbox;
+  QGroupBox* final_groupbox;
+  QWidget* init_final_widget;
+
+  QWidget* amplitude_init_widget;
+  QWidget* left_right_init_widget;
+  QWidget* amplitude_final_widget;
+  QWidget* left_right_final_widget;
+
+  QVBoxLayout* main_layout;
+  QHBoxLayout* init_final_layout;
+  QVBoxLayout* init_layout;
+  QVBoxLayout* final_layout;
+
+  QHBoxLayout* amplitude_init_layout;
+  QHBoxLayout* left_right_init_layout;
+
+  QHBoxLayout* amplitude_final_layout;
+  QHBoxLayout* left_right_final_layout;
+
+  QPushButton* remove_button;
+
+  QLabel* amplitude_init_label;
+  QLabel* left_init_label;
+  QLabel* right_init_label;
+  QLabel* delta_left_init_label;
+  QLabel* delta_right_init_label;
+  QLineEdit* amplitude_init_input;
+  QLineEdit* left_init_input;
+  QLineEdit* right_init_input;
+  QLineEdit* delta_left_init_input;
+  QLineEdit* delta_right_init_input;
+  QLabel* amplitude_final_label;
+  QLabel* left_final_label;
+  QLabel* right_final_label;
+  QLabel* delta_left_final_label;
+  QLabel* delta_right_final_label;
+  QLineEdit* amplitude_final_input;
+  QLineEdit* left_final_input;
+  QLineEdit* right_final_input;
+  QLineEdit* delta_left_final_input;
+  QLineEdit* delta_right_final_input;
+
+  QDoubleValidator* double_validator;
+  QDoubleValidator* double_amplitude_validator;
+public:
+  QtInputCloud(Source*);
+  ~QtInputCloud();
+  QWidget* validate();
+public slots:
+  void emitRemove();
+signals:
+  void remove(QtInputCloud* input_cloud);
+};
+
+inline
+QtInputCloud::~QtInputCloud(){
+  source->removeCloud(cloud);
+  delete double_validator;
+  delete double_amplitude_validator;
+}
+
+inline void
+QtInputCloud::emitRemove(){
+  emit remove(this);
+}
+
+#endif

+ 67 - 0
src/qt/input_clouds_tab.cpp

@@ -0,0 +1,67 @@
+#include "input_clouds_tab.hpp"
+
+QtInputCloudsTab::QtInputCloudsTab(Source* _source):QWidget(){
+  source=_source;
+
+  main_layout=new QVBoxLayout;
+  clouds_layout=new QVBoxLayout;
+  button_layout=new QHBoxLayout;
+  clouds_widget=new QWidget;
+  button_widget=new QWidget;
+  scroll_area=new QScrollArea;
+  add_button=new QPushButton("Add cloud");
+  refresh_button=new QPushButton("Refresh");
+
+  clouds_widget->setLayout(clouds_layout);
+  scroll_area->setWidget(clouds_widget);
+  scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+  scroll_area->setWidgetResizable(true);
+  main_layout->addWidget(scroll_area);
+
+  button_layout->addWidget(add_button);
+  button_layout->addWidget(refresh_button);
+  button_widget->setLayout(button_layout);
+  main_layout->addWidget(button_widget);
+
+  setLayout(main_layout);
+  connect(add_button,&QPushButton::clicked,this,&QtInputCloudsTab::addCloud);
+  connect(refresh_button,&QPushButton::clicked,this,&QtInputCloudsTab::updateSources);
+}
+
+void
+QtInputCloudsTab::addCloud(){
+  QtInputCloud* input_cloud=new QtInputCloud(source);
+  clouds_layout->addWidget(input_cloud);
+  connect(input_cloud,&QtInputCloud::remove,this,&QtInputCloudsTab::removeCloud);
+  emit sourcesChanged();
+}
+
+void
+QtInputCloudsTab::removeCloud(QtInputCloud* input_cloud){
+  disconnect(input_cloud,nullptr,nullptr,nullptr);
+  clouds_layout->removeWidget(input_cloud);
+  delete input_cloud;
+  emit sourcesChanged();
+}
+
+QWidget*
+QtInputCloudsTab::validate(){
+  for(size_t i=0;i<clouds_layout->count();++i){
+    QtInputCloud* cloud_input=(QtInputCloud*)clouds_layout->itemAt(i)->widget();
+    QWidget* widget=cloud_input->validate();
+    if(widget!=nullptr) return widget;
+  }
+  return nullptr;
+}
+
+void
+QtInputCloudsTab::updateSources(){
+  QWidget* widget=validate();
+  if(widget!=nullptr){
+    QMessageBox msgBox;
+    msgBox.setText("Incorrect cloud entry");
+    msgBox.exec();
+    widget->setFocus();
+  }
+  emit sourcesChanged();
+}

+ 49 - 0
src/qt/input_clouds_tab.hpp

@@ -0,0 +1,49 @@
+#ifndef QT_INPUT_CLOUDS_TAB_HPP
+#define QT_INPUT_CLOUDS_TAB_HPP
+
+#include <iostream>
+#include <fstream>
+
+#include <QWidget>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QScrollArea>
+#include <QPushButton>
+#include <QPalette>
+#include <QMessageBox>
+
+#include "qt/input_cloud.hpp"
+
+#include "source.hpp"
+
+class QtInputCloudsTab:public QWidget{
+  Q_OBJECT
+private:
+  Source* source;
+  QPushButton* add_button;
+  QPushButton* refresh_button;
+  QScrollArea* scroll_area;
+  QVBoxLayout* clouds_layout;
+  QWidget* clouds_widget;
+  QVBoxLayout* main_layout;
+  QHBoxLayout* button_layout;
+  QWidget* button_widget;
+public:
+  QtInputCloudsTab(Source* source);
+  ~QtInputCloudsTab();
+  QWidget* validate();
+  void save(fstream& file);
+  void load(fstream& file);
+public slots:
+   void addCloud();
+   void removeCloud(QtInputCloud*);
+   void updateSources();
+signals:
+   void sourcesChanged();
+};
+
+inline
+QtInputCloudsTab::~QtInputCloudsTab(){
+}
+
+#endif

+ 3 - 4
src/qt/input_geometry.cpp

@@ -2,11 +2,11 @@
 
 QtInputGeometry::QtInputGeometry(Geometry* _geometry):QWidget(){
   geometry=_geometry;
-  
+
   main_layout=new QVBoxLayout;
   lX_label=new QLabel("Horizontal lenght of the domain (l<sub>X</sub>)");
   nX_label=new QLabel("Number of horizontal steps (n<sub>X</sub>)");
-  nZ_label=new QLabel("Number of vertical steps (n<sub>Z</sub>)");
+  nZ_label=new QLabel("Maximal number of vertical steps (n<sub>Z</sub>)");
   depth_label=new QLabel("Maximal height between h<sub>soil</sub> and h<sub>bot</sub> (depth)");
   lX_input=new QLineEdit(QString::number(geometry->lX));
   nX_input=new QLineEdit(QString::number(geometry->nX));
@@ -46,6 +46,7 @@ QtInputGeometry::QtInputGeometry(Geometry* _geometry):QWidget(){
   positive_double_validator->setBottom(0);
   positive_int_validator=new QIntValidator;
   positive_int_validator->setBottom(1);
+  positive_int_validator->setTop(geometry->nmax_Qt);
   lX_input->setValidator(positive_double_validator);
   nX_input->setValidator(positive_int_validator);
   depth_input->setValidator(positive_double_validator);
@@ -90,5 +91,3 @@ QtInputGeometry::load(fstream& file){
   file.read((char*)&n,sizeof(size_t));
   nZ_input->setText(QString::number(n));
 }
-
-

+ 26 - 1
src/qt/input_geometry.hpp

@@ -36,13 +36,17 @@ private:
   QPushButton* refresh_button;
   QDoubleValidator* positive_double_validator;
   QIntValidator* positive_int_validator;
-  
+
 public:
   QtInputGeometry(Geometry* geometry);
   ~QtInputGeometry();
   QWidget* validate();
   void save(fstream& file);
   void load(fstream& file);
+  double get_lX();
+  size_t get_nX();
+  double get_depth();
+  size_t get_nZ_max();
 public slots:
   void emitGeometryChanged();
 signals:
@@ -51,6 +55,8 @@ signals:
 
 inline
 QtInputGeometry::~QtInputGeometry(){
+  delete positive_double_validator;
+  delete positive_int_validator;
 }
 
 inline void
@@ -58,4 +64,23 @@ QtInputGeometry::emitGeometryChanged(){
   emit geometryChanged();
 }
 
+inline double
+QtInputGeometry::get_lX(){
+  return lX_input->text().toDouble();
+}
+
+inline size_t
+QtInputGeometry::get_nX(){
+  return nX_input->text().toULong();
+}
+
+inline double
+QtInputGeometry::get_depth(){
+  return depth_input->text().toDouble();
+}
+
+inline size_t
+QtInputGeometry::get_nZ_max(){
+  return nZ_input->text().toULong();
+}
 #endif

+ 69 - 2
src/qt/input_initial_state.cpp

@@ -1,7 +1,74 @@
 #include "input_initial_state.hpp"
 
-QtInputInitialState::QtInputInitialState(){
+QtInputInitialState::QtInputInitialState(InitialState* _initial_state):QWidget(){
+  initial_state=_initial_state;
+
+  main_layout=new QVBoxLayout;
+  tanks_layout=new QVBoxLayout;
+  button_layout=new QHBoxLayout;
+  tanks_widget=new QWidget;
+  button_widget=new QWidget;
+  scroll_area=new QScrollArea;
+  add_button=new QPushButton("Add tank");
+  refresh_button=new QPushButton("Refresh");
+
+  tanks_widget->setLayout(tanks_layout);
+  scroll_area->setWidget(tanks_widget);
+  scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+  scroll_area->setWidgetResizable(true);
+  main_layout->addWidget(scroll_area);
+
+  button_layout->addWidget(add_button);
+  button_layout->addWidget(refresh_button);
+  button_widget->setLayout(button_layout);
+  main_layout->addWidget(button_widget);
+
+  setLayout(main_layout);
+  connect(add_button,&QPushButton::clicked,this,&QtInputInitialState::addTank);
+  connect(refresh_button,&QPushButton::clicked,this,&QtInputInitialState::updateInitialState);
+}
+
+void
+QtInputInitialState::addTank(){
+  QtInputTank* input_tank=new QtInputTank(initial_state);
+  tanks_layout->addWidget(input_tank);
+  connect(input_tank,&QtInputTank::remove,this,&QtInputInitialState::removeTank);
+  emit initialStateChanged();
+}
+
+void
+QtInputInitialState::removeTank(QtInputTank* input_tank){
+  disconnect(input_tank,nullptr,nullptr,nullptr);
+  tanks_layout->removeWidget(input_tank);
+  delete input_tank;
+  emit initialStateChanged();
+}
+
+QWidget*
+QtInputInitialState::validate(){
+  for(size_t i=0;i<tanks_layout->count();++i){
+    QtInputTank* tank_input=(QtInputTank*)tanks_layout->itemAt(i)->widget();
+    QWidget* widget=tank_input->validate();
+    if(widget!=nullptr) return widget;
+  }
+  return nullptr;
+}
+void
+QtInputInitialState::updateInitialState(){
+  QWidget* widget=validate();
+  if(widget!=nullptr){
+    QMessageBox msgBox;
+    msgBox.setText("Incorrect tank entry");
+    msgBox.exec();
+    widget->setFocus();
+  }
+  emit initialStateChanged();
 }
 
-QtInputInitialState::~QtInputInitialState(){
+void
+QtInputInitialState::save(fstream& file){
+  double d;
+  size_t n;
+  //d=lX_input->text().toDouble();
+  //file.write((char*)&d,sizeof(double));
 }

+ 33 - 2
src/qt/input_initial_state.hpp

@@ -5,14 +5,45 @@
 #include <fstream>
 
 #include <QWidget>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QScrollArea>
+#include <QPushButton>
+#include <QPalette>
+#include <QMessageBox>
+
+#include "qt/input_tank.hpp"
 
 #include "initial_state.hpp"
 
 class QtInputInitialState:public QWidget{
+  Q_OBJECT
 private:
+  InitialState* initial_state;
+  QPushButton* add_button;
+  QPushButton* refresh_button;
+  QScrollArea* scroll_area;
+  QVBoxLayout* tanks_layout;
+  QWidget* tanks_widget;
+  QVBoxLayout* main_layout;
+  QHBoxLayout* button_layout;
+  QWidget* button_widget;
 public:
-  QtInputInitialState();
+  QtInputInitialState(InitialState* initial_state);
   ~QtInputInitialState();
-  
+  QWidget* validate();
+  void save(fstream& file);
+  void load(fstream& file);
+public slots:
+   void addTank();
+   void removeTank(QtInputTank*);
+   void updateInitialState();
+signals:
+   void initialStateChanged();
 };
+
+inline
+QtInputInitialState::~QtInputInitialState(){
+}
+
 #endif

+ 4 - 6
src/qt/input_physics.cpp

@@ -34,7 +34,7 @@ QtInputPhysics::QtInputPhysics():QWidget(){
   positive_double_validator=new QDoubleValidator;
   positive_double_validator->setBottom(0);
 
- 
+
   g_input->setValidator(positive_double_validator);
   rho_input->setValidator(double_validator);
   phi_input->setValidator(double_validator);
@@ -47,12 +47,12 @@ QtInputPhysics::QtInputPhysics():QWidget(){
   phy_model_selection_box=new QComboBox;
   phy_model_selection_box->addItem("Brooks and Corey");
 
-  
+
   //Layouts
   base_layout=new QHBoxLayout;
   phy_common_layout=new QVBoxLayout;
   phy_model_layout=new QVBoxLayout;
-  
+
   //Phy commont layout
   int vspace=20;
   phy_common_layout->addWidget(g_label);
@@ -79,7 +79,7 @@ QtInputPhysics::QtInputPhysics():QWidget(){
     phy_model_layout->addWidget(model_input[i]);
   }
   phy_model_layout->addStretch();
-  
+
   //Boxes
   phy_common_box->setLayout(phy_common_layout);
   phy_model_box->setLayout(phy_model_layout);
@@ -99,9 +99,7 @@ QtInputPhysics::QtInputPhysics():QWidget(){
   loadData();
 }
 
-QtInputPhysics::~QtInputPhysics(){
 
-}
 
 void
 QtInputPhysics::modelChoosed(int index){

+ 4 - 0
src/qt/input_physics.hpp

@@ -54,4 +54,8 @@ private slots:
   void modelChoosed(int index);
 };
 
+inline QtInputPhysics::~QtInputPhysics(){
+  delete double_validator;
+  delete positive_double_validator;
+}
 #endif

+ 226 - 0
src/qt/input_pump.cpp

@@ -0,0 +1,226 @@
+#include "input_pump.hpp"
+
+QtInputPump::QtInputPump(Source* _source){
+  source=_source;
+  pump=source->addPump();
+
+
+  init_groupbox=new QGroupBox("Initial values");
+  amplitude_init_widget=new QWidget;
+  left_right_init_widget=new QWidget;
+  bottom_top_init_widget=new QWidget;
+
+  final_groupbox=new QGroupBox("Final values");
+  amplitude_final_widget=new QWidget;
+  left_right_final_widget=new QWidget;
+  bottom_top_final_widget=new QWidget;
+
+  init_final_widget=new QWidget;
+
+  main_layout=new QVBoxLayout;
+  init_final_layout=new QHBoxLayout;
+  init_layout=new QVBoxLayout;
+  final_layout=new QVBoxLayout;
+  amplitude_init_layout=new QHBoxLayout;
+  left_right_init_layout=new QHBoxLayout;
+  bottom_top_init_layout=new QHBoxLayout;
+  amplitude_final_layout=new QHBoxLayout;
+  left_right_final_layout=new QHBoxLayout;
+  bottom_top_final_layout=new QHBoxLayout;
+
+
+  amplitude_init_label=new QLabel("Amplitude: ");
+  amplitude_init_input=new QLineEdit(QString::number(pump->amplitude_init));
+  amplitude_init_layout->addWidget(amplitude_init_label);
+  amplitude_init_layout->addWidget(amplitude_init_input);
+  amplitude_init_widget->setLayout(amplitude_init_layout);
+
+  left_init_label=new QLabel("Left: ");
+  delta_left_init_label=new QLabel("  Left delta: ");
+  left_init_input=new QLineEdit(QString::number(pump->left_init));
+  delta_left_init_input=new QLineEdit(QString::number(pump->delta_left_init));
+  right_init_label=new QLabel("  Right: ");
+  delta_right_init_label=new QLabel("  Right delta: ");
+  right_init_input=new QLineEdit(QString::number(pump->right_init));
+  delta_right_init_input=new QLineEdit(QString::number(pump->delta_right_init));
+
+  left_right_init_layout->addWidget(left_init_label);
+  left_right_init_layout->addWidget(left_init_input,1);
+  left_right_init_layout->addWidget(delta_left_init_label);
+  left_right_init_layout->addWidget(delta_left_init_input,1);
+  left_right_init_layout->addWidget(right_init_label);
+  left_right_init_layout->addWidget(right_init_input,1);
+  left_right_init_layout->addWidget(delta_right_init_label);
+  left_right_init_layout->addWidget(delta_right_init_input,1);
+  left_right_init_widget->setLayout(left_right_init_layout);
+
+  bottom_init_label=new QLabel("Bottom: ");
+  delta_bottom_init_label=new QLabel("  Bottom delta: ");
+  bottom_init_input=new QLineEdit(QString::number(pump->bottom_init));
+  delta_bottom_init_input=new QLineEdit(QString::number(pump->delta_bottom_init));
+  top_init_label=new QLabel("  Top: ");
+  delta_top_init_label=new QLabel("  Top delta: ");
+  top_init_input=new QLineEdit(QString::number(pump->top_init));
+  delta_top_init_input=new QLineEdit(QString::number(pump->delta_top_init));
+
+  bottom_top_init_layout->addWidget(bottom_init_label);
+  bottom_top_init_layout->addWidget(bottom_init_input,1);
+  bottom_top_init_layout->addWidget(delta_bottom_init_label);
+  bottom_top_init_layout->addWidget(delta_bottom_init_input,1);
+  bottom_top_init_layout->addWidget(top_init_label);
+  bottom_top_init_layout->addWidget(top_init_input,1);
+  bottom_top_init_layout->addWidget(delta_top_init_label);
+  bottom_top_init_layout->addWidget(delta_top_init_input,1);
+  bottom_top_init_widget->setLayout(bottom_top_init_layout);
+
+  init_layout->addWidget(amplitude_init_widget);
+  init_layout->addWidget(left_right_init_widget);
+  init_layout->addWidget(bottom_top_init_widget);
+  init_groupbox->setLayout(init_layout);
+
+
+  amplitude_final_label=new QLabel("Amplitude: ");
+  amplitude_final_input=new QLineEdit(QString::number(pump->amplitude_final));
+  amplitude_final_layout->addWidget(amplitude_final_label);
+  amplitude_final_layout->addWidget(amplitude_final_input);
+  amplitude_final_widget->setLayout(amplitude_final_layout);
+
+  left_final_label=new QLabel("Left: ");
+  delta_left_final_label=new QLabel("  Left delta: ");
+  left_final_input=new QLineEdit(QString::number(pump->left_final));
+  delta_left_final_input=new QLineEdit(QString::number(pump->delta_left_final));
+  right_final_label=new QLabel("  Right: ");
+  delta_right_final_label=new QLabel("  Right delta: ");
+  right_final_input=new QLineEdit(QString::number(pump->right_final));
+  delta_right_final_input=new QLineEdit(QString::number(pump->delta_right_final));
+
+  left_right_final_layout->addWidget(left_final_label);
+  left_right_final_layout->addWidget(left_final_input,1);
+  left_right_final_layout->addWidget(delta_left_final_label);
+  left_right_final_layout->addWidget(delta_left_final_input,1);
+  left_right_final_layout->addWidget(right_final_label);
+  left_right_final_layout->addWidget(right_final_input,1);
+  left_right_final_layout->addWidget(delta_right_final_label);
+  left_right_final_layout->addWidget(delta_right_final_input,1);
+  left_right_final_widget->setLayout(left_right_final_layout);
+
+  bottom_final_label=new QLabel("Bottom: ");
+  delta_bottom_final_label=new QLabel("  Bottom delta: ");
+  bottom_final_input=new QLineEdit(QString::number(pump->bottom_final));
+  delta_bottom_final_input=new QLineEdit(QString::number(pump->delta_bottom_final));
+  top_final_label=new QLabel("  Top: ");
+  delta_top_final_label=new QLabel("  Top delta: ");
+  top_final_input=new QLineEdit(QString::number(pump->top_final));
+  delta_top_final_input=new QLineEdit(QString::number(pump->delta_top_final));
+
+  bottom_top_final_layout->addWidget(bottom_final_label);
+  bottom_top_final_layout->addWidget(bottom_final_input,1);
+  bottom_top_final_layout->addWidget(delta_bottom_final_label);
+  bottom_top_final_layout->addWidget(delta_bottom_final_input,1);
+  bottom_top_final_layout->addWidget(top_final_label);
+  bottom_top_final_layout->addWidget(top_final_input,1);
+  bottom_top_final_layout->addWidget(delta_top_final_label);
+  bottom_top_final_layout->addWidget(delta_top_final_input,1);
+  bottom_top_final_widget->setLayout(bottom_top_final_layout);
+
+  final_layout->addWidget(amplitude_final_widget);
+  final_layout->addWidget(left_right_final_widget);
+  final_layout->addWidget(bottom_top_final_widget);
+  final_groupbox->setLayout(final_layout);
+
+  init_final_layout->addWidget(init_groupbox);
+  init_final_layout->addWidget(final_groupbox);
+
+  init_final_widget->setLayout(init_final_layout);
+
+
+  remove_button=new QPushButton("Remove",this);
+  main_layout->addWidget(init_final_widget);
+  main_layout->addWidget(remove_button);
+
+  double_validator=new QDoubleValidator;
+  double_amplitude_validator=new QDoubleValidator;
+  double_validator->setBottom(0);
+  double_validator->setTop(1);
+
+  amplitude_init_input->setValidator(double_amplitude_validator);
+  left_init_input->setValidator(double_validator);
+  right_init_input->setValidator(double_validator);
+  bottom_init_input->setValidator(double_validator);
+  top_init_input->setValidator(double_validator);
+  delta_left_init_input->setValidator(double_validator);
+  delta_right_init_input->setValidator(double_validator);
+  delta_bottom_init_input->setValidator(double_validator);
+  delta_top_init_input->setValidator(double_validator);
+
+  amplitude_final_input->setValidator(double_amplitude_validator);
+  left_final_input->setValidator(double_validator);
+  right_final_input->setValidator(double_validator);
+  bottom_final_input->setValidator(double_validator);
+  top_final_input->setValidator(double_validator);
+  delta_left_final_input->setValidator(double_validator);
+  delta_right_final_input->setValidator(double_validator);
+  delta_bottom_final_input->setValidator(double_validator);
+  delta_top_final_input->setValidator(double_validator);
+
+  setLayout(main_layout);
+  setFrameShape(QFrame::Box);
+
+  connect(remove_button,&QPushButton::clicked,this,&QtInputPump::emitRemove);
+}
+
+
+QWidget*
+QtInputPump::validate(){
+  if(not amplitude_init_input->hasAcceptableInput()) return amplitude_init_input;
+  if(not left_init_input->hasAcceptableInput()) return left_init_input;
+  if(not right_init_input->hasAcceptableInput()) return right_init_input;
+  if(not bottom_init_input->hasAcceptableInput()) return bottom_init_input;
+  if(not top_init_input->hasAcceptableInput()) return top_init_input;
+  if(not delta_left_init_input->hasAcceptableInput()) return delta_left_init_input;
+  if(not delta_right_init_input->hasAcceptableInput()) return delta_right_init_input;
+  if(not delta_bottom_init_input->hasAcceptableInput()) return delta_bottom_init_input;
+  if(not delta_top_init_input->hasAcceptableInput()) return delta_top_init_input;
+  if(not amplitude_final_input->hasAcceptableInput()) return amplitude_final_input;
+  if(not left_final_input->hasAcceptableInput()) return left_final_input;
+  if(not right_final_input->hasAcceptableInput()) return right_final_input;
+  if(not bottom_final_input->hasAcceptableInput()) return bottom_final_input;
+  if(not top_final_input->hasAcceptableInput()) return top_final_input;
+  if(not delta_left_final_input->hasAcceptableInput()) return delta_left_final_input;
+  if(not delta_right_final_input->hasAcceptableInput()) return delta_right_final_input;
+  if(not delta_bottom_final_input->hasAcceptableInput()) return delta_bottom_final_input;
+  if(not delta_top_final_input->hasAcceptableInput()) return delta_top_final_input;
+
+  double li,lf,ri,rf,ti,tf,bi,bf;
+  li=left_init_input->text().toDouble();
+  lf=left_final_input->text().toDouble();
+  ri=right_init_input->text().toDouble();
+  rf=right_final_input->text().toDouble();
+  ti=top_init_input->text().toDouble();
+  tf=top_final_input->text().toDouble();
+  bi=bottom_init_input->text().toDouble();
+  bf=bottom_final_input->text().toDouble();
+  if(li>=ri) return right_init_input;
+  if(bi>=ti) return top_init_input;
+  if(lf>=rf) return right_final_input;
+  if(bf>=tf) return top_final_input;
+  pump->left_init=li;
+  pump->right_init=ri;
+  pump->top_init=ti;
+  pump->bottom_init=bi;
+  pump->left_final=lf;
+  pump->right_final=rf;
+  pump->top_final=tf;
+  pump->bottom_final=bf;
+  pump->amplitude_init=amplitude_init_input->text().toDouble();
+  pump->amplitude_final=amplitude_final_input->text().toDouble();
+  pump->delta_left_init=delta_left_init_input->text().toDouble();
+  pump->delta_right_init=delta_right_init_input->text().toDouble();
+  pump->delta_top_init=delta_top_init_input->text().toDouble();
+  pump->delta_bottom_init=delta_bottom_init_input->text().toDouble();
+  pump->delta_left_final=delta_left_final_input->text().toDouble();
+  pump->delta_right_final=delta_right_final_input->text().toDouble();
+  pump->delta_top_final=delta_top_final_input->text().toDouble();
+  pump->delta_bottom_final=delta_bottom_final_input->text().toDouble();
+  return nullptr;
+}

+ 108 - 0
src/qt/input_pump.hpp

@@ -0,0 +1,108 @@
+#ifndef QT_INPUT_PUMP_HPP
+#define QT_INPUT_PUMP_HPP
+
+
+#include <QFrame>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QGroupBox>
+#include <QDoubleValidator>
+
+#include "source.hpp"
+
+class QtInputPump:public QFrame{
+  Q_OBJECT
+private:
+  Source* source;
+  Pump* pump;
+  QGroupBox* init_groupbox;
+  QGroupBox* final_groupbox;
+  QWidget* init_final_widget;
+
+  QWidget* amplitude_init_widget;
+  QWidget* left_right_init_widget;
+  QWidget* bottom_top_init_widget;
+  QWidget* amplitude_final_widget;
+  QWidget* left_right_final_widget;
+  QWidget* bottom_top_final_widget;
+
+  QVBoxLayout* main_layout;
+  QHBoxLayout* init_final_layout;
+  QVBoxLayout* init_layout;
+  QVBoxLayout* final_layout;
+
+  QHBoxLayout* amplitude_init_layout;
+  QHBoxLayout* left_right_init_layout;
+  QHBoxLayout* bottom_top_init_layout;
+
+  QHBoxLayout* amplitude_final_layout;
+  QHBoxLayout* left_right_final_layout;
+  QHBoxLayout* bottom_top_final_layout;
+
+  QPushButton* remove_button;
+
+  QLabel* amplitude_init_label;
+  QLabel* left_init_label;
+  QLabel* right_init_label;
+  QLabel* top_init_label;
+  QLabel* bottom_init_label;
+  QLabel* delta_left_init_label;
+  QLabel* delta_right_init_label;
+  QLabel* delta_top_init_label;
+  QLabel* delta_bottom_init_label;
+  QLineEdit* amplitude_init_input;
+  QLineEdit* left_init_input;
+  QLineEdit* right_init_input;
+  QLineEdit* top_init_input;
+  QLineEdit* bottom_init_input;
+  QLineEdit* delta_left_init_input;
+  QLineEdit* delta_right_init_input;
+  QLineEdit* delta_top_init_input;
+  QLineEdit* delta_bottom_init_input;
+  QLabel* amplitude_final_label;
+  QLabel* left_final_label;
+  QLabel* right_final_label;
+  QLabel* top_final_label;
+  QLabel* bottom_final_label;
+  QLabel* delta_left_final_label;
+  QLabel* delta_right_final_label;
+  QLabel* delta_top_final_label;
+  QLabel* delta_bottom_final_label;
+  QLineEdit* amplitude_final_input;
+  QLineEdit* left_final_input;
+  QLineEdit* right_final_input;
+  QLineEdit* top_final_input;
+  QLineEdit* bottom_final_input;
+  QLineEdit* delta_left_final_input;
+  QLineEdit* delta_right_final_input;
+  QLineEdit* delta_top_final_input;
+  QLineEdit* delta_bottom_final_input;
+
+  QDoubleValidator* double_validator;
+  QDoubleValidator* double_amplitude_validator;
+public:
+  QtInputPump(Source*);
+  ~QtInputPump();
+  QWidget* validate();
+public slots:
+  void emitRemove();
+signals:
+  void remove(QtInputPump* input_pump);
+};
+
+inline
+QtInputPump::~QtInputPump(){
+  source->removePump(pump);
+  delete double_validator;
+  delete double_amplitude_validator;
+}
+
+inline void
+QtInputPump::emitRemove(){
+  emit remove(this);
+}
+
+#endif

+ 67 - 0
src/qt/input_pump_tab.cpp

@@ -0,0 +1,67 @@
+#include "input_pump_tab.hpp"
+
+QtInputPumpTab::QtInputPumpTab(Source* _source):QWidget(){
+  source=_source;
+
+  main_layout=new QVBoxLayout;
+  pumps_layout=new QVBoxLayout;
+  button_layout=new QHBoxLayout;
+  pumps_widget=new QWidget;
+  button_widget=new QWidget;
+  scroll_area=new QScrollArea;
+  add_button=new QPushButton("Add pump");
+  refresh_button=new QPushButton("Refresh");
+
+  pumps_widget->setLayout(pumps_layout);
+  scroll_area->setWidget(pumps_widget);
+  scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+  scroll_area->setWidgetResizable(true);
+  main_layout->addWidget(scroll_area);
+
+  button_layout->addWidget(add_button);
+  button_layout->addWidget(refresh_button);
+  button_widget->setLayout(button_layout);
+  main_layout->addWidget(button_widget);
+
+  setLayout(main_layout);
+  connect(add_button,&QPushButton::clicked,this,&QtInputPumpTab::addPump);
+  connect(refresh_button,&QPushButton::clicked,this,&QtInputPumpTab::updateSources);
+}
+
+void
+QtInputPumpTab::addPump(){
+  QtInputPump* input_pump=new QtInputPump(source);
+  pumps_layout->addWidget(input_pump);
+  connect(input_pump,&QtInputPump::remove,this,&QtInputPumpTab::removePump);
+  emit sourcesChanged();
+}
+
+void
+QtInputPumpTab::removePump(QtInputPump* input_pump){
+  disconnect(input_pump,nullptr,nullptr,nullptr);
+  pumps_layout->removeWidget(input_pump);
+  delete input_pump;
+  emit sourcesChanged();
+}
+
+QWidget*
+QtInputPumpTab::validate(){
+  for(size_t i=0;i<pumps_layout->count();++i){
+    QtInputPump* pump_input=(QtInputPump*)pumps_layout->itemAt(i)->widget();
+    QWidget* widget=pump_input->validate();
+    if(widget!=nullptr) return widget;
+  }
+  return nullptr;
+}
+
+void
+QtInputPumpTab::updateSources(){
+  QWidget* widget=validate();
+  if(widget!=nullptr){
+    QMessageBox msgBox;
+    msgBox.setText("Incorrect pump entry");
+    msgBox.exec();
+    widget->setFocus();
+  }
+  emit sourcesChanged();
+}

+ 50 - 0
src/qt/input_pump_tab.hpp

@@ -0,0 +1,50 @@
+
+#ifndef QT_INPUT_PUMP_TAB_HPP
+#define QT_INPUT_PUMP_TAB_HPP
+
+#include <iostream>
+#include <fstream>
+
+#include <QWidget>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QScrollArea>
+#include <QPushButton>
+#include <QPalette>
+#include <QMessageBox>
+
+#include "qt/input_pump.hpp"
+
+#include "source.hpp"
+
+class QtInputPumpTab:public QWidget{
+  Q_OBJECT
+private:
+  Source* source;
+  QPushButton* add_button;
+  QPushButton* refresh_button;
+  QScrollArea* scroll_area;
+  QVBoxLayout* pumps_layout;
+  QWidget* pumps_widget;
+  QVBoxLayout* main_layout;
+  QHBoxLayout* button_layout;
+  QWidget* button_widget;
+public:
+  QtInputPumpTab(Source* source);
+  ~QtInputPumpTab();
+  QWidget* validate();
+  void save(fstream& file);
+  void load(fstream& file);
+public slots:
+   void addPump();
+   void removePump(QtInputPump*);
+   void updateSources();
+signals:
+   void sourcesChanged();
+};
+
+inline
+QtInputPumpTab::~QtInputPumpTab(){
+}
+
+#endif

+ 120 - 0
src/qt/input_tank.cpp

@@ -0,0 +1,120 @@
+#include "input_tank.hpp"
+
+QtInputTank::QtInputTank(InitialState* _initial_state):QFrame(){
+  initial_state=_initial_state;
+  tank=initial_state->addTank();
+
+  saturation_widget=new QWidget;
+  left_right_widget=new QWidget;
+  bottom_top_widget=new QWidget;
+
+  main_layout=new QVBoxLayout;
+  saturation_layout=new QHBoxLayout;
+  left_right_layout=new QHBoxLayout;
+  bottom_top_layout=new QHBoxLayout;
+
+  saturation_label=new QLabel("Saturation: ");
+  saturation_input=new QLineEdit(QString::number(tank->saturation));
+  saturation_layout->addWidget(saturation_label);
+  saturation_layout->addWidget(saturation_input);
+  saturation_widget->setLayout(saturation_layout);
+
+  left_label=new QLabel("Left: ");
+  delta_left_label=new QLabel("  Left delta: ");
+  left_input=new QLineEdit(QString::number(tank->left));
+  delta_left_input=new QLineEdit(QString::number(tank->delta_left));
+  right_label=new QLabel("  Right: ");
+  delta_right_label=new QLabel("  Right delta: ");
+  right_input=new QLineEdit(QString::number(tank->right));
+  delta_right_input=new QLineEdit(QString::number(tank->delta_right));
+
+  left_right_layout->addWidget(left_label);
+  left_right_layout->addWidget(left_input,1);
+  left_right_layout->addWidget(delta_left_label);
+  left_right_layout->addWidget(delta_left_input,1);
+  left_right_layout->addWidget(right_label);
+  left_right_layout->addWidget(right_input,1);
+  left_right_layout->addWidget(delta_right_label);
+  left_right_layout->addWidget(delta_right_input,1);
+  left_right_widget->setLayout(left_right_layout);
+
+  bottom_label=new QLabel("Bottom: ");
+  delta_bottom_label=new QLabel("  Bottom delta: ");
+  bottom_input=new QLineEdit(QString::number(tank->bottom));
+  delta_bottom_input=new QLineEdit(QString::number(tank->delta_bottom));
+  top_label=new QLabel("  Top: ");
+  delta_top_label=new QLabel("  Top delta: ");
+  top_input=new QLineEdit(QString::number(tank->top));
+  delta_top_input=new QLineEdit(QString::number(tank->delta_top));
+
+  bottom_top_layout->addWidget(bottom_label);
+  bottom_top_layout->addWidget(bottom_input,1);
+  bottom_top_layout->addWidget(delta_bottom_label);
+  bottom_top_layout->addWidget(delta_bottom_input,1);
+  bottom_top_layout->addWidget(top_label);
+  bottom_top_layout->addWidget(top_input,1);
+  bottom_top_layout->addWidget(delta_top_label);
+  bottom_top_layout->addWidget(delta_top_input,1);
+  bottom_top_widget->setLayout(bottom_top_layout);
+
+  remove_button=new QPushButton("Remove",this);
+  main_layout->addWidget(saturation_widget);
+  main_layout->addWidget(left_right_widget);
+  main_layout->addWidget(bottom_top_widget);
+  main_layout->addWidget(remove_button);
+
+  double_validator=new QDoubleValidator;
+  double_validator->setBottom(0);
+  double_validator->setTop(1);
+
+  saturation_input->setValidator(double_validator);
+  left_input->setValidator(double_validator);
+  right_input->setValidator(double_validator);
+  bottom_input->setValidator(double_validator);
+  top_input->setValidator(double_validator);
+  delta_left_input->setValidator(double_validator);
+  delta_right_input->setValidator(double_validator);
+  delta_bottom_input->setValidator(double_validator);
+  delta_top_input->setValidator(double_validator);
+
+  setLayout(main_layout);
+  setFrameShape(QFrame::Box);
+
+  connect(remove_button,&QPushButton::clicked,this,&QtInputTank::emitRemove);
+}
+
+QWidget*
+QtInputTank::validate(){
+  if(not saturation_input->hasAcceptableInput()) return saturation_input;
+  if(not left_input->hasAcceptableInput()) return left_input;
+  if(not right_input->hasAcceptableInput()) return right_input;
+  if(not bottom_input->hasAcceptableInput()) return bottom_input;
+  if(not top_input->hasAcceptableInput()) return top_input;
+  if(not delta_left_input->hasAcceptableInput()) return delta_left_input;
+  if(not delta_right_input->hasAcceptableInput()) return delta_right_input;
+  if(not delta_bottom_input->hasAcceptableInput()) return delta_bottom_input;
+  if(not delta_top_input->hasAcceptableInput()) return delta_top_input;
+  double s,l,r,t,b,sl,sr,st,sb;
+  s=saturation_input->text().toDouble();
+  l=left_input->text().toDouble();
+  r=right_input->text().toDouble();
+  t=top_input->text().toDouble();
+  b=bottom_input->text().toDouble();
+  if(l>=r) return right_input;
+  if(b>=t) return top_input;
+  sl=delta_left_input->text().toDouble();
+  sr=delta_right_input->text().toDouble();
+  st=delta_top_input->text().toDouble();
+  sb=delta_bottom_input->text().toDouble();
+  tank->saturation=s;
+  tank->left=l;
+  tank->right=r;
+  tank->bottom=b;
+  tank->top=t;
+  tank->delta_left=sl;
+  tank->delta_right=sr;
+  tank->delta_bottom=sb;
+  tank->delta_top=st;
+  return nullptr;
+
+}

+ 68 - 0
src/qt/input_tank.hpp

@@ -0,0 +1,68 @@
+#ifndef QT_INPUT_TANK_HPP
+#define QT_INPUT_TANK_HPP
+
+#include <QFrame>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QDoubleValidator>
+
+#include "initial_state.hpp"
+
+class QtInputTank:public QFrame{
+  Q_OBJECT
+private:
+  InitialState* initial_state;
+  Tank* tank;
+  QWidget* saturation_widget;
+  QWidget* left_right_widget;
+  QWidget* bottom_top_widget;
+  QVBoxLayout* main_layout;
+  QHBoxLayout* saturation_layout;
+  QHBoxLayout* left_right_layout;
+  QHBoxLayout* bottom_top_layout;
+  QPushButton* remove_button;
+  QLabel* saturation_label;
+  QLabel* left_label;
+  QLabel* right_label;
+  QLabel* top_label;
+  QLabel* bottom_label;
+  QLabel* delta_left_label;
+  QLabel* delta_right_label;
+  QLabel* delta_top_label;
+  QLabel* delta_bottom_label;
+  QLineEdit* saturation_input;
+  QLineEdit* left_input;
+  QLineEdit* right_input;
+  QLineEdit* top_input;
+  QLineEdit* bottom_input;
+  QLineEdit* delta_left_input;
+  QLineEdit* delta_right_input;
+  QLineEdit* delta_top_input;
+  QLineEdit* delta_bottom_input;
+  QDoubleValidator* double_validator;
+public:
+  QtInputTank(InitialState*);
+  ~QtInputTank();
+  QWidget* validate();
+public slots:
+  void emitRemove();
+signals:
+  void remove(QtInputTank* input_tank);
+};
+
+inline
+QtInputTank::~QtInputTank(){
+  initial_state->removeTank(tank);
+  delete double_validator;
+}
+
+inline void
+QtInputTank::emitRemove(){
+  emit remove(this);
+}
+
+
+#endif

+ 3 - 1
src/qt/input_time.hpp

@@ -23,7 +23,7 @@ private:
   QVBoxLayout* main_layout;
   QDoubleValidator* positive_double_validator;
   QIntValidator* positive_int_validator;
-  
+
 public:
   QtInputTime();
   ~QtInputTime();
@@ -34,5 +34,7 @@ public:
 
 inline
 QtInputTime::~QtInputTime(){
+  delete positive_double_validator;
+  delete positive_int_validator;
 }
 #endif

+ 227 - 11
src/qt/input_view.cpp

@@ -1,6 +1,19 @@
 #include "qt/input_view.hpp"
 
-QtInputView::QtInputView():QtView(){
+QtInputView::QtInputView(QtInputGeometry* _input_geometry,Geometry* geometry,InitialState* _initial_state,Source* _source):QtView(geometry){
+  input_geometry=_input_geometry;
+  initial_state=_initial_state;
+  source=_source;
+  selected=3*np;
+  status=Other;
+  initPoints();
+  hbot.setPoints(point,np);
+  hbot.compute();
+  hsoil.setPoints(&point[np],np);
+  hsoil.compute();
+  hsat.setPoints(&point[2*np],np);
+  hsat.compute();
+  initial_state->update(*geometry,hsat);
 }
 
 void
@@ -8,32 +21,235 @@ QtInputView::initPoints(){
   for(size_t i=0;i<np;++i){
     double x=double(i)/(np-1);
     point[i].x=x;
-    point[i].y=0.3;
+    point[i].y=0.2;
     point[np+i].x=x;
-    point[np+i].y=0.5;
+    point[np+i].y=0.8;
     point[2*np+i].x=x;
-    point[2*np+i].y=0.7;
+    point[2*np+i].y=0.5;
   }
 }
 
 void
-QtInputView::drawSplinePoints(Spline& spline){  
+QtInputView::paintGL(){
+  if(status==Geom or status==Init){
+    glBegin(GL_QUADS);
+    double xs=double(pointSize)/width();
+    double ys=double(pointSize)/height();
+    glColor3f(0,0,0);
+    size_t imin=(status==Geom)?0:2*np;
+    size_t imax=(status==Geom)?2*np:3*np;
+    for(size_t i=imin;i<imax;++i){
+      Point& P=point[i];
+      double x=P.x;
+      double y=P.y;
+      glVertex3f(x-xs,y-ys,1);
+      glVertex3f(x+xs,y-ys,1);
+      glVertex3f(x+xs,y+ys,1);
+      glVertex3f(x-xs,y+ys,1);
+    }
+    glEnd();
+  }
+  for(auto it=initial_state->tanks.begin();it!=initial_state->tanks.end();++it){
+    paintTank(*it);
+  }
+  for(auto it=source->pumps.begin();it!=source->pumps.end();++it){
+    paintPump(*it);
+  }
+  for(auto it=source->clouds.begin();it!=source->clouds.end();++it){
+    paintCloud(*it);
+  }
+  glColor3f(0.6,0.6,0.6);
+  drawSpline(hbot);
+  glColor3f(0.6,0.3,0);
+  drawSpline(hsoil);
+  glColor3f(0,1,1);
+  drawSpline(hsat);
+  QtView::paintGL();
 }
 
 void
-QtInputView::paintGL(){
-  QtView::paintGL();
+QtInputView::paintTank(Tank* tank){
+  double l=tank->left;
+  double r=tank->right;
+  double b=tank->bottom;
+  double t=tank->top;
+  glLineWidth(2);
+  glColor3f(1,0,1);
+  glBegin(GL_LINE_LOOP);
+  glVertex2f(l,b);
+  glVertex2f(r,b);
+  glVertex2f(r,t);
+  glVertex2f(l,t);
+  glEnd();
+}
+
+void
+QtInputView::paintPump(Pump* pump){
+  double a=pump->get_amplitude(time);
+  if(a==0) return;
+  double l=pump->get_left(time);
+  double r=pump->get_right(time);
+  double b=pump->get_bottom(time);
+  double t=pump->get_top(time);
+  double dl=pump->get_left_delta(time);
+  double dr=pump->get_right_delta(time);
+  double db=pump->get_bottom_delta(time);
+  double dt=pump->get_top_delta(time);
+  glLineWidth(2);
+  if(a>0){
+    glColor3f(0,0.6,1);
+  }
+  else{
+    glColor3f(1,0.2,0);
+  }
+  glLineStipple(3, 0xAAAA);
+  glBegin(GL_LINE_LOOP);
+  glVertex2f(l,b);
+  glVertex2f(r,b);
+  glVertex2f(r,t);
+  glVertex2f(l,t);
+  glEnd();
+  glLineWidth(1);
+  glEnable(GL_LINE_STIPPLE);
+  glBegin(GL_LINE_LOOP);
+  glVertex2f(l-dl,b-db);
+  glVertex2f(r+dr,b-db);
+  glVertex2f(r+dr,t+dt);
+  glVertex2f(l-dl,t+dt);
+  glEnd();
+  glDisable(GL_LINE_STIPPLE);
+}
+
+void
+QtInputView::paintCloud(Cloud* cloud){
+  double a=cloud->get_amplitude(time);
+  double amax=cloud->get_amplitude_max();
+  if(a==0) return;
+  double l=cloud->get_left(time);
+  double r=cloud->get_right(time);
+  double dl=cloud->get_left_delta(time);
+  double dr=cloud->get_right_delta(time);
+  double middle=0.97;
+  double thick=0.03*a/amax;
+  double top=middle+thick;
+  double bottom=middle-thick;
+
+  glLineWidth(1);
+  glColor3f(0.5,0.5,0.5);
+  glLineWidth(1);
+  //glEnable(GL_LINE_STIPPLE);
+  glBegin(GL_POLYGON);
+  glVertex2f(l-dl,middle);
+  glVertex2f(l,top);
+  glVertex2f(r,top);
+  glVertex2f(r+dr,middle);
+  glVertex2f(r,bottom);
+  glVertex2f(l,bottom);
+  glEnd();
+  //glDisable(GL_LINE_STIPPLE);
 }
 
 void
 QtInputView::mousePressEvent(QMouseEvent* event){
-  /*double x=double(event->x())/width()*kernel->geometry.lX;
-  double y=1-(double(event->y())/height());
-  displayInfos(x,y);*/
+  if(status==Geom or status==Init){
+    size_t p=findPoint(event->x(),height()-event->y());
+    if(status==Geom){
+      selected=(p<2*np)?p:3*np;
+    }
+    else{
+      selected=(p>=2*np)?p:3*np;
+    }
+  }
 }
 
+void
+QtInputView::mouseMoveEvent(QMouseEvent* event){
+  if(selected<3*np){
+    double mx=double(event->x())/width();
+    double my=1-double(event->y())/height();
+    moveSelected(mx,my);
+  }
+}
+
+size_t
+QtInputView::findPoint(int x,int y){
+  double w=width();
+  double h=height();
+  for(size_t i=0;i<3*np;++i){
+    int px=point[i].x*w;
+    int py=point[i].y*h;
+    if(abs(x-px)<pointSize and abs(y-py)<pointSize) return i;
+  }
+  return 3*np;
+}
 
 void
 QtInputView::updateGeometry(){
-  
+  geometry->update(input_geometry->get_lX(),input_geometry->get_nX(),input_geometry->get_depth(),input_geometry->get_nZ_max(),hsoil,hbot);
+  initial_state->update(*geometry,hsat);
+  update();
+}
+
+void
+QtInputView::updateInitialState(){
+  update();
+}
+
+void
+QtInputView::updateSource(){
+  update();
+}
+void
+QtInputView::drawSpline(Spline& S){
+  double w=width();
+  glLineWidth(3);
+  glBegin(GL_LINE_STRIP);
+  for(int i=0;i<=w;i+=2){
+    double x=i/w;
+    glVertex2f(x,S(x));
+  }
+  glEnd();
+}
+
+void
+QtInputView::moveSelected(double x,double y){
+  double xp=point[selected].x;
+  double yp=point[selected].y;
+  if((selected%np)!=0 and (selected%np)!=np-1){
+    float xmin=point[selected-1].x+min_d;
+    float xmax=point[selected+1].x-min_d;
+    if(xmin<=x and x<=xmax){
+      point[selected].x=x;
+    }
+  }
+  if(0<=y and y<=1){
+    point[selected].y=y;
+  }
+  if(selected<np) hbot.compute();
+  else if(selected<2*np) hsoil.compute();
+  else hsat.compute();
+
+  if(selected<2*np){
+    double w=width();
+    bool ok=true;
+    for(int i=0;i<=w;++i){
+      double x=i/w;
+      double ybot=hbot(x);
+      double ysoil=hsoil(x);
+      if(ybot<min_d or ybot>1-min_d or ysoil<min_d or ysoil>1-min_d or ybot>ysoil-min_d){
+        point[selected].x=xp;
+        point[selected].y=yp;
+        if(selected<np) hbot.compute();
+        else hsoil.compute();
+        update();
+        return;
+      }
+    }
+  }
+  update();
+}
+
+void
+QtInputView::mouseReleaseEvent(QMouseEvent* event){
+  if(selected<3*np) updateGeometry();
 }

+ 58 - 8
src/qt/input_view.hpp

@@ -1,27 +1,77 @@
 #ifndef QT_INPUT_VIEW_HPP
 #define QT_INPUT_VIEW_HPP
 
+#include "initial_state.hpp"
+#include "input_geometry.hpp"
 #include "view.hpp"
+#include "math/point.hpp"
+#include "math/spline.hpp"
+#include "geometry.hpp"
+#include "time.hpp"
+#include "source.hpp"
 
 using namespace std;
 
-static const size_t np=10;
-
 class QtInputView:public QtView{
   Q_OBJECT
+public:
+  enum Status{Geom,Init,Sources,Other};
 private:
-  int margin;
-  int radius;
-  float min_d;
+  QtInputGeometry* input_geometry;
+  InitialState* initial_state;
+  Source* source;
+  Status status;
+  static constexpr size_t const np=10;
+  static constexpr int const pointSize=6;
+  static constexpr double const min_d=0.01;
   size_t selected;
   Point point[3*np];
-  void drawSplinePoints(Spline& spline);
+  Spline hsoil;
+  Spline hbot;
+  Spline hsat;
+  double time;
   void initPoints();
+  size_t findPoint(int x,int y);
+  void drawSpline(Spline& S);
+  void moveSelected(double x,double y);
 public:
-  QtInputView();
-  void paintGL() override;  
+  QtInputView(QtInputGeometry* input_geometry,Geometry* geometry,InitialState* initial_state,Source* source);
+  ~QtInputView();
+  void paintGL() override;
   void mousePressEvent(QMouseEvent* event);
+  void mouseMoveEvent(QMouseEvent* event);
+  void mouseReleaseEvent(QMouseEvent* event);
+  void setStatus(Status status);
+  double getP(size_t ix,size_t iz);
+  void paintTank(Tank*);
+  void paintPump(Pump*);
+  void paintCloud(Cloud*);
 public slots:
   void updateGeometry();
+  void updateInitialState();
+  void updateSource();
+  void setTime(int v);
 };
+
+
+inline void
+QtInputView::setStatus(Status _status){
+  status=_status;
+}
+
+inline double
+QtInputView::getP(size_t ix,size_t iz){
+  return initial_state->Pinit[ix][iz];
+
+}
+
+inline
+QtInputView::~QtInputView(){
+}
+
+inline void
+QtInputView::setTime(int v){
+  time=double(v)/99;
+  updateSource();
+}
 #endif

+ 4 - 9
src/qt/mainwindow.cpp

@@ -2,19 +2,19 @@
 
 QtMainWindow::QtMainWindow():QMainWindow(){
   input=nullptr;
-  view_solution=nullptr;
-  
+  //view_solution=nullptr;
+
   //Actions
   new_act=new QAction("New input",this);
   load_act=new QAction("Load input",this);
   exit_act=new QAction("Exit",this);
-  
+
   //Menu bar
   input_menu=menuBar()->addMenu("File");
   input_menu->addAction(new_act);
   input_menu->addAction(load_act);
   input_menu->addAction(exit_act);
-    
+
   connect(new_act,&QAction::triggered,this,&QtMainWindow::new_input);
   connect(load_act,&QAction::triggered,this,&QtMainWindow::load_input);
   connect(exit_act,&QAction::triggered,this,&QtMainWindow::exit);
@@ -26,9 +26,6 @@ QtMainWindow::QtMainWindow(string filename):QtMainWindow(){
 
 }
 
-QtMainWindow::~QtMainWindow(){
-}
-
 void
 QtMainWindow::new_input(){
   input=new QtInput;
@@ -77,5 +74,3 @@ void
 QtMainWindow::exit(){
   QApplication::quit();
 }
-
-

+ 6 - 3
src/qt/mainwindow.hpp

@@ -8,14 +8,12 @@
 #include <QApplication>
 
 #include "qt/input.hpp"
-#include "qt/view_solution.hpp"
 #include "kernel.hpp"
 
 class QtMainWindow:public QMainWindow{
   Q_OBJECT
 private:
   QtInput* input;
-  QtViewSolution* view_solution;
   QMenu* input_menu;
   QAction* new_act;
   QAction* load_act;
@@ -33,5 +31,10 @@ private slots:
   void exit_input();
 };
 
-
+inline
+QtMainWindow::~QtMainWindow(){
+  delete new_act;
+  delete load_act;
+  delete exit_act;
+}
 #endif

+ 29 - 18
src/qt/view.cpp

@@ -17,14 +17,13 @@ QtView::resizeGL(int w,int h){
   glViewport(0,0,w,h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
-  gluOrtho2D(0,geometry->lX,0,1);
+  gluOrtho2D(0,1,0,1);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
 }
 
 void
 QtView::paintGL(){
-  cout<<"PaintGL"<<endl;
   glBegin(GL_TRIANGLES);
   for(size_t i=0;i<geometry->nX-1;++i){
     size_t max_left=geometry->nZ[i];
@@ -33,42 +32,54 @@ QtView::paintGL(){
     size_t right=0;
     while(left<max_left-1 and right<max_right-1){
       if(geometry->Z[i][left+1]<geometry->Z[i+1][right+1]){
-	drawTriangle(i,left,i+1,right,i,left+1);
-	++left;
+        drawTriangle(i,left,i+1,right,i,left+1);
+        ++left;
       }
       else{
-	drawTriangle(i,left,i+1,right,i+1,right+1);
-	++right;
+        drawTriangle(i,left,i+1,right,i+1,right+1);
+        ++right;
       }
     }
     if(left==max_left-1){
       while(right<max_right-1){
-	drawTriangle(i,left,i+1,right,i+1,right+1);
-	++right;
+        drawTriangle(i,left,i+1,right,i+1,right+1);
+        ++right;
       }
     }
     if(right==max_right-1){
       while(left<max_left-1){
-	drawTriangle(i,left,i+1,right,i,left+1);
-	++left;
+        drawTriangle(i,left,i+1,right,i,left+1);
+        ++left;
       }
     }
   }
   glEnd();
 }
 
+void
+QtView::setColor(size_t ix,size_t iz){
+  double p=getP(ix,iz);
+  double s=Physics::s(p);
+  double r=(1-s);
+  double g=0.7*(1-s);
+  double b=0.8*s+0.4*(1-s);
+  glColor3f(r,g,b);
+}
+
 void
 QtView::drawTriangle(size_t ix1,size_t iz1,size_t ix2,size_t iz2,size_t ix3,size_t iz3){
-  double dX=geometry->dX;
+  double dX=1/double(geometry->nX-1);
   double x1=ix1*dX;
   double x2=ix2*dX;
   double x3=ix3*dX;
-  double y1=geometry->Z[ix1][iz1];
-  double y2=geometry->Z[ix2][iz2];
-  double y3=geometry->Z[ix3][iz3];
-  glColor3f(1,0,0);
-  glVertex2f(x1,y1);
-  glVertex2f(x2,y2);
-  glVertex2f(x3,y3);
+  double y1=geometry->Z[ix1][iz1]/geometry->factor;
+  double y2=geometry->Z[ix2][iz2]/geometry->factor;
+  double y3=geometry->Z[ix3][iz3]/geometry->factor;
+  setColor(ix1,iz1);
+  glVertex3f(x1,y1,0);
+  setColor(ix2,iz2);
+  glVertex3f(x2,y2,0);
+  setColor(ix3,iz3);
+  glVertex3f(x3,y3,0);
 
 }

+ 7 - 7
src/qt/view.hpp

@@ -11,6 +11,7 @@
 #include <GL/glut.h>
 
 #include "geometry.hpp"
+#include "physics.hpp"
 
 using namespace std;
 
@@ -18,22 +19,21 @@ class QtView:public QOpenGLWidget{
 protected:
   Geometry* geometry;
 public:
-  QtView();
+  QtView(Geometry* geometry);
   void setGeometry(Geometry* geometry);
   void initializeGL();
   void paintGL();
   void resizeGL(int x,int h);
   void drawTriangle(size_t ix1,size_t iz1,size_t ix2,size_t iz2,size_t ix3,size_t iz3);
+  virtual double getP(size_t ix,size_t iz)=0;
+  void setColor(size_t ix,size_t iz);
+
 };
 
 inline
-QtView::QtView():QOpenGLWidget(){
-  geometry=nullptr;
-}
-
-inline void
-QtView::setGeometry(Geometry* _geometry){
+QtView::QtView(Geometry* _geometry):QOpenGLWidget(){
   geometry=_geometry;
 }
 
+
 #endif

+ 147 - 0
src/source.cpp

@@ -1 +1,148 @@
 #include "source.hpp"
+
+Pump::Pump(){
+  amplitude_init=1.e-4;
+  left_init=0.45;
+  right_init=0.55;
+  bottom_init=0.45;
+  top_init=0.55;
+  delta_left_init=0.05;
+  delta_right_init=0.05;
+  delta_top_init=0.05;
+  delta_bottom_init=0.05;
+  amplitude_final=1.e-4;
+  left_final=0.45;
+  right_final=0.55;
+  bottom_final=0.45;
+  top_final=0.55;
+  delta_left_final=0.05;
+  delta_right_final=0.05;
+  delta_top_final=0.05;
+  delta_bottom_final=0.05;
+}
+
+
+double
+Pump::get_amplitude(double t){
+  return (1-t)*amplitude_init+t*amplitude_final;
+}
+
+double
+Pump::get_left(double t){
+  return (1-t)*left_init+t*left_final;
+}
+
+double
+Pump::get_right(double t){
+  return (1-t)*right_init+t*right_final;
+}
+
+double
+Pump::get_top(double t){
+  return (1-t)*top_init+t*top_final;
+}
+
+double
+Pump::get_bottom(double t){
+  return (1-t)*bottom_init+t*bottom_final;
+}
+
+double
+Pump::get_left_delta(double t){
+  return (1-t)*delta_left_init+t*delta_left_final;
+}
+
+double
+Pump::get_right_delta(double t){
+  return (1-t)*delta_right_init+t*delta_right_final;
+}
+
+double
+Pump::get_top_delta(double t){
+  return (1-t)*delta_top_init+t*delta_top_final;
+}
+
+double
+Pump::get_bottom_delta(double t){
+  return (1-t)*delta_bottom_init+t*delta_bottom_final;
+}
+
+Cloud::Cloud(){
+  amplitude_init=1.e-4;
+  left_init=0.45;
+  right_init=0.55;
+  delta_left_init=0.05;
+  delta_right_init=0.05;
+  amplitude_final=1.e-4;
+  left_final=0.45;
+  right_final=0.55;
+  delta_left_final=0.05;
+  delta_right_final=0.05;
+}
+
+double
+Cloud::get_amplitude(double t){
+  return (1-t)*amplitude_init+t*amplitude_final;
+}
+
+double
+Cloud::get_amplitude_max(){
+  return max(amplitude_init,amplitude_final);
+}
+
+double
+Cloud::get_left(double t){
+  return (1-t)*left_init+t*left_final;
+}
+
+double
+Cloud::get_right(double t){
+  return (1-t)*right_init+t*right_final;
+}
+
+double
+Cloud::get_left_delta(double t){
+  return (1-t)*delta_left_init+t*delta_left_final;
+}
+
+double
+Cloud::get_right_delta(double t){
+  return (1-t)*delta_right_init+t*delta_right_final;
+}
+
+
+Pump*
+Source::addPump(){
+  Pump* pump=new Pump;
+  pumps.push_back(pump);
+  return pump;
+}
+
+void
+Source::removePump(Pump* pump){
+  for(auto it=pumps.begin();it!=pumps.end();++it){
+    if(*it==pump){
+      delete *it;
+      pumps.erase(it);
+      return;
+    }
+  }
+}
+
+Cloud*
+Source::addCloud(){
+  Cloud* cloud=new Cloud;
+  clouds.push_back(cloud);
+  return cloud;
+}
+
+void
+Source::removeCloud(Cloud* cloud){
+  for(auto it=clouds.begin();it!=clouds.end();++it){
+    if(*it==cloud){
+      delete *it;
+      clouds.erase(it);
+      return;
+    }
+  }
+}

+ 54 - 1
src/source.hpp

@@ -1,8 +1,61 @@
 #ifndef SOURCE_HPP
 #define SOURCE_HPP
 
+#include <list>
 
-class Source{
+using namespace std;
+
+class Pump{
+public:
+  double amplitude_init;
+  double left_init,right_init,bottom_init,top_init;
+  double delta_left_init,delta_right_init,delta_bottom_init,delta_top_init;
+  double amplitude_final;
+  double left_final,right_final,bottom_final,top_final;
+  double delta_left_final,delta_right_final,delta_bottom_final,delta_top_final;
+  double get_amplitude(double t);
+  double get_left(double t);
+  double get_right(double t);
+  double get_top(double t);
+  double get_bottom(double t);
+  double get_left_delta(double t);
+  double get_right_delta(double t);
+  double get_top_delta(double t);
+  double get_bottom_delta(double t);
+  Pump();
+};
+
+class Cloud{
+public:
+  double amplitude_init;
+  double left_init,right_init;
+  double delta_left_init,delta_right_init;
+  double amplitude_final;
+  double left_final,right_final;
+  double delta_left_final,delta_right_final;
+  double get_amplitude(double t);
+  double get_amplitude_max();
+  double get_left(double t);
+  double get_right(double t);
+  double get_left_delta(double t);
+  double get_right_delta(double t);
+
+  Cloud();
+};
 
+class Source{
+public:
+  list<Pump*> pumps;
+  list<Cloud*> clouds;
+  Source();
+  Pump* addPump();
+  Cloud* addCloud();
+  void removePump(Pump* pump);
+  void removeCloud(Cloud* cloud);
 };
+
+inline Source::Source(){
+
+}
+
 #endif