Exemple #1
0
void 
UZRectConst::tick (const GeometryRect& geo, const std::vector<size_t>&,
                   const Soil&, 
                   SoilWater& soil_water, const SoilHeat&,
                   const Surface&, const Groundwater&, 
                   const double, Treelog&)

{
  const size_t edge_size = geo.edge_size (); // number of edges 

  for (size_t edge = 0; edge != edge_size; ++edge) 
    {
      const double sin_angle = geo.edge_sin_angle (edge);
      const double cos_angle = geo.edge_cos_angle (edge);
      const double q = q_z * sin_angle + q_x * cos_angle;
      soil_water.set_flux (edge, q);
    }
}
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");
	}
    }
}
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");
        }
    }
}