Exemplo n.º 1
0
void
MovementSolute::divide_top_incomming (const Geometry& geo, 
                                      const SoilWater& soil_water, 
                                      const double J_above, // [g/cm^2/h]
                                      std::map<size_t, double>& J_primary,
                                      std::map<size_t, double>& J_secondary,
                                      std::map<size_t, double>& J_tertiary)
{
  daisy_assert (J_above < 0.0); // Negative upward flux.
  const std::vector<size_t>& edge_above 
    = geo.cell_edges (Geometry::cell_above);
  const size_t edge_above_size = edge_above.size ();
  double total_water_in = 0.0;  // [cm^3 W/h]
  double total_area = 0.0;      // [cm^2 S]

  // Find incomming water in all domain.
  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 area = geo.edge_area (edge); // [cm^2 S]
      total_area += area;
      const double in_sign 
        = geo.cell_is_internal (geo.edge_to (edge)) 
        ? 1.0
        : -1.0;
      daisy_assert (in_sign < 0);

      // Tertiary domain.
      const double q_tertiary = soil_water.q_tertiary (edge);
      daisy_assert (std::isfinite (q_tertiary));
      const double tertiary_in = q_tertiary * in_sign; // [cm^3 W/cm^2 S/h]
      if (tertiary_in > 0)
        {
          total_water_in += tertiary_in * area;
          J_tertiary[edge] = q_tertiary; // [cm^3 W/cm^2 S/h]
        }
      else
        J_tertiary[edge] = 0.0;

      // Secondary domain.
      const double q_secondary = soil_water.q_secondary (edge);
      const double secondary_in = q_secondary * in_sign; // [cm^3 W/cm^2 S/h]
      if (secondary_in > 0)
        {
          total_water_in += secondary_in * area;
          J_secondary[edge] = q_secondary; // [cm^3 W/cm^2 S/h]
          
        }
      else
        J_secondary[edge] = 0.0;

      // Primary domain.
      const double q_primary = soil_water.q_primary (edge);
      const double primary_in = q_primary * in_sign; // [cm^3 W/cm^2 S/h]
      if (primary_in > 0)
        {
          total_water_in += primary_in * area;
          J_primary[edge] = q_primary; // [cm^3 W/cm^2 S/h]
        }
      else
        J_primary[edge] = 0.0;
    }
  daisy_approximate (total_area, geo.surface_area ());

  if (total_water_in > 1e-9 * total_area)
    // Scale with incomming solute.
    {
      // [g/cm^3 W] = [g/cm^2 S/h] * [cm^2 S] / [cm^3 W/h] 
      const double C_above = -J_above * total_area / total_water_in;
      daisy_assert (std::isfinite (C_above));
      for (size_t i = 0; i < edge_above_size; i++)
        {
          const size_t edge = edge_above[i];
          // [g/cm^2 S/h] = [cm^3 W/cm^2 S/h] * [g/cm^3 W]
          J_tertiary[edge] *= C_above;
          J_secondary[edge] *= C_above;
          J_primary[edge] *= C_above;
        }
    }
  else
    {
      daisy_assert (total_water_in >= 0.0);
      for (size_t i = 0; i < edge_above_size; i++)
        {
          const size_t edge = edge_above[i];
          const double in_sign 
            = geo.cell_is_internal (geo.edge_to (edge)) ? 1.0 : -1.0;
          J_tertiary[edge] = 0.0;
          J_secondary[edge] = 0.0;
          J_primary[edge] = -J_above * in_sign;
        }
    }
}
Exemplo n.º 2
0
void
MovementSolute::secondary_transport (const Geometry& geo,
                                     const Soil& soil,
                                     const SoilWater& soil_water,
                                     const std::map<size_t, double>& J_forced,
                                     const std::map<size_t, double>& C_border,
                                     Chemical& solute, 
                                     std::vector<double>& S_extra,
                                     const double dt,
                                     const Scope& scope, Treelog& msg)
{ 
  // Edges.
  const size_t edge_size = geo.edge_size ();

  std::vector<double> q (edge_size); // Water flux [cm].
  std::vector<double> J (edge_size, 0.0); // Flux delivered by flow.

    for (size_t e = 0; e < edge_size; e++)
    {
      q[e] = soil_water.q_secondary (e);
      daisy_assert (std::isfinite (q[e]));
    }

  // Cells.
  const size_t cell_size = geo.cell_size ();

  std::vector<double> Theta_old (cell_size); // Water content at start...
  std::vector<double> Theta_new (cell_size); // ...and end of timestep.
  std::vector<double> A (cell_size); // Content ignored by flow.
  std::vector<double> Mf (cell_size); // Content given to flow.
  std::vector<double> S (cell_size); // Source given to flow.

  for (size_t c = 0; c < cell_size; c++)
    {
      Theta_old[c] = soil_water.Theta_secondary_old (c);
      daisy_assert (Theta_old[c] >= 0.0);
      Theta_new[c] = soil_water.Theta_secondary (c);
      daisy_assert (Theta_new[c] >= 0.0);
      const double source = solute.S_secondary (c);
      daisy_assert (std::isfinite (source));
      Mf[c] = solute.C_secondary (c) * Theta_old[c];
      daisy_assert (Mf[c] >= 0.0);
      A[c] = solute.M_secondary (c) - Mf[c];
      daisy_assert (std::isfinite (A[c]));
      if (Theta_new[c] > 0)
        {
          if (Theta_old[c] > 0)
            // Secondary water fully active.
            S[c] = source;
          else if (source > 0.0)
            // Fresh water and source.
            S[c] = source;
          else
            // Fresh water and sink.
            S[c] = 0.0;
        }
      else
        // No secondary water at end of timestep.
        S[c] = 0.0;
      
      // Put any remaining source in S_extra.
      S_extra[c] += source - S[c];
      daisy_assert (std::isfinite (S_extra[c]));
    }
  
  // Flow.
  secondary_flow (geo, Theta_old, Theta_new, q, solute.objid, 
                  S, J_forced, C_border, Mf, J, dt, msg);

  // Check fluxes.
  for (size_t e = 0; e < edge_size; e++)
    daisy_assert (std::isfinite (J[e]));


  // Negative content should be handled by primary transport.
  std::vector<double> Mn (cell_size); // New content.
  std::vector<double> C (cell_size);
  for (size_t c = 0; c < cell_size; c++)
    {
      Mn[c] = A[c] + Mf[c] + S_extra[c] * dt;
      if (Mn[c] < 0.0 || Theta_new[c] < 1e-6)
        {
          S_extra[c] = Mn[c] / dt;
          Mn[c] = 0.0;
        }
      else
        S_extra[c] = 0.0;

      daisy_assert (std::isfinite (S_extra[c]));
    }
  solute.set_secondary (soil, soil_water, Mn, J);
}