void Image_Magnification()
{
	int i, j;
	
	for ( i = 0; i < H; ++i )
	{
		for ( j = 0; j < W; ++j )
		{
			r_image[i << 1][j << 1] = i_image[i][j].r;							
			g_image[i << 1][j << 1] = i_image[i][j].g;							
			b_image[i << 1][j << 1] = i_image[i][j].b;	
		}
	}
	
	for ( i = 0; i < M * H  - 1; ++i )
	{
		for ( j = 0; j < M * W - 1; ++j )
		{
			Interpolation( i, j, r_image );			
			Interpolation( i, j, g_image );			
			Interpolation( i, j, b_image );	
		}
	}

	for ( i = 0; i < M * H  - 1; ++i )
	{
		for ( j = 0; j < M * W - 1; ++j )
		{				
			o_image[i][j].r = r_image[i][j];			
			o_image[i][j].g = g_image[i][j];			
			o_image[i][j].b = b_image[i][j];			
		}
	}	
}		
Exemplo n.º 2
0
double PlaneInterpolaton(double x1, double y1, double z1, double x2, double y2, double z2,
double x3, double y3, double z3, double x4, double y4, double z4, double x, double y)
{
    double a1, a2;
    a1 = Interpolation(x1,x2, z1,z2, x);
    a2 = Interpolation(x4,x3, z4,z3, x);
    double y5, y6;
    y5 = Interpolation(x1,x2,y1,y2, x);
    y6 = Interpolation(x4,x3,y4,y3, x);
    return  Interpolation(y5,y6,a1,a2, y);
}
Exemplo n.º 3
0
Interpolation* Animation::add_interp()
{
	Interpolation interp = Interpolation();

	_interps.push(interp);
	_controller.push(ANIM_CTR_INTERP);

	return &_interps.back();
}
Exemplo n.º 4
0
//read pixel
sRGB8 cTexture::Pixel(double x, double y)
{
	sRGB8 black = sRGB8(0, 0, 0);
	if (x >= 0 && x < width && y >= 0 && y < height - 1.0)
	{
		return Interpolation(x, y);
	}
	else
	{
		return black;
	}
}
Exemplo n.º 5
0
void Renderer::RenderFrame(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
	SetupPass1(pipeline, pipelineContext);

#ifdef USE_CG
	shaderEngine.enableShader(currentPipe->warpShader, pipeline, pipelineContext);
#endif
	Interpolation(pipeline);
#ifdef USE_CG
	shaderEngine.disableShader();
#endif

	RenderItems(pipeline, pipelineContext);

	FinishPass1();
	Pass2(pipeline, pipelineContext);
}
Exemplo n.º 6
0
//-----------------------------------------------------------------------------------------------------------------------------------
void MessageReceived_LLgps(const ardrone_autonomy::navdata_gps& msg)
	{

	double lat = msg.lat_fused;
	double lng = msg.long_fused;
	message.c_latit= lat;
	message.c_longit=lng;
	
	//ROS_INFO("sto pubblicando il message, lat=%lf e long=%lf", message.c_latit, message.c_longit);
	if(request)
		{
	    request=false;
	   	gps_common::LLtoUTM(msg.lat_fused, msg.long_fused, northingGPS, eastingGPS, zoneGPS);
	   	Interpolation(eastingGPS, northingGPS, waypoints_UTM_vect[indexWP].easting_struct, waypoints_UTM_vect[indexWP].northing_struct);
	   	}

	pub_feedback.publish(message);  //per vederlo su mappa gui 	
	return;
 	}
void Renderer::RenderFrame(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{

#ifdef USE_FBO
    // when not 'renderToTexture', the user may use its own couple FBO/texture
    // so retrieve this external FBO if it exists, (0 means no FBO) and unbind it
    GLint externalFBO = 0;
    if (!renderTarget->renderToTexture)
    {
        glGetIntegerv(GL_FRAMEBUFFER_BINDING, &externalFBO);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    }
#endif

	SetupPass1(pipeline, pipelineContext);

#ifdef USE_CG
	shaderEngine.enableShader(currentPipe->warpShader, pipeline, pipelineContext);
#endif
	Interpolation(pipeline);
#ifdef USE_CG
	shaderEngine.disableShader();
#endif

	RenderItems(pipeline, pipelineContext);
	FinishPass1();

#ifdef USE_FBO
    // when not 'renderToTexture', the user may use its own couple FBO/texture
    // if it exists (0 means no external FBO)
    // then rebind it just before calling the final pass: Pass2
    if (!renderTarget->renderToTexture && externalFBO != 0)
        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, externalFBO);
#endif

	Pass2(pipeline, pipelineContext);
}
Exemplo n.º 8
0
    declare.time(1.0);

    TEST_CYCLE()
    {
        cv::gpu::resize(src, dst, cv::Size(), f, f, interpolation);
    }
}

INSTANTIATE_TEST_CASE_P(ImgProc, Resize, testing::Combine(
    ALL_DEVICES,
    GPU_TYPICAL_MAT_SIZES,
    testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4),
                    MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4),
                    MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
    testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR),
                    Interpolation(cv::INTER_CUBIC),   Interpolation(cv::INTER_AREA)),
    testing::Values(Scale(0.5), Scale(0.3), Scale(2.0))));

