void 
UZRectMollerup::lowerboundary (const GeometryRect& geo,
			       const Groundwater& groundwater,
			       const std::vector<bool>& active_lysimeter,
			       const ublas::vector<double>& h,
			       const ublas::vector<double>& Kedge,
			       ublas::vector<double>& dq,
			       ublas::banded_matrix<double>& Dm_mat, 
			       ublas::vector<double>& Dm_vec, 
			       ublas::vector<double>& Gm, 
			       ublas::vector<double>& B, Treelog& msg)
{
  const std::vector<size_t>& edge_below = geo.cell_edges (Geometry::cell_below);
  const size_t edge_below_size = edge_below.size ();

  for (size_t i = 0; i < edge_below_size; i++)
    {
      const size_t edge = edge_below[i];
      const int cell = geo.edge_other (edge, Geometry::cell_below);
      daisy_assert (geo.cell_is_internal (cell));
      const double in_sign 
        = geo.cell_is_internal (geo.edge_to (edge)) ? 1.0 : -1.0;
      daisy_assert (in_sign > 0);
      const double area = geo.edge_area (edge);
      const double sin_angle = geo.edge_sin_angle (edge);

      switch (groundwater.bottom_type ())
        {
        case Groundwater::free_drainage:
          {
            const double sin_angle = geo.edge_sin_angle (edge);
            //const double flux = -in_sign * sin_angle * K (cell) * area; //old
            const double flux = -in_sign * sin_angle * Kedge (edge);
            Neumann (edge, cell, area, in_sign, flux, dq, B);
          }
          break;
          
        case Groundwater::forced_flux:
          {
            const double flux = groundwater.q_bottom (edge);
            Neumann (edge, cell, area, in_sign, flux, dq, B);
          }
          break;
        
        case Groundwater::pressure:
          {
            const double value = -Kedge (edge) * geo.edge_area_per_length (edge);
            const double pressure =  groundwater.table () - geo.zplus (cell);
            
            Dirichlet (edge, cell, area, in_sign, sin_angle, 
                       Kedge (edge), 
                       h (cell),
                       value, pressure,
                       dq, Dm_mat, Dm_vec, Gm);
          }
          break;

        case Groundwater::lysimeter:
          {
            if (active_lysimeter[cell])
              {
                //Neumann - not so good
                //const double flux = -in_sign * sin_angle * K (cell);
                //Neumann (edge, cell, area, in_sign, flux, dq, B);
                //Dirichlet - better
                const double value = -Kedge (edge) * geo.edge_area_per_length (edge);
                const double pressure =  0.0;
                Dirichlet (edge, cell, area, in_sign, sin_angle,
                           Kedge (edge), 
                           h (cell),
                           value, pressure, dq, Dm_mat, Dm_vec, Gm);
              }
            else
              // Indsat af [email protected] Fri Jul 10 11:21:14     2009
              {
                const double flux = 0.0;
                Neumann (edge, cell, area, in_sign, flux, dq, B);
              }

          }
          break;
          
        default:
          daisy_panic ("Unknown groundwater type");
        }
    }
}
void 
UZRectMollerup::upperboundary (const GeometryRect& geo,
                               const Soil& soil,
                               const ublas::vector<double>& T,
			       const Surface& surface,
                               std::vector<top_state>& state,
			       const ublas::vector<double>& remaining_water,
			       const ublas::vector<double>& h,
			       const ublas::vector<double>& Kedge,
			       ublas::vector<double>& dq,
			       ublas::banded_matrix<double>& Dm_mat, 
			       ublas::vector<double>& Dm_vec, 
			       ublas::vector<double>& Gm, 
			       ublas::vector<double>& B,
			       const double ddt,
			       const int debug,
                               Treelog& msg, const double BIG_DT)
{
  const std::vector<size_t>& edge_above = geo.cell_edges (Geometry::cell_above);
  const size_t edge_above_size = edge_above.size ();

  for (size_t i = 0; i < edge_above_size; i++)
    {
      const size_t edge = edge_above[i];
      const int cell = geo.edge_other (edge, Geometry::cell_above);
      daisy_assert (geo.cell_is_internal (cell));
      const double in_sign 
        = geo.cell_is_internal (geo.edge_to (edge)) ? 1.0 : -1.0;
      daisy_assert (in_sign < 0);
      const double area = geo.edge_area (edge);
      const double sin_angle = geo.edge_sin_angle (edge);

      switch (surface.top_type (geo, edge))
	{
	case Surface::forced_flux: 
          {
            const double flux = -surface.q_top (geo, edge, BIG_DT);
            Neumann (edge, cell, area, in_sign, flux, dq, B);
          }
	  break;
	case Surface::forced_pressure:
          {
            const double value = -Kedge (edge) * geo.edge_area_per_length (edge);
            const double pressure = surface.h_top (geo, edge);
            Dirichlet (edge, cell, area, in_sign, sin_angle, 
                       Kedge (edge), 
                       h (cell), value, pressure, dq, Dm_mat, Dm_vec, Gm);
          }
	  break;
	case Surface::limited_water:
          {
            const double h_top = remaining_water (i);

            // We pretend that the surface is particlaly saturated.
            const double K_sat = soil.K (cell, 0.0, 0.0, T (cell));
            const double K_cell = Kedge (edge);
            const double K_edge = 0.5 * (K_cell + K_sat);
            
            const double dz = geo.edge_length (edge);
            daisy_assert (approximate (dz, -geo.cell_z (cell)));
            double q_in_avail = h_top / ddt;
            const double q_in_pot = K_edge * (h_top - h (cell) + dz) / dz;
            // Decide type.
            bool is_flux = h_top <= 0.0 || q_in_pot > q_in_avail;

            if (is_flux)
              {
                state[i] = top_flux;
                Neumann (edge, cell, area, in_sign, q_in_avail, dq, B);
              }
            else			// Pressure
              {
                state[i] = top_pressure;
                if (debug > 0 && q_in_pot < 0.0)
                  {
                    std::ostringstream tmp;
                    tmp << "q_in_pot = " << q_in_pot << ", q_avail = " 
                        << q_in_avail << ", h_top = " << h_top 
                        << ", h (cell) = " << h (cell) 
                        << " K (edge) = " << Kedge (edge) 
                        << ", K_sat = " << K_sat << ", K_edge = "
                        << K_edge <<", dz = " << dz << ", ddt = " << ddt
                        << ", is_flux = " << is_flux << "\n";
                    msg.message (tmp.str ());
                  }
                const double value = -K_edge * geo.edge_area_per_length (edge);
                const double pressure = h_top;
                Dirichlet (edge, cell, area, in_sign, sin_angle, 
                           K_edge, h (cell),
                           value, pressure, dq, Dm_mat, Dm_vec, Gm);
              }
            if (debug == 3)
              {
                std::ostringstream tmp;
                tmp << "edge = " << edge << ", K_edge = " << K_edge 
                    << ", h_top = "
                    << h_top << ", dz = " << dz << ", q_avail = " << q_in_avail
                    << ", q_pot = " << q_in_pot << ", is_flux = " << is_flux;
                msg.message (tmp.str ());
              }
          }
	  break;
	case Surface::soil:
	  throw "Don't know how to handle this surface type";
	default:
	  daisy_panic ("Unknown surface type");
	}
    }
}
Example #3
0
void makeFlux(FVMesh2D &m, FVVect<double> &phi, FVVect< FVPoint2D<double> > &u,
              FVVect<double> &Vd,FVVect<double> &Vn,
              FVVect<double> &F,Parameter &para) {

    //FVEdge2D *ptr_e;
    double leftPhi,rightPhi,normal_velocity;
    FVPoint2D<double> BB;
    m.beginEdge();
    size_t edges = m.getNbEdge();

    //avoid getting static values in loops
    const unsigned int dirCode = para.getUnsigned("DirichletCode");
    const unsigned int neuCode = para.getUnsigned("NeumannCode");
    const double difusion = getDiffusion(NULL,para);        
    
    
    #pragma omp parallel for private(normal_velocity,leftPhi,rightPhi)
    for(size_t i = 0; i < edges; i++) {

        FVEdge2D *ptr_e;
        //ptr_e = m.nextEdge();
        ptr_e = m.getEdge(i);
        
        normal_velocity = Dot(u[ptr_e->label-1],ptr_e->normal);  
        leftPhi = phi[ptr_e->leftCell->label-1];
        
        if(ptr_e->rightCell) {
            // edge has the code = 0    
            
            rightPhi = phi[ptr_e->rightCell->label-1];
            // compute the convection contribution
            if(normal_velocity<0) {
              
                F[ptr_e->label-1] = normal_velocity*rightPhi;
            }
            else {
              
                F[ptr_e->label-1] = normal_velocity*leftPhi;   
            }
            // compute the diffusive contribution
            BB=ptr_e->rightCell->centroid - ptr_e->leftCell->centroid;                        
            
            F[ptr_e->label-1] -= difusion*(rightPhi-leftPhi)/Norm(BB); 

         }
          else {
            //  we are on the boundary
            if(ptr_e->code == dirCode) {                
                // we have a Dirichlet condition                
                rightPhi = Dirichlet(ptr_e->centroid,para);
                // compute the convection contribution
                if(normal_velocity<0) {
                    
                    F[ptr_e->label-1] = normal_velocity*rightPhi;
                }
                else {
                    
                    F[ptr_e->label-1] = normal_velocity*leftPhi;   
                }
                // compute the diffusive contribution                
                BB = ptr_e->centroid - ptr_e->leftCell->centroid;
               
                F[ptr_e->label-1] -= difusion*(rightPhi-leftPhi)/Norm(BB); 
            }
             
            if(ptr_e->code == neuCode) {
                // we have a Neumann condition      
                
                F[ptr_e->label-1] = Neumann(ptr_e->centroid,para);
            }
        }

        // here, we have all the data to compute the flux    
        
        F[ptr_e->label-1] *= ptr_e->length;
    }
}