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"); } } }