GPU_PERF_TEST(ResizeArea, cv::gpu::DeviceInfo, cv::Size, MatType, Scale)
{
    cv::gpu::DeviceInfo devInfo = GET_PARAM(0);
    cv::gpu::setDevice(devInfo.deviceID());

    cv::Size size = GET_PARAM(1);
    int type = GET_PARAM(2);
    int interpolation = cv::INTER_AREA;
    double f = GET_PARAM(3);

    cv::Mat src_host(size, type);
    fill(src_host, 0, 255);
Exemplo n.º 9
0
/// Backward computation of the price of a Zero Coupon Bond
static void CapFloor_BackwardIterationLRS1D(TreeLRS1D* Meth, ModelLRS1D* ModelParam, ZCMarketData* ZCMarket, PnlVect* OptionPriceVect1, PnlVect* OptionPriceVect2, int index_last, int index_first)
{
    double sigma, rho, kappa, lambda;

    int i, j, h;
    double delta_y, delta_t, sqrt_delta_t;
    double price_up, price_middle, price_down;
    double y_00, y_ih, r_ih, phi_ihj, phi_next;


    PnlVect* proba_from_ij;

    proba_from_ij = pnl_vect_create(3);


    ///********* Model parameters *********///
    kappa = (ModelParam->Kappa);
    sigma = (ModelParam->Sigma);
    rho = (ModelParam->Rho);
    lambda = (ModelParam->Lambda);

    delta_t = GET(Meth->t, 1) - GET(Meth->t,0);
    y_00 = r_to_y(ModelParam, -log(BondPrice(GET(Meth->t, 1), ZCMarket))/delta_t);

    for(i = index_last-1; i>=index_first; i--)
    {
        pnl_vect_resize(OptionPriceVect1, 6*i-3);  // OptionPriceVect1 := Price of the bond in the tree at time t(i)

        delta_t = GET(Meth->t, i+1) - GET(Meth->t,i);
        sqrt_delta_t = sqrt(delta_t);
        delta_y = lambda * sqrt_delta_t;

        for( h=0; h<=2*i; h++) /// h : numero de la box
        {
            y_ih = y_00 + (i-h) * delta_y;
            r_ih = y_to_r(ModelParam, y_ih);

            for(j=0;j<number_phi_in_box(i, h);j++) /// Boucle sur les  valeurs de phi à (i,h)
            {
                phi_ihj = phi_value(Meth, i, h, j);

                phi_next = phi_ihj * (1-2*kappa*delta_t) + SQR(sigma) * pow(y_to_r(ModelParam, y_ih), (2*rho)) * delta_t;

                price_up     = Interpolation(Meth, i+1, h  , OptionPriceVect2, phi_next);
                price_middle = Interpolation(Meth, i+1, h+1, OptionPriceVect2, phi_next);
                price_down   = Interpolation(Meth, i+1, h+2, OptionPriceVect2, phi_next);

                probabilities(GET(Meth->t,i), y_ih, phi_ihj, lambda, sqrt_delta_t, ModelParam, ZCMarket, proba_from_ij);

                LET(OptionPriceVect1, index_tree(i,h,j)) = exp(-r_ih*delta_t) * (GET(proba_from_ij,0) * price_up + GET(proba_from_ij,1) * price_middle + GET(proba_from_ij,2) * price_down );

            }
        }

        pnl_vect_clone(OptionPriceVect2, OptionPriceVect1); // Copy OptionPriceVect1 in OptionPriceVect2

    } // END of the loop on i (time)

    pnl_vect_free(&proba_from_ij);

}
Exemplo n.º 10
0
/************************************************
*        Complex root search subroutine         *
* --------------------------------------------- *
* This routine searches for the complex roots   *
* of an analytical function by encircling the   *
* zero and estimating where it is. The circle   *
* is subsequently tightened by a factor e, and  *
* a new estimate made.                          *
* The inputs to the subroutine are;             *
*     w      initial radius of search circle    *
*     x0,y0  the initial guess                  *
*     e      factor by which circle is reduced  *
*     n      maximum number of iterations       *
*     m      evaluation points per quadrant     *
* The routine returns Z=X+IY (X,Y), and the     *
* number of iterations, k.                      *
************************************************/
void Zcircle(double w, double e, double x0, double y0, int n, int m, 
				double &xx, double &yy, dielectric &epsilon)  {
  //Labels: 50,100,200,250,300,310,320,330,340,350,400,450
  //        460,470,500,510,520,521
  int i,j,m3,m4;
  double X[80],Y[80],U[80],V[80];
  double a,b1,b2,PI,x1,x2,xm1,xm2;
  double x3,y3,x4,y1,y2,y4,uu,vv;
  int k;
  double yy0;
  m=m*4; k=1;
  PI = 4*atan(1);
  a=2*PI/m;
e50:for (i=1; i<m+1; i++) {
    X[i]=w*cos(a*(i-1))+x0;
    Y[i]=w*sin(a*(i-1))+yy0;
	}
   std::cout<<"Determine the corresponding U[i] and V[i]"<<std::endl;
  for (i=1; i<m+1; i++) {
    xx=X[i] ; yy=Y[i];
    //Eval(xx,yy,&uu,&vv);
	std::cout<<"Calling epsilon.determinant ..."<<std::endl;
	std::cout<<k<<"  "<<i<<" A kx_re: "<<xx<<" kx_im: "<<yy<<std::endl;
	epsilon.determinant(xx,yy,&uu,&vv);
	std::cout<<"B det_re: "<<uu<<" det_im: "<<vv<<std::endl;
    U[i]=uu;
    V[i]=vv;
  }
   std::cout<<"Find the position at which uu changes sign"<<std::endl;
  // in the counterclockwise direction
  i=1; uu=U[i];
e100: Auxilliary(m,&i,&j);
  if (uu*U[i]<0) goto e200;
   std::cout<<"Guard against infinite loop B"<<std::endl;
   std::cout<<uu*U[i]<<std::endl;
  if (i==1) Set_to_zero(&xx,&yy);
  goto e100;
   std::cout<<"Transition found"<<std::endl;
e200: xm1=i;
   std::cout<<"Search for the other transition, starting"<<std::endl;
  // on the other side of the circle
  i=(int) xm1+m/2;
  if (i>m) i=i-m;
  j=i;
  uu=U[i];
   std::cout<<"Flip directions alternately"<<std::endl;
e250: Auxilliary(m,&i,&j);
  if (uu*U[i]<0) goto e300;
  if (uu*U[j]<0) goto e310;
   std::cout<<"Guard against infinite loop C"<<std::endl;
  if (i==xm1+(xm2/2)) Set_to_zero(&xx,&yy);
  if (j==xm1+(xm2/2)) Set_to_zero(&xx,&yy);
  goto e250;
   std::cout<<"Transition found"<<std::endl;
e300: m3=i;
  goto e320;
   std::cout<<"Transition found"<<std::endl;
e310: if (j==m) j=0;
  m3=j+1;
   std::cout<<"xm1 and m3 have been determined, now for xm2 and m4"<<std::endl;
  // now for the vv transitions                         
e320: i=(int) xm1+m/4;
  if (i>m) i=i-m;
  j=i; vv=V[i];
e330: Auxilliary(m,&i,&j);
  if (vv*V[i]<0) goto e340;
  if (vv*V[j]<0) goto e350;
   std::cout<<"Guard against infinite loop A"<<std::endl;
  if (i==xm1+m/4) Set_to_zero(&xx,&yy);
  if (j==xm1+m/4) Set_to_zero(&xx,&yy);
  goto e330;
   std::cout<<"xm2 has been found"<<std::endl;
e340: xm2=i;
  goto e400;
e350: if (j==m) j=0;
  xm2=j+1;
   std::cout<<"xm2 has been found, now for m4"<<std::endl;
e400: i=(int) xm2+m/2;
  if (i>m) i=i-m;
  j=i; vv=V[i];
e450: Auxilliary(m,&i,&j);
  if (uu*V[i]<0) goto e460;
  if (vv*V[j]<0) goto e470;
  // Guard against infinite loop
  if (i==xm2+m/2) Set_to_zero(&xx,&yy);
  if (j==xm2+m/2) Set_to_zero(&xx,&yy);
  goto e450;
e460: m4=i;
  goto e500;
e470: if (j==m) j=0;
  m4=j+1;
   std::cout<<"All the intersections have been determinep"<<std::endl;
  // Interpolate to find the four (x,y) coordinates
e500: i=(int) xm1;
  Interpolation(m,i,j,X,Y,U,V,&xx,&yy);
  x1=xx ; y1=yy ; i=(int) xm2;
  Interpolation(m,i,j,X,Y,U,V,&xx,&yy);
  x2=xx ; y2=yy ; i=m3;
  Interpolation(m,i,j,X,Y,U,V,&xx,&yy);
  x3=xx ; y3=yy ; i=m4;
  Interpolation(m,i,j,X,Y,U,V,&xx,&yy);
  x4=xx ; y4=yy;
   std::cout<<"Calculate the intersection of the lines"<<std::endl;
  // Guard against a divide by zero
  if (x1!=x3) goto e510;
  xx=x1; yy=(y1+y3)/2.0;
  goto e520;
e510: xm1=(y3-y1)/(x3-x1);
  if (x2!=x4) goto e520;
  xm2=1e8;
  goto e521;
e520: xm2=(y2-y4)/(x2-x4);
e521: b1=y1-xm1*x1;
  b2=y2-xm2*x2;
  xx=-(b1-b2)/(xm1-xm2);
  yy=(xm1*b2+xm2*b1)/(xm1+xm2);
   std::cout<<"is another iteration in order ?"<<std::endl;
  if (k==n) return;
  x0=xx ; yy0=yy ; k=k+1 ; w=w*e;
  goto e50;
} // Zcircle
double Viscous_Component_XY_2ND_Order(double*** velocity_x,
                                      double*** velocity_y,
				      double*** temperature, 
                                      double Reynolds,
                                      double dx, double* dy,
                                      int i, int j, int k)
{

  double derivative_y[2], dy_total=0.;

  //Calculation of the du/dy component
  for (int vi=0; vi<2; vi++)
    {
      dy_total=dy[j+vi]+dy[j+vi-1];
      derivative_y[vi] = Derivative(velocity_x[k][j+vi][i],
				    velocity_x[k][j+vi-1][i],
				    dy_total, 1);
    }


  // Calculation of the dv/dx component
  // interpolating the velocities at i\pm 1/2 (j-1,j,j+1)
  double interpolation_x[3][2];
  for(int vi=0; vi<2; vi++){
    for(int vj=0; vj<3; vj++){
  
      interpolation_x[vj][vi] = 
	Interpolation(velocity_y[k][j+vj-1][i+vi], 
		      velocity_y[k][j+vj-1][i+vi-1]); 
					
    }
  }

  //computing the derivative dv/dx at j-1,j,j+1
  double derivative_x[3];
  for(int vi=0; vi<3; vi++){
      
    derivative_x[vi]= Derivative(interpolation_x[vi][1],
				 interpolation_x[vi][0],
				 dx, 1);
  }

  //interpolation in the x direction
  double final_derivative_x[2];
  for(int vi=0, vj=1; vi<2; vi++, vj++){
    
    final_derivative_x[vi]=  Interpolation(derivative_x[vj],
					   derivative_x[vj-1]);
  }
  


  //Computing the viscosities.
  double viscosity[2];
  for (int vi=0; vi<2; vi++)
    {
      viscosity[vi]=
        Viscosity_Calculator(Interpolation(temperature[k][j+vi][i],
                                           temperature[k][j+vi-1][i]));
    }

  //Summing the X-component of the Viscous Term of the X-Momentum
  //equation
  double viscous_terms[2];
  for (int vi=0; vi<2; vi++)
    {
      viscous_terms[vi] =viscosity[vi]*(derivative_y[vi]                   
					+final_derivative_x[vi]);
    }

  dy_total=2.*dy[j];
  double result =
    1./Reynolds*(1.*Derivative(viscous_terms[1],
			       viscous_terms[0],
			       dy_total,1));
  
  return result;
}
Exemplo n.º 12
0
//---------------------------------------------------------------------------
double DoRInterpolation(double r, double g, double b)
{
    double x1,y1,z1;
    double x2,y2,z2;
    double x3,y3,z3;
    double x4,y4,z4;
    double g1, g2, e1, e2;

    TColorTable ct[8];
    MakeCube(r,g,b, ct);

    x1 = ct[0].BM;
    y1 = ct[0].RM;
	z1 = ct[0].GM;

    x2 = ct[7].BM;
    y2 = ct[7].RM;
    z2 = ct[7].GM;

    x3 = ct[3].BM;
    y3 = ct[3].RM;
    z3 = ct[3].GM;

    x4 = ct[5].BM;
    y4 = ct[5].RM;
    z4 = ct[5].GM;

    g1 = PlaneInterpolaton(x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,b,r);
    z1 = ct[0].R  - ct[0].RM;
    z2 = ct[7].R  - ct[7].RM;
    z3 = ct[3].R  - ct[3].RM;
    z4 = ct[5].R  - ct[5].RM;
    e1 = PlaneInterpolaton(x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,b,r);

    x1 = ct[6].BM;
    y1 = ct[6].RM;
    z1 = ct[6].GM;

    x2 = ct[2].BM;
    y2 = ct[2].RM;
    z2 = ct[2].GM;

    x3 = ct[1].BM;
    y3 = ct[1].RM;
    z3 = ct[1].GM;

    x4 = ct[4].BM;
    y4 = ct[4].RM;
    z4 = ct[4].GM;

    g2 = PlaneInterpolaton(x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,b,r);


    z1 = ct[6].R  - ct[6].RM;
    z2 = ct[2].R  - ct[2].RM;
    z3 = ct[1].R  - ct[1].RM;
    z4 = ct[4].R  - ct[4].RM;
    e2 = PlaneInterpolaton(x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,b,r);
    return Interpolation(g1,g2,e1,e2, g);

}
Exemplo n.º 13
0
double Viscous_Component_YX(double*** velocity_x, double*** velocity_y,
                            double*** temperature,
                            double*** eddy_viscosity,
                            double Reynolds,
                            double dx, double* dy,
                            int i, int j, int k)
{

  double  derivative_xx[4][2], derivative_xy[4][2];
  double dy_total,  viscous_terms[4];

  // Calculation of the (dv/dx) component
  double total_derivative_x[4];
  for (int vi=0; vi<4; vi++)
    {

      derivative_xx[vi][0] = 9./(8.)*Derivative(velocity_y[k][j][i+vi-1],
                                                velocity_y[k][j][i+vi-2],
                                                dx,1);

      derivative_xx[vi][1] = -1./(8.)*Derivative(velocity_y[k][j][i+vi],
                                                 velocity_y[k][j][i+vi-3],
                                                 dx,3);

      //initalizing the vector
      total_derivative_x[vi]=0.;
      for (int vj=0; vj<2; vj++)
        total_derivative_x[vi]+=derivative_xx[vi][vj];

    }

  // Calculation of the (du/dy) component
  //i-3/2
  //i-3
  dy_total=dy[j-1]+2.*dy[j]+dy[j+1];
  derivative_xy[0][0] = Derivative(velocity_x[k][j+1][i-3],
                                   velocity_x[k][j-1][i-3],
                                   dy_total,1);

  //i
  dy_total=dy[j-1]+2.*dy[j]+dy[j+1];
  derivative_xy[0][1] = Derivative(velocity_x[k][j+1][i],
                                   velocity_x[k][j-1][i],
                                   dy_total,1);

  //i-1/2
  //i-1
  dy_total=dy[j-1]+2.*dy[j]+dy[j+1];
  derivative_xy[1][0] = Derivative(velocity_x[k][j+1][i-1],
                                   velocity_x[k][j-1][i-1],
                                   dy_total,1);

  //i/
  derivative_xy[1][1] = derivative_xy[0][1];

  //i+1/2
  //i
  derivative_xy[2][0] = derivative_xy[0][1];
  //i+1
  dy_total=dy[j-1]+2.*dy[j]+dy[j+1];
  derivative_xy[2][1] = Derivative(velocity_x[k][j+1][i+1],
                                   velocity_x[k][j-1][i+1],
                                   dy_total,1);

  //i+3/2
  //i
  derivative_xy[3][0] = derivative_xy[0][1];
  //i+3
  dy_total=dy[j-1]+2.*dy[j]+dy[j+1];
  derivative_xy[3][1] = Derivative(velocity_x[k][j+1][i+3],
                                   velocity_x[k][j-1][i+3],
                                   dy_total,1);


  //summing the derivatives in the y direction
  double total_derivative_y[4];
  for(int vi=0; vi<4; vi++)
    {
      total_derivative_y[vi]=Interpolation(derivative_xy[vi][0],
                                           derivative_xy[vi][1]);
    }

  //Computing the viscosities.
  double viscosity[4];
  for (int vi=-2, vj=0; vi<2; vi++, vj++)
    {
      viscosity[vj]=
        Viscosity_Calculator(Interpolation(temperature[k][j][i+vi+1],
                                           temperature[k][j][i+vi]))
        +Interpolation(eddy_viscosity[k][j][i+vi+1],
                       eddy_viscosity[k][j][i+vi]);
    }


  //computing the viscous tensors
  for (int vi=0; vi<4; vi++)
    {
      viscous_terms[vi] =viscosity[vi]*(total_derivative_x[vi]
                                        +total_derivative_y[vi]);
    }


  // cout<<"yx"<<endl;
  // cout<<-1./24.*(total_derivative_y[3]-total_derivative_y[0])
  //   +9./8.*(total_derivative_y[2]-total_derivative_y[1])<<endl;



  /* Summing the X-component of the Viscous Term of the Y-Momentum equation*/
  double viscous_component =
    1./Reynolds*(9./8.*Derivative(viscous_terms[2],
                                  viscous_terms[1],
                                  dx,1)-
                 1./8.*Derivative(viscous_terms[3],
                                  viscous_terms[0],
                                  dx,3));

  return viscous_component;


}
double Energy_Convection(double*** temperature,
                         double*** velocity_x, double*** velocity_y,
                         double*** velocity_z,
                         double dx, double* dy, double dz,
                         int i, int j, int k)
{

  double convective_terms[3];
  double interpolated[4], derivative[2],total_interpolated[2];


  //X-Direction
  for (int vi=0; vi<2; vi++)
    {
      interpolated[vi]=Interpolation(velocity_x[k][j][i+vi],
                                     velocity_x[k][j][i+vi-1]);

      interpolated[vi+2]=Interpolation(velocity_x[k][j][i+2*vi],
                                       velocity_x[k][j][i+2*vi-2]);
    }

  total_interpolated[0]=interpolated[0]+interpolated[1];
  total_interpolated[1]=interpolated[2]+interpolated[3];


  derivative[0]=4./3.*Derivative(temperature[k][j][i+1],
                                 temperature[k][j][i-1],
                                 dx, 2);

  derivative[1]=-1./3.*Derivative(temperature[k][j][i+2],
                                  temperature[k][j][i-2],
                                  dx, 4);

  convective_terms[0]=0.;
  for(int vi=0; vi<2; vi++)
    convective_terms[0]+=derivative[vi]*total_interpolated[vi];



  //Y-direction. This quantity I computed it by just implementing vdT/dy. At the
  // paper it says that the v has also to be interpolated so this source can
  // cause errors

  double dy_total=dy[j+1]+2.*dy[j]+dy[j-1];
  derivative[0]=Derivative(velocity_y[k][j+1][i],
                           velocity_y[k][j-1][i],
                           dy_total,1);

  convective_terms[1] =velocity_y[k][j][i]*derivative[0];


  //Z-Component
  for (int vi=0; vi<2; vi++)
    {
      interpolated[vi]=Interpolation( velocity_z[k+vi][j][i],
                                      velocity_z[k+vi-1][j][i]);

      interpolated[vi+2]=Interpolation(velocity_z[k+2*vi][j][i],
                                       velocity_x[k+2*vi-2][j][i]);

    }

  total_interpolated[0]=interpolated[0]+interpolated[1];
  total_interpolated[1]=interpolated[2]+interpolated[3];


  derivative[0]=4./3.*Derivative(temperature[k+1][j][i],
                                 temperature[k-1][j][i],
                                 dz, 2);

  derivative[1]=-1./3.*Derivative(temperature[k+2][j][i],
                                  temperature[k-2][j][i],
                                  dz, 4);

  convective_terms[2]=0.;
  for(int vi=0; vi<2; vi++)
    convective_terms[2]+=derivative[vi]*total_interpolated[vi];


  double convection=0.;
  for (int vi=0; vi<3; vi++)
    convection+=convective_terms[vi];

  return convection;
}
Exemplo n.º 15
0
double get_ndep (TSD ndep_ts, double t)
{
    return Interpolation (&ndep_ts, t);
}
double Viscous_Component_YZ(double*** velocity_y, double*** velocity_z,
                            double*** temperature, double Reynolds,
                            double* dy, double dz,
                            int i, int j, int k)
{

  double derivative_zy[4][2], derivative_zz[4][2],
    viscous_terms[4], viscosity[4], dy_total;

  //Calculation of the d/dz(dv/dz) component
  double total_derivative_z[4];
  for (int vi=0; vi<4; vi++)
    {
      derivative_zz[vi][0]= 9./8.*Derivative(velocity_y[k+vi-1][j][i],
                                             velocity_y[k+vi-2][j][i],
                                             dz,1);

      derivative_zz[vi][1]= -1./8.*Derivative(velocity_y[k+vi][j][i],
                                              velocity_y[k+vi-3][j][i],
                                              dz,3);

      //computing the total derivative
      total_derivative_z[vi]=0.;
      for (int vj=0; vj<2; vj++)
        total_derivative_z[vi]+=derivative_zz[vi][vj];

    }

  //Calculation of the d/dz(dw/dy) component

  //k-3/2
  //k-3
  dy_total=dy[j-1]+2.*dy[j]+dy[j+1];
  derivative_zy[0][0] = Derivative(velocity_z[k-3][j+1][i],
                                   velocity_z[k-3][j-1][i],
                                   dy_total,1);

  //k
  dy_total=dy[j-1]+2.*dy[j]+dy[j+1];
  derivative_zy[0][1] = Derivative(velocity_z[k][j+1][i],
                                   velocity_z[k][j-1][i],
                                   dy_total,1);

  //k-1/2

  //k-1
  //k
  dy_total=dy[j-1] +2.*dy[j] +dy[j+1];
  derivative_zy[1][0] = Derivative(velocity_z[k-1][j+1][i],
                                   velocity_z[k-1][j-1][i],
                                   dy_total,1);

  //k
  derivative_zy[1][1] = derivative_zy[0][1];


  //k+1/2

  //k
  derivative_zy[2][0] = derivative_zy[0][1];


  //k+1
  dy_total=dy[j-1] +2.*dy[j] +dy[j+1];
  derivative_zy[2][1] = Derivative(velocity_z[k+1][j+1][i],
                                   velocity_z[k+1][j-1][i],
                                   dy_total,1);

  // k+3/2
  //k
  derivative_zy[3][0] = derivative_zy[0][1];
  //k+3
  dy_total=dy[j-1]+2.*dy[j]+dy[j+1];
  derivative_zy[3][1] = Derivative(velocity_z[k+3][j+1][i],
                                   velocity_z[k+3][j-1][i],
                                   dy_total,1);

  //computing the total derivative in the y-direction
  double total_derivative_y[4];
  for(int vi=0; vi<4; vi++)
    {
      total_derivative_y[vi]=Interpolation(derivative_zy[vi][0],
                                           derivative_zy[vi][1]);
    }


  //Computing the viscosities.
  for (int vi=-1, vj=0; vj<4; vi++, vj++)
    {
      viscosity[vj]=
        Viscosity_Calculator(Interpolation(temperature[k+vi][j][i],
                                           temperature[k+vi+1][j][i]));
    }



  //computing the viscous tensors
  for (int vi=0; vi<4; vi++)
    {
      viscous_terms[vi] =viscosity[vi]*(total_derivative_y[vi]+
                                        total_derivative_z[vi]);
    }



  // cout<<"yz"<<endl;
  // cout<<-1./24.*(total_derivative_y[3]-total_derivative_y[0])
  //   +9./8*(total_derivative_y[2]-total_derivative_y[1])<<endl;


  double viscous_component =
    1./Reynolds*(9./8.*Derivative(viscous_terms[2],
                                  viscous_terms[1],
                                  dz,1)-
                 1./8.*Derivative(viscous_terms[3],
                                  viscous_terms[0],
                                  dz,3));


  return viscous_component;

}
Exemplo n.º 17
0
Arquivo: f.c Projeto: geoxuan/PIHM
void f(integertype N, realtype t, N_Vector CV_Y, N_Vector CV_Ydot, void *DS)
{
  int i, j;
  
  realtype Avg_Y_Surf, Dif_Y_Surf;
  realtype Distance;
  realtype Grad_Y_Surf, Avg_Sf;
  
  realtype TotalY_Riv, TotalY_Riv_down;
  realtype Wid, Wid_down;
  realtype Avg_Wid;
  realtype Avg_Y_Riv, Avg_Rough;
  realtype Left_Ele_Y, Left_Ele_YH;
  realtype Right_Ele_Y, Right_Ele_YH;
  realtype Dif_Y_Riv;
  realtype Avg_Y_Sub, Dif_Y_Sub;
  realtype Avg_Ksat, Grad_Y_Sub;
  realtype mp_factor;
  realtype G, GI;
  realtype Cwr, RivPrep;
  realtype temp1, temp2;
  
  realtype Alfa, Beta, CrossA;
  realtype bank_ele;
  realtype AquiferDepth, Deficit, PH;
  
  realtype *Y, *DY;
  Model_Data MD;
  
  Y = NV_DATA_S(CV_Y);
  DY = NV_DATA_S(CV_Ydot);
  MD = (Model_Data) DS;
  
  for(i=0; i<MD->NumEle; i++)
  {
    /*Unconfine Condition */

    if((Y[i + 2*MD->NumEle] >= ((MD->Ele[i].zmax - MD->Ele[i].zmin) + 0.1)))
    {
         Y[i] = Y[i] + MD->Ele[i].Porosity * (Y[i + 2*MD->NumEle] - (MD->Ele[i].zmax - MD->Ele[i].zmin + 0.1));
         Y[i + MD->NumEle] = 0.0;
         Y[i + 2*MD->NumEle] = MD->Ele[i].zmax - MD->Ele[i].zmin + 0.1;   
    }
    
    for(j=0; j<3; j++)
    {
      if(MD->Ele[i].nabr[j] > 0)
      {
        /* groundwater interaction */
        Avg_Y_Sub = (Y[i+2*MD->NumEle] + Y[MD->Ele[i].nabr[j]-1+2*MD->NumEle])/2.0;
        Dif_Y_Sub = (Y[i+2*MD->NumEle] + MD->Ele[i].zmin) - (Y[MD->Ele[i].nabr[j]-1 + 2*MD->NumEle] + MD->Ele[MD->Ele[i].nabr[j]-1].zmin);
        Distance = sqrt(pow((MD->Ele[i].x - MD->Ele[MD->Ele[i].nabr[j] - 1].x), 2) + pow((MD->Ele[i].y - MD->Ele[MD->Ele[i].nabr[j] - 1].y), 2));
        Avg_Ksat = (MD->Ele[i].Ksat + MD->Ele[MD->Ele[i].nabr[j] - 1].Ksat)/2.0;
        Grad_Y_Sub = Dif_Y_Sub/Distance;
        
        /* take care of macropore effect */
        if (MD->Soil[(MD->Ele[i].soil-1)].Macropore == 0)
        {
          mp_factor = 1;
        }
        else if (MD->Soil[(MD->Ele[i].soil-1)].Macropore == 1)
        {
          if (Y[i+2*MD->NumEle] > MD->Soil[(MD->Ele[i].soil-1)].base)
          {
            temp1 = pow(10, MD->Soil[(MD->Ele[i].soil-1)].gama*(Y[i+2*MD->NumEle]/MD->Soil[(MD->Ele[i].soil-1)].base - 1));
          }
          else
          {
            temp1 = 1;
          }
          
          if (Y[MD->Ele[i].nabr[j] - 1 + 2*MD->NumEle] > MD->Soil[(MD->Ele[MD->Ele[i].nabr[j]-1].soil-1)].base)
          {
            temp2 = pow(10, MD->Soil[(MD->Ele[MD->Ele[i].nabr[j]-1].soil-1)].gama*(Y[MD->Ele[i].nabr[j]-1+2*MD->NumEle]/MD->Soil[(MD->Ele[MD->Ele[i].nabr[j]-1].soil-1)].base - 1));
          }
          else
          {
            temp2 = 1;
          }  
          
          mp_factor = (temp1 + temp2)/2.0; 
        }
        
        /* groundwater flow modeled by Darcy's law */
        MD->FluxSub[i][j] = mp_factor*Avg_Ksat*Grad_Y_Sub*Avg_Y_Sub*MD->Ele[i].edge[j];
        
        /* No Source Check */
        if(Y[i + 2*MD->NumEle] <= 0 && MD->FluxSub[i][j] > 0)
        {
          MD->FluxSub[i][j] = 0;
        }
        if(Y[MD->Ele[i].nabr[j] - 1 + 2*MD->NumEle] <= 0 && MD->FluxSub[i][j] < 0)
        {
          MD->FluxSub[i][j] = 0;
        }
        
        /* Saturation check */
        /*
        if((Y[i + 2*MD->NumEle] >= (MD->Ele[i].zmax - MD->Ele[i].zmin)) && MD->FluxSub[i][j] < 0)
        {
          MD->FluxSub[i][j] = 0;
        }
        if((Y[MD->Ele[i].nabr[j] - 1 + 2*MD->NumEle] >= (MD->Ele[MD->Ele[i].nabr[j] - 1].zmax - MD->Ele[MD->Ele[i].nabr[j] - 1].zmin)) && MD->FluxSub[i][j] <0)
        {
          MD->FluxSub[i][j] = 0;
        }*/
        
        /* Surface Interaction */
        Avg_Y_Surf = (Y[i] + Y[MD->Ele[i].nabr[j]-1])/2.0;
        Dif_Y_Surf = (Y[i] + MD->Ele[i].zmax) - (Y[MD->Ele[i].nabr[j] - 1] + MD->Ele[MD->Ele[i].nabr[j] - 1].zmax);
        Grad_Y_Surf = Dif_Y_Surf/Distance;
        Avg_Sf = (MD->Ele[i].Sf + MD->Ele[MD->Ele[i].nabr[j] - 1].Sf)/2.0;
        Avg_Rough = 0.5*(MD->Ele[i].Rough + MD->Ele[MD->Ele[i].nabr[j] - 1].Rough);
        CrossA = Avg_Y_Surf*MD->Ele[i].edge[j];
        
        /* if surface gradient is not enough to overcome the friction */
        if(fabs(Grad_Y_Surf) <= Avg_Sf)
        {
          MD->FluxSurf[i][j] = 0;
        } 
        else if((Grad_Y_Surf > 0) && (Grad_Y_Surf > Avg_Sf))
        {
          switch(MD->SurfMode) 
          {
            case 1:      
              
              /* Kinematic Wave Approximation constitutive relationship: Manning Equation */
              Alfa = sqrt(Grad_Y_Surf - Avg_Sf)/Avg_Rough;
              Beta = pow(Avg_Y_Surf, 2.0/3.0);
              MD->FluxSurf[i][j] = 60*Alfa*Beta*CrossA;
              break;                   
              
            case 2:
            
              /* Diffusion Wave Approximation constitutive relationship: Gottardi & Venutelli, 1993 */
              Alfa = pow(Avg_Y_Surf, 2.0/3.0)/Avg_Rough;
              Beta = Alfa/sqrt(Grad_Y_Surf - Avg_Sf);
              MD->FluxSurf[i][j] = 60*CrossA*Beta*Grad_Y_Surf;
              break;
              
            default:
              printf("Fatal Error: Surface Overland Mode Type Is Wrong!");
              exit(1);
          }                        
        }
        else if((Grad_Y_Surf < 0) && ((-Grad_Y_Surf) > Avg_Sf))
        {
          switch(MD->SurfMode) 
          {
            case 1:
            
              /* Kinematic Wave Approximation constitutive relationship: Manning Equation */
              Alfa = sqrt(-Grad_Y_Surf - Avg_Sf)/Avg_Rough;
              Beta = pow(Avg_Y_Surf, 2.0/3.0);
              MD->FluxSurf[i][j] = -60*Alfa*Beta*CrossA;
              break;                   
              
            case 2:
              
              /* Diffusion Wave Approximation constitutive relationship: Gottardi & Venutelli, 1993 */
              Alfa = pow(Avg_Y_Surf, 2.0/3.0)/Avg_Rough;
              Beta = Alfa/sqrt(-Grad_Y_Surf - Avg_Sf);
              MD->FluxSurf[i][j] = 60*CrossA*Beta*Grad_Y_Surf;
              break;
              
            default:
              printf("Fatal Error: Surface Overland Mode Type Is Wrong!");
              exit(1);
          }   
        }
        
        /* Source Check */
        if(Y[i] <= 0 && MD->FluxSurf[i][j] > 0)
        {
          MD->FluxSurf[i][j] = 0;
        }
        if(Y[MD->Ele[i].nabr[j] - 1] <= 0 && MD->FluxSurf[i][j] < 0)
        {
          MD->FluxSurf[i][j] = 0;
        }
      }
      else
      {
        /* Handle boundary conditions for elements. No flow (natural) boundary condition is default */
        if(MD->Ele[i].BC == 0)
        {
          MD->FluxSurf[i][j] = 0;
          MD->FluxSub[i][j] = 0;
        }
        else
        {
          MD->FluxSurf[i][j] = 0;
          
          /* this part of code has not been tested! */
          if(MD->Ele[i].BC > 0)         /* Dirichlet BC */
          {
            Avg_Y_Sub = (Y[i+2*MD->NumEle] + (Interpolation(&MD->TSD_EleBC[(MD->Ele[i].BC)-1], t) - MD->Ele[i].zmin))/2;
            Dif_Y_Sub = (Y[i+2*MD->NumEle] + MD->Ele[i].zmin) - 
                         Interpolation(&MD->TSD_EleBC[(MD->Ele[i].BC)-1], t);            
            Distance = sqrt(pow(MD->Ele[i].edge[0]*MD->Ele[i].edge[1]*MD->Ele[i].edge[2]/(4*MD->Ele[i].area), 2) - pow(MD->Ele[i].edge[j]/2, 2));
            Avg_Ksat = MD->Ele[i].Ksat;
            Grad_Y_Sub = Dif_Y_Sub/Distance;
        
            MD->FluxSub[i][j] = Avg_Ksat*Grad_Y_Sub*Avg_Y_Sub*MD->Ele[i].edge[j];
          }
          else                          /* Nuemann BC */
          {
            MD->FluxSub[i][j] = Interpolation(&MD->TSD_EleBC[(-MD->Ele[i].BC)-1+MD->Num1BC], t);
          }
        }
        
        /* Source check */
        if(Y[i + 2*MD->NumEle] <= 0 && MD->FluxSub[i][j] > 0)
        {
          MD->FluxSub[i][j] = 0;
        }  
      }
    }
  }
  
  /* initialize river flux */
  for(i=0; i<MD->NumRiv; i++)
  {
    for(j=0; j<6; j++)
    {
      MD->FluxRiv[i][j] = 0;
    }  
  } 
   
  for(i=0; i<MD->NumRiv; i++)
  {
    /* Note: the ordering of river segment in input file has to be: from UP to DOWN */   
    TotalY_Riv = Y[i + 3*MD->NumEle] + MD->Riv[i].zmin;
    Wid = MD->Riv_Shape[MD->Riv[i].shape - 1].width;
    
    if(MD->Riv[i].down > 0)
    {
      TotalY_Riv_down = Y[MD->Riv[i].down - 1 + 3*MD->NumEle] + MD->Riv[MD->Riv[i].down - 1].zmin;
      Wid_down = MD->Riv_Shape[MD->Riv[MD->Riv[i].down - 1].shape - 1].width;
      Avg_Wid = (Wid + Wid_down)/2.0;
      Avg_Y_Riv = (Y[i+3*MD->NumEle] + Y[MD->Riv[i].down - 1 + 3*MD->NumEle])/2.0;
      Avg_Rough = (MD->Riv_Mat[MD->Riv[i].material - 1].Rough + MD->Riv_Mat[MD->Riv[MD->Riv[i].down - 1].material-1].Rough)/2.0;
      Distance = sqrt(pow(MD->Riv[i].x - MD->Riv[MD->Riv[i].down - 1].x, 2) + pow(MD->Riv[i].y - MD->Riv[MD->Riv[i].down - 1].y, 2));
      Dif_Y_Riv = (TotalY_Riv - TotalY_Riv_down)/Distance; 
      Avg_Sf = (MD->Riv_Mat[MD->Riv[i].material - 1].Sf + MD->Riv_Mat[MD->Riv[MD->Riv[i].down - 1].material-1].Sf)/2.0;   
      CrossA = Avg_Y_Riv*Avg_Wid;
      
      if(fabs(Dif_Y_Riv) <= Avg_Sf)
      {
        MD->FluxRiv[i][1] = 0;
      } 
      else if((Dif_Y_Riv > 0) && (Dif_Y_Riv > Avg_Sf))
      {
        switch(MD->RivMode) 
        {
          case 1:  
          
          /* Kinematic Wave Approximation constitutive relationship: Manning Equation */    
          Alfa = sqrt(Dif_Y_Riv - Avg_Sf)/(Avg_Rough*pow((Avg_Wid + 2*Avg_Y_Riv), 2.0/3.0));
          Beta = 5.0/3.0;
          MD->FluxRiv[i][1] = 60*Alfa*pow(CrossA, Beta);
          break;                   
              
          case 2:
          
          /* Diffusion Wave Approximation constitutive relationship: Gottardi & Venutelli, 1993 */    
          Alfa = pow(Avg_Y_Riv, 2.0/3.0)/Avg_Rough;
          Beta = Alfa/sqrt(Dif_Y_Riv - Avg_Sf);
          MD->FluxRiv[i][1] = 60*CrossA*Beta*Dif_Y_Riv;
          break;
              
          default:
            printf("Fatal Error: River Routing Mode Type Is Wrong!");
            exit(1);
        }
      }
      else if((Dif_Y_Riv < 0) && (-Dif_Y_Riv > Avg_Sf))
      {
        switch(MD->RivMode) 
        {
          case 1:
              
          /* Kinematic Wave Approximation constitutive relationship: Manning Equation */    
          Alfa = sqrt(-Dif_Y_Riv - Avg_Sf)/(Avg_Rough*pow((Avg_Wid + 2*Avg_Y_Riv), 2.0/3.0));
          Beta = 5.0/3.0;
          MD->FluxRiv[i][1] = -60*Alfa*pow(CrossA, Beta);
          break;                     
              
          case 2:
          
          /* Diffusion Wave Approximation constitutive relationship: Gottardi & Venutelli, 1993 */     
          Alfa = pow(Avg_Y_Riv, 2.0/3.0)/Avg_Rough;
          Beta = Alfa/sqrt(-Dif_Y_Riv - Avg_Sf);
          MD->FluxRiv[i][1] = 60*CrossA*Beta*Dif_Y_Riv;
          break;
              
          default:
            printf("Fatal Error: River Routing Mode Type Is Wrong!");
            exit(1);
        }
      }  

      /* Source check */
      if(Y[i + 3*MD->NumEle] <= 0 && MD->FluxRiv[i][1] > 0)
      {
        MD->FluxRiv[i][1] = 0;
      }
      else if(Y[MD->Riv[i].down - 1 + 3*MD->NumEle] <= 0 && MD->FluxRiv[i][1] < 0)
      {
        MD->FluxRiv[i][1] = 0;
      }
      
      /* accumulate to get in-flow for down segments */
      MD->FluxRiv[MD->Riv[i].down - 1][0] = MD->FluxRiv[MD->Riv[i].down - 1][0] + MD->FluxRiv[i][1];
    }
    else
    {
      switch(MD->Riv[i].down)
      {
        case -1:  
         
          /* Dirichlet boundary condition */        
          TotalY_Riv_down = Interpolation(&MD->TSD_Riv[(MD->Riv[i].BC)-1], t) + MD->Node[MD->Riv[i].ToNode-1].zmin + MD->Riv_Shape[MD->Riv[i].shape-1].bed;
          Distance = sqrt(pow(MD->Riv[i].x - MD->Node[MD->Riv[i].ToNode-1].x, 2) + pow(MD->Riv[i].y - MD->Node[MD->Riv[i].ToNode-1].y, 2));
          Dif_Y_Riv = (TotalY_Riv - TotalY_Riv_down)/Distance; 
          Avg_Sf = MD->Riv_Mat[MD->Riv[i].material - 1].Sf;
          Avg_Rough = MD->Riv_Mat[MD->Riv[i].material-1].Rough;
          Avg_Y_Riv = Y[i + 3*MD->NumEle];
          Avg_Wid = Wid;
          CrossA = Wid*Avg_Y_Riv;
          
          if(fabs(Dif_Y_Riv) <= Avg_Sf)
          {
            MD->FluxRiv[i][1] = 0;
          } 
          else if((Dif_Y_Riv > 0) && (Dif_Y_Riv > Avg_Sf))
          {
            switch(MD->RivMode) 
            {
              case 1:  
                
                /* Kinematic Wave Approximation constitutive relationship: Manning Equation */    
                Alfa = sqrt(Dif_Y_Riv - Avg_Sf)/(Avg_Rough*pow((Avg_Wid + 2*Avg_Y_Riv), 2.0/3.0));
                Beta = 5.0/3.0;
                MD->FluxRiv[i][1] = 60*Alfa*pow(CrossA, Beta);
                break;                
              
              case 2:     
              
                /* Diffusion Wave Approximation constitutive relationship: Gottardi & Venutelli, 1993 */
                Alfa = pow(Avg_Y_Riv, 2.0/3.0)/Avg_Rough;
                Beta = Alfa/sqrt(Dif_Y_Riv - Avg_Sf);
                MD->FluxRiv[i][1] = 60*CrossA*Beta*Dif_Y_Riv;
                break;
              
              default:
                printf("Fatal Error: River Routing Mode Type Is Wrong!");
                exit(1);
            }
          }
          else if((Dif_Y_Riv < 0) && (-Dif_Y_Riv > Avg_Sf))
          {
            switch(MD->RivMode) 
            {
              case 1: 
              
                /* Kinematic Wave Approximation constitutive relationship: Manning Equation */    
                Alfa = sqrt(-Dif_Y_Riv - Avg_Sf)/(Avg_Rough*pow((Avg_Wid + 2*Avg_Y_Riv), 2.0/3.0));
                Beta = 5.0/3.0;
                MD->FluxRiv[i][1] = -60*Alfa*pow(CrossA, Beta);
                break;                      
              
              case 2:
              
                /* Diffusion Wave Approximation constitutive relationship: Gottardi & Venutelli, 1993 */
                Alfa = pow(Avg_Y_Riv, 2.0/3.0)/Avg_Rough;
                Beta = Alfa/sqrt(-Dif_Y_Riv - Avg_Sf);
                MD->FluxRiv[i][1] = 60*CrossA*Beta*Dif_Y_Riv;
                break;
              
              default:
                printf("Fatal Error: River Routing Mode Type Is Wrong!");
                exit(1);
            }
          }
          break;
          
        case -2:
          
          /* Neumann boundary condition */
          MD->FluxRiv[i][1] = Interpolation(&MD->TSD_Riv[MD->Riv[i].BC-1], t);
          break;
          
        case -3:    
          
          /* zero-depth-gradient boundary conditions */
          Distance = sqrt(pow(MD->Riv[i].x - MD->Node[MD->Riv[i].ToNode-1].x, 2) + pow(MD->Riv[i].y - MD->Node[MD->Riv[i].ToNode-1].y, 2));
          Dif_Y_Riv = (MD->Riv[i].zmin - (MD->Node[MD->Riv[i].ToNode-1].zmin + MD->Riv_Shape[MD->Riv[i].shape-1].bed))/Distance;
          Avg_Rough = MD->Riv_Mat[MD->Riv[i].material-1].Rough;
          Avg_Y_Riv = Y[i + 3*MD->NumEle];
          Avg_Wid = Wid;
          CrossA = Wid*Avg_Y_Riv;
          MD->FluxRiv[i][1] = 60*Avg_Wid*pow(Avg_Y_Riv, 5.0/3.0)*sqrt(Dif_Y_Riv)/Avg_Rough;
          break;
          
        case -4:
          
          /* Critical Depth boundary conditions */
          CrossA = Wid*Y[i + 3*MD->NumEle];
          MD->FluxRiv[i][1] = 60*CrossA*sqrt(9.81*Y[i + 3*MD->NumEle]);
          break;
          
        default:
          printf("Fatal Error: River Routing Boundary Condition Type Is Wrong!");
          exit(1); 
      }     
      
      /* Source check */
      if(Y[i + 3*MD->NumEle] <= 0 && MD->FluxRiv[i][1] > 0)
      {
        MD->FluxRiv[i][1] = 0;
      }
      else if(Y[MD->Riv[i].down - 1 + 3*MD->NumEle] <= 0 && MD->FluxRiv[i][1] < 0)
      {
        MD->FluxRiv[i][1] = 0;
      }  
      
      /* need some work to take care of multiple output Q */
      MD->Q = MD->FluxRiv[i][1];
          
    }
    
    /* Interaction between surface flow and channel */
    if (MD->Riv[i].LeftEle > 0)
    {
      Left_Ele_Y = Y[MD->Riv[i].LeftEle - 1];
      Left_Ele_YH = Y[MD->Riv[i].LeftEle - 1] + MD->Ele[MD->Riv[i].LeftEle - 1].zmax;
      Distance = sqrt(pow(MD->Riv[i].x - MD->Ele[MD->Riv[i].LeftEle - 1].x, 2) + pow(MD->Riv[i].y - MD->Ele[MD->Riv[i].LeftEle - 1].y, 2));
      Cwr = MD->Riv_Mat[MD->Riv[i].material-1].Cwr;
      
      if (MD->Riv[i].zmax < MD->Ele[MD->Riv[i].LeftEle - 1].zmax) { bank_ele = MD->Ele[MD->Riv[i].LeftEle - 1].zmax;} 
      else { bank_ele = MD->Riv[i].zmax;}
      
      if (TotalY_Riv > Left_Ele_YH)
      {
        if (Left_Ele_YH > bank_ele)
        {
          MD->FluxRiv[i][2] = Cwr*60*2.0*sqrt(2*9.81)*MD->Riv[i].Length*sqrt(TotalY_Riv - Left_Ele_YH)*(TotalY_Riv - bank_ele)/3.0;
        }
        else
        {
          MD->FluxRiv[i][2] = Cwr*60*2.0*sqrt(2*9.81)*MD->Riv[i].Length*sqrt(TotalY_Riv - bank_ele)*(TotalY_Riv - bank_ele)/3.0;
        }
      }
      else
      {
        if (TotalY_Riv > bank_ele)
        {
          MD->FluxRiv[i][2] = -Cwr*60*2.0*sqrt(2*9.81)*MD->Riv[i].Length*sqrt(Left_Ele_YH - TotalY_Riv)*(Left_Ele_YH - bank_ele)/3.0;
        }
        else
        {
          /* This is basicaly a lump representation */
          MD->FluxRiv[i][2] = -Cwr*60*2.0*sqrt(2*9.81)*MD->Riv[i].Length*sqrt(Left_Ele_YH - bank_ele)*(Left_Ele_YH - bank_ele)/3.0;
        }
      }
      
      /* source check */
      if(Y[i + 3*MD->NumEle] <= 0 && MD->FluxRiv[i][2] > 0)
      {
        MD->FluxRiv[i][2] = 0;
      }
    
      if(Y[MD->Riv[i].LeftEle - 1] <= 0 && MD->FluxRiv[i][2] < 0)
      {
        MD->FluxRiv[i][2] = 0;
      }
      
      /* replace overland flux item */
      for(j=0; j < 3; j++)
      {
        /* this may cause trouble when there are 2 boundary side and one is not neutral.*/
        if(MD->Ele[MD->Riv[i].LeftEle - 1].nabr[j] == MD->Riv[i].RightEle)
        {
          MD->FluxSurf[MD->Riv[i].LeftEle - 1][j] = -MD->FluxRiv[i][2];
        }
      }      
    }
    
    if (MD->Riv[i].RightEle > 0)
    {
      Right_Ele_Y = Y[MD->Riv[i].RightEle - 1];
      Right_Ele_YH = Y[MD->Riv[i].RightEle - 1] + MD->Ele[MD->Riv[i].RightEle - 1].zmax;
      Distance = sqrt(pow(MD->Riv[i].x - MD->Ele[MD->Riv[i].RightEle - 1].x, 2) + pow(MD->Riv[i].y - MD->Ele[MD->Riv[i].RightEle - 1].y, 2));
      Cwr = MD->Riv_Mat[MD->Riv[i].material-1].Cwr;
      
      if (MD->Riv[i].zmax < MD->Ele[MD->Riv[i].RightEle - 1].zmax) { bank_ele = MD->Ele[MD->Riv[i].RightEle - 1].zmax;} 
      else { bank_ele = MD->Riv[i].zmax;}
      
      if (TotalY_Riv > Right_Ele_YH)
      {
        if (Right_Ele_YH > bank_ele)
        {
          MD->FluxRiv[i][3] = Cwr*60*2.0*sqrt(2*9.81)*MD->Riv[i].Length*sqrt(TotalY_Riv - Right_Ele_YH)*(TotalY_Riv - bank_ele)/3.0;
        }
        else
        {
          MD->FluxRiv[i][3] = Cwr*60*2.0*sqrt(2*9.81)*MD->Riv[i].Length*sqrt(TotalY_Riv - bank_ele)*(TotalY_Riv - bank_ele)/3.0;
        }
      }
      else
      {
        if (TotalY_Riv > bank_ele)
        {
          MD->FluxRiv[i][3] = -Cwr*60*2.0*sqrt(2*9.81)*MD->Riv[i].Length*sqrt(Right_Ele_YH - TotalY_Riv)*(Right_Ele_YH - bank_ele)/3.0;
        }
        else
        {
          MD->FluxRiv[i][3] = -Cwr*60*2.0*sqrt(2*9.81)*MD->Riv[i].Length*sqrt(Right_Ele_YH - bank_ele)*(Right_Ele_YH - bank_ele)/3.0;
        }
      }
      
      /* source check */
      if(Y[i + 3*MD->NumEle] <= 0 && MD->FluxRiv[i][3] > 0)
      {
        MD->FluxRiv[i][3] = 0;
      }
    
      if(Y[MD->Riv[i].RightEle - 1] <= 0 && MD->FluxRiv[i][3] < 0)
      {
        MD->FluxRiv[i][3] = 0;
      }
      
      /* replace overland flux item */
      for(j=0; j < 3; j++)
      {
        if(MD->Ele[MD->Riv[i].RightEle - 1].nabr[j] == MD->Riv[i].LeftEle)
        {
          MD->FluxSurf[MD->Riv[i].RightEle - 1][j] = -MD->FluxRiv[i][3];
          break;
        }
      }
    }
           
    /* groundwater interaction */
    if (MD->Riv[i].LeftEle > 0)
    {
      /* Left Neighbor Groundwater Head */
      Left_Ele_Y = Y[MD->Riv[i].LeftEle - 1 + 2*MD->NumEle];
      Left_Ele_YH = Y[MD->Riv[i].LeftEle - 1 + 2*MD->NumEle] + MD->Ele[MD->Riv[i].LeftEle - 1].zmin;
      Distance = sqrt(pow(MD->Riv[i].x - MD->Ele[MD->Riv[i].LeftEle - 1].x, 2) + pow(MD->Riv[i].y - MD->Ele[MD->Riv[i].LeftEle - 1].y, 2));
    
      if (MD->Soil[(MD->Ele[MD->Riv[i].LeftEle - 1].soil-1)].Macropore == 0)
      {
        mp_factor = 1;
      }
      else if (MD->Soil[(MD->Ele[MD->Riv[i].LeftEle - 1].soil-1)].Macropore == 1)
      {
        if (Y[MD->Riv[i].LeftEle - 1 + 2*MD->NumEle] > MD->Soil[(MD->Ele[MD->Riv[i].LeftEle - 1].soil-1)].base)
        {
          mp_factor = pow(10, MD->Soil[(MD->Ele[MD->Riv[i].LeftEle - 1].soil-1)].gama*(Y[MD->Riv[i].LeftEle - 1 + 2*MD->NumEle]/MD->Soil[(MD->Ele[MD->Riv[i].LeftEle - 1].soil-1)].base - 1));
        }
        else
        {
          mp_factor = 1;
        }
      }
    
      MD->FluxRiv[i][4] = mp_factor*MD->Riv[i].Length*(0.5*Wid+Y[i+3*MD->NumEle]) * MD->Ele[MD->Riv[i].LeftEle - 1].Ksat * (TotalY_Riv - Left_Ele_YH)/Distance;
    
      /* source check */
      if(Y[i+3*MD->NumEle] <= 0 && MD->FluxRiv[i][4] > 0)
      {
        MD->FluxRiv[i][4] = 0;
      }
      if(Y[MD->Riv[i].LeftEle - 1 + 2*MD->NumEle] <= 0 && MD->FluxRiv[i][4] < 0)
      {
        MD->FluxRiv[i][4] = 0;
      }
    }
    
    if (MD->Riv[i].RightEle > 0)  
    {
      Right_Ele_Y = Y[MD->Riv[i].RightEle - 1 + 2*MD->NumEle];
      Right_Ele_YH = Y[MD->Riv[i].RightEle - 1 + 2*MD->NumEle] + MD->Ele[MD->Riv[i].RightEle - 1].zmin;
      Distance = sqrt(pow(MD->Riv[i].x - MD->Ele[MD->Riv[i].RightEle - 1].x, 2) + pow(MD->Riv[i].y - MD->Ele[MD->Riv[i].RightEle - 1].y, 2));
    
      if (MD->Soil[(MD->Ele[MD->Riv[i].RightEle - 1].soil-1)].Macropore == 0)
      {
        mp_factor = 1;
      }
      else if (MD->Soil[(MD->Ele[MD->Riv[i].RightEle - 1].soil-1)].Macropore == 1)
      {
        if (Y[MD->Riv[i].RightEle - 1 + 2*MD->NumEle] > MD->Soil[(MD->Ele[MD->Riv[i].RightEle - 1].soil-1)].base)
        {
          mp_factor = pow(10, MD->Soil[(MD->Ele[MD->Riv[i].RightEle - 1].soil-1)].gama*(Y[MD->Riv[i].RightEle - 1 + 2*MD->NumEle]/MD->Soil[(MD->Ele[MD->Riv[i].RightEle - 1].soil-1)].base - 1));
        }
        else
        {
          mp_factor = 1;
        }
      }
      
      MD->FluxRiv[i][5] = mp_factor*MD->Riv[i].Length*(0.5*Wid+Y[i+3*MD->NumEle]) * MD->Ele[MD->Riv[i].RightEle - 1].Ksat * (TotalY_Riv - Right_Ele_YH)/Distance;
    
      /* source check */
      if(Y[i + 3*MD->NumEle] <= 0 && MD->FluxRiv[i][5] > 0)
      {
        MD->FluxRiv[i][5] = 0;
      }
      if(Y[MD->Riv[i].RightEle - 1 + 2*MD->NumEle] <= 0 && MD->FluxRiv[i][5] < 0)
      {
        MD->FluxRiv[i][5] = 0;
      }
    }  
  }
  
  /* Calculate DY */ 
  switch(MD->UnsatMode) {
  
  case 1: 
   
    /* Shallow Groundwater assumption applied here*/
    for(i=0; i<MD->NumEle; i++)
    {
      AquiferDepth = MD->Ele[i].zmax - MD->Ele[i].zmin;
      
      if(Y[i+2*MD->NumEle] >= AquiferDepth)
      {
        Deficit = 0;
        MD->EleVic[i] = 0;
      }
      else
      {
        Deficit = AquiferDepth - Y[i+2*MD->NumEle];
        MD->EleVic[i] = Interpolation(&MD->TSD_Inc[MD->Soil[(MD->Ele[i].soil-1)].Inf-1], t);
      } 

      /* handle Prep and Infiltration first */
      if(Y[i+MD->NumEle] <= Deficit)
      {
        if(Y[i] > 0)
        {
          DY[i] = MD->EleNetPrep[i] - MD->EleVic[i];
          DY[i+2*MD->NumEle] = MD->EleVic[i];
        } 
        else if(MD->EleNetPrep[i] > MD->EleVic[i] && Y[i] <= 0)
        {
          DY[i] = MD->EleNetPrep[i] - MD->EleVic[i];
          DY[i+2*MD->NumEle] = MD->EleVic[i];
        }
        else if(MD->EleNetPrep[i] < MD->EleVic[i] && Y[i] <= 0 && MD->EleNetPrep[i] > 0)
        {
          DY[i] = 0;
          DY[i+2*MD->NumEle] = MD->EleNetPrep[i];
        }
        else     
        {
          DY[i] = 0;
          DY[i+2*MD->NumEle] = MD->EleNetPrep[i];
        }
      }
      else
      {
        /* The reason of this happening is not clear, therefore the treatment is not secure
           Fortranately, this will not happen in most cases. */
        DY[i] = MD->EleNetPrep[i];
        DY[i+2*MD->NumEle] = 0;
 
        if (Deficit > 0)
        {
          Y[i+MD->NumEle] = AquiferDepth - Y[i+2*MD->NumEle];
        }
        else
        {
          Y[i+2*MD->NumEle] = AquiferDepth;
          Y[i+MD->NumEle] = 0;
        }  
      }
      
      /* handle surface flux then */
      for(j=0; j<3; j++)
      {
        DY[i] =  DY[i] - MD->FluxSurf[i][j]/MD->Ele[i].area;
      }  
      
      /*
      if(Y[i] <= 0 && DY[i] < 0)
      {
        DY[i] = 0;
        DY[i+2*MD->NumEle] = MD->EleNetPrep[i];
      }*/
      
      for(j=0; j<3; j++)
      {
        DY[i+2*MD->NumEle] = DY[i+2*MD->NumEle] - MD->FluxSub[i][j]/MD->Ele[i].area;
      }
    }
  
    for(i=0; i<MD->NumRiv; i++)
    {
      if (MD->Riv[i].LeftEle > 0 && MD->Riv[i].RightEle > 0)
      {
        RivPrep = Interpolation(&MD->TSD_Prep[MD->Ele[MD->Riv[i].LeftEle-1].prep-1], t) + Interpolation(&MD->TSD_Prep[MD->Ele[MD->Riv[i].RightEle-1].prep-1], t);
        RivPrep = RivPrep/2;
      }  
      else if (MD->Riv[i].LeftEle > 0 && MD->Riv[i].RightEle == 0)
      {
        RivPrep = Interpolation(&MD->TSD_Prep[MD->Ele[MD->Riv[i].LeftEle-1].prep-1], t);
      }
      else if (MD->Riv[i].LeftEle == 0 && MD->Riv[i].RightEle > 0)  
      {
        RivPrep = Interpolation(&MD->TSD_Prep[MD->Ele[MD->Riv[i].RightEle-1].prep-1], t);
      }
      else
      {  
        /* for test case 3 only */
        /*RivPrep = Interpolation(&MD->TSD_Prep[0], t);*/
        RivPrep = 0;
      }
      
      DY[i+3*MD->NumEle] = RivPrep + MD->FluxRiv[i][0] - MD->FluxRiv[i][1];
      DY[i+3*MD->NumEle] = DY[i+3*MD->NumEle] - MD->FluxRiv[i][2] - MD->FluxRiv[i][3];
      DY[i+3*MD->NumEle] = DY[i+3*MD->NumEle] - MD->FluxRiv[i][4] - MD->FluxRiv[i][5];
      DY[i+3*MD->NumEle] = DY[i+3*MD->NumEle]/(MD->Riv[i].Length*Wid);
    
      if (MD->Riv[i].LeftEle > 0)
      {
        DY[MD->Riv[i].LeftEle-1 + 2*MD->NumEle] = DY[MD->Riv[i].LeftEle-1 + 2*MD->NumEle]
                                + MD->FluxRiv[i][4]/MD->Ele[MD->Riv[i].LeftEle-1].area;
      }
      if (MD->Riv[i].RightEle > 0)
      {                          
        DY[MD->Riv[i].RightEle-1 + 2*MD->NumEle] = DY[MD->Riv[i].RightEle-1 + 2*MD->NumEle]
                                 + MD->FluxRiv[i][5]/MD->Ele[MD->Riv[i].RightEle-1].area;
      }
    }
  
    for(i=0; i<MD->NumEle; i++)
    { 
      AquiferDepth = MD->Ele[i].zmax - MD->Ele[i].zmin;
      Deficit = AquiferDepth - Y[i+2*MD->NumEle];
      G = 1e-4 + MD->Ele[i].Porosity*(1-pow( 1+pow(MD->Ele[i].Alpha*Deficit , MD->Ele[i].Beta),-(MD->Ele[i].Beta+1)/MD->Ele[i].Beta));
      GI = -pow( 1+pow(MD->Ele[i].Alpha*Deficit , MD->Ele[i].Beta), -(MD->Ele[i].Beta+1)/MD->Ele[i].Beta);
    
      /* for test case 1 only */
      /*
      G = MD->Ele[i].Porosity;
      GI = 0; 
      */
      
      DY[i+2*MD->NumEle] = DY[i+2*MD->NumEle]/G;
      DY[i+MD->NumEle] = GI*DY[i+2*MD->NumEle];
      
      // if there is a source (well) in it
      if(MD->Ele[i].source > 0)
      {
        DY[i+2*MD->NumEle] = DY[i+2*MD->NumEle] - Interpolation(&MD->TSD_Source[MD->Ele[i].source - 1], t)/(MD->Ele[i].Porosity*MD->Ele[i].area);
      }
    
      // check if it is out of bound
      if(Y[i+MD->NumEle]>Deficit && DY[i+MD->NumEle]>0)
      {
        DY[i+MD->NumEle] = 0;
      }
      if(Y[i+MD->NumEle]<0 && DY[i+MD->NumEle]<0)
      {
        DY[i+MD->NumEle] = 0;
      }
    
      if(Y[i+2*MD->NumEle]>AquiferDepth && DY[i+2*MD->NumEle]>0)
      {
        DY[i+2*MD->NumEle] = 0;
      }
      if(Y[i+2*MD->NumEle]<0 && DY[i+2*MD->NumEle]<0)
      {
        DY[i+2*MD->NumEle] = 0;
      }
    }  
  
    break;
    
  case 2:
    
    for(i=0; i<MD->NumEle; i++)
    {
      /* Uncomment if there is no interception storage */
      /* MD->EleNetPrep[i] = Interpolation(&MD->TSD_Prep[MD->Ele[i].prep-1], t); */
      MD->EleVic[i] = Interpolation(&MD->TSD_Inc[MD->Soil[(MD->Ele[i].soil-1)].Inf-1], t);
  
      AquiferDepth = MD->Ele[i].zmax - MD->Ele[i].zmin;
      Deficit = AquiferDepth - Y[i+2*MD->NumEle];

      if(Y[i+MD->NumEle] < Deficit)
      {
        if(Y[i] > 0)
        {
          DY[i] = MD->EleNetPrep[i] - MD->EleVic[i];
          DY[i+MD->NumEle] = MD->EleVic[i];
        }
        else if(MD->EleNetPrep[i] > MD->EleVic[i] && Y[i] <= 0)
        {
          DY[i] = MD->EleNetPrep[i] - MD->EleVic[i];
          DY[i+MD->NumEle] = MD->EleVic[i];
        }
        else if(MD->EleNetPrep[i] < MD->EleVic[i] && Y[i] <= 0 && MD->EleNetPrep[i] > 0)
        {
          DY[i] = 0;
          DY[i+MD->NumEle] = MD->EleNetPrep[i];
        }
        else
        {
          DY[i] = 0;
          DY[i+MD->NumEle] = MD->EleNetPrep[i];
        }  
      }
      else
      {
        DY[i] = MD->EleNetPrep[i];
        DY[i+MD->NumEle] = 0;
      }
      
      for(j=0; j<3; j++)
      {
        DY[i] =  DY[i] - MD->FluxSurf[i][j]/MD->Ele[i].area;
      }
      
      if(Y[i] <= 0 && DY[i] < 0)
      {
        DY[i] = 0;
        DY[i+MD->NumEle] = MD->EleNetPrep[i];
      }
    
      PH = 1 - exp(-MD->Ele[i].Ksat*Deficit);
     
      MD->Recharge[i] = MD->Ele[i].Ksat*(PH - MD->Ele[i].Alpha*Y[i+MD->NumEle])/(1e-7 + MD->Ele[i].Alpha*Deficit - PH);
    
      if(Y[i+MD->NumEle]<0 && MD->Recharge[i] < 0)
      {
        MD->Recharge[i] = 0;
      }
      if(Y[i+2*MD->NumEle]<0 && MD->Recharge[i] > 0)
      {
        MD->Recharge[i] = 0;
      }
    
      DY[i+MD->NumEle] = DY[i+MD->NumEle] + MD->Recharge[i];
      DY[i+MD->NumEle] = DY[i+MD->NumEle]/MD->Ele[i].Porosity;
      
      /* Source check */
      if(Y[i+MD->NumEle]>Deficit && DY[i+MD->NumEle]>0)
      {
        DY[i+MD->NumEle] = 0;
      }
      if(Y[i+MD->NumEle]<0 && DY[i+MD->NumEle]<0)
      {
        DY[i+MD->NumEle] = 0;
      }
    
      DY[i+2*MD->NumEle] = -MD->Recharge[i];
    
      for(j=0; j<3; j++)
      {
        DY[i+2*MD->NumEle] = DY[i+2*MD->NumEle] - MD->FluxSub[i][j]/MD->Ele[i].area;
      }
    }
  
    for(i=0; i<MD->NumRiv; i++)
    {
      if (MD->Riv[i].LeftEle > 0 && MD->Riv[i].RightEle > 0)
      {
        RivPrep = Interpolation(&MD->TSD_Prep[MD->Ele[MD->Riv[i].LeftEle-1].prep-1], t) + Interpolation(&MD->TSD_Prep[MD->Ele[MD->Riv[i].RightEle-1].prep-1], t);
        RivPrep = RivPrep/2;
      }  
      else if (MD->Riv[i].LeftEle > 0 && MD->Riv[i].RightEle == 0)
      {
        RivPrep = Interpolation(&MD->TSD_Prep[MD->Ele[MD->Riv[i].LeftEle-1].prep-1], t);
      }
      else if (MD->Riv[i].LeftEle == 0 && MD->Riv[i].RightEle > 0)  
      {
        RivPrep = Interpolation(&MD->TSD_Prep[MD->Ele[MD->Riv[i].RightEle-1].prep-1], t);
      }
      else
      {  
        /* for test case 3 only */
        /*RivPrep = Interpolation(&MD->TSD_Prep[0], t);*/
        RivPrep = 0;
      }
      
      DY[i+3*MD->NumEle] = RivPrep + MD->FluxRiv[i][0] - MD->FluxRiv[i][1];
      DY[i+3*MD->NumEle] = DY[i+3*MD->NumEle] - MD->FluxRiv[i][2] - MD->FluxRiv[i][3];
      DY[i+3*MD->NumEle] = DY[i+3*MD->NumEle] - MD->FluxRiv[i][4] - MD->FluxRiv[i][5];
      DY[i+3*MD->NumEle] = DY[i+3*MD->NumEle]/(MD->Riv[i].Length*MD->Riv_Shape[MD->Riv[i].shape-1].width);
    
      if (MD->Riv[i].LeftEle > 0)
      {
        DY[MD->Riv[i].LeftEle-1 + 2*MD->NumEle] = DY[MD->Riv[i].LeftEle-1 + 2*MD->NumEle] + MD->FluxRiv[i][4]/MD->Ele[MD->Riv[i].LeftEle-1].area;
      }
      
      if (MD->Riv[i].RightEle > 0)
      {                         
        DY[MD->Riv[i].RightEle-1 + 2*MD->NumEle] = DY[MD->Riv[i].RightEle-1 + 2*MD->NumEle] + MD->FluxRiv[i][5]/MD->Ele[MD->Riv[i].RightEle-1].area;
      }                           
    }
  
    for(i=0; i<MD->NumEle; i++)
    {
      
      /* if there is a source (well) in it */
      if(MD->Ele[i].source > 0)
      {
        DY[i+2*MD->NumEle] = DY[i+2*MD->NumEle] - Interpolation(&MD->TSD_Source[MD->Ele[i].source - 1], t)/MD->Ele[i].area;
      }
      
      DY[i+2*MD->NumEle] = DY[i+2*MD->NumEle]/MD->Ele[i].Porosity;
    
      if(Y[i+2*MD->NumEle]>AquiferDepth && DY[i+2*MD->NumEle]>0)
      {
        DY[i+2*MD->NumEle] = 0;
      }
      if(Y[i+2*MD->NumEle]<0 && DY[i+2*MD->NumEle]<0)
      {
        DY[i+2*MD->NumEle] = 0;
      }
    }  
  
    break;
    
  default:
  
    printf("Fatal Error: Unsaturated Layer Mode Type Is Wrong!");
    exit(1);
  
  }
}
double Viscous_Component_YY(double*** velocity_x, double*** velocity_y,
                            double*** velocity_z,
                            double*** temperature, double Reynolds,
                            double dx, double* dy, double dz,
                            int i, int j, int k)
{

  double derivative_yx[3][2],derivative_yz[3][2],derivative_yy[2],
    viscous_terms[2], viscosity[2], dy_total;



  //Calculation of the d/dy(dv/dy)
  //j-1/2
  dy_total= dy[j]+dy[j-1];
  derivative_yy[0] = 
    Derivative(velocity_y[k][j][i],velocity_y[k][j-1][i],
	       dy_total,1);

  //j+1/2
  dy_total= dy[j+1]+dy[j];
  derivative_yy[1] = 
    Derivative(velocity_y[k][j+1][i], velocity_y[k][j][i],
	       dy_total,1);


  //Calculation of the d/dy(du/dx)
  double sum[3];
  for (int vi=0; vi<3; vi++)
    {

      derivative_yx[vi][0]=4./3.*Derivative(velocity_x[k][j+vi-1][i+1],
                                            velocity_x[k][j+vi-1][i-1],
                                            dx,2);

      derivative_yx[vi][1]=-1./3.*Derivative(velocity_x[k][j+vi-1][i+2],
                                             velocity_x[k][j+vi-1][i-2],
                                             dx,4);
      sum[vi]=0.;
      for (int vj=0; vj<2; vj++)
        {
          sum[vi] += derivative_yx[vi][vj];
        }

    }

  double total_derivative_x[2];
  for (int vi=0; vi<2; vi++)
    {
      //interpolation to obtain the derivative at the desired point
      total_derivative_x[vi] = Interpolation_Y(sum[vi],dy[j-1+vi],
                                               sum[vi+1],dy[j+vi]);
    }



  // Calculation of the d/dy(dw/dz)

  for (int vi=0; vi<3; vi++)
    {
      derivative_yz[vi][0]=4./3.*Derivative(velocity_z[k+1][j+vi-1][i],
                                            velocity_z[k-1][j+vi-1][i],
                                            dz,2);

      derivative_yz[vi][1]=-1./3.*Derivative(velocity_z[k+2][j+vi-1][i],
                                             velocity_z[k-2][j+vi-1][i],
                                             dz,4);

      sum[vi]=0.;
      for (int vj=0; vj<2; vj++)
        {
          sum[vi] += derivative_yz[vi][vj];
        }
    }


  //interpolation to obtain the derivative at the desired point
  double total_derivative_z[2];
  for (int vi=0; vi<2; vi++)
    {

      total_derivative_z[vi] = Interpolation_Y(sum[vi],dy[j-1+vi],
                                               sum[vi+1],dy[j+vi]);
    }

  //Computing the viscosities.
  for (int vi=-1, vj=0; vi<1; vi++, vj++)
    {
      viscosity[vj]=
        Viscosity_Calculator(Interpolation(temperature[k][j+vi][i],
                                           temperature[k][j+vi+1][i]));
    }



  //computing the viscous tensors
  for (int vi=0; vi<2; vi++)
    {
      viscous_terms[vi] =viscosity[vi]*(4./3*derivative_yy[vi]
                                        -2./3.*(total_derivative_x[vi]+
                                                total_derivative_z[vi]) );
    }


  // cout<<"yy"<<endl;
  //     cout<<total_derivative_x[1]-total_derivative_x[0]<<endl;
  //     cout<<total_derivative_z[1]-total_derivative_z[0]<<endl;


  /* Summing the X-component of the Viscous Term of the Y-Momentum equation*/

  dy_total=2.*dy[j];
  double viscous_term =
    1./Reynolds*(Derivative(viscous_terms[1],
                            viscous_terms[0],
                            dy_total,1));

  return viscous_term;
}