Ejemplo n.º 1
0
void MulMat (real *a, real *b, real *c, int n)
{
  int i, j, k;

  for (i = 0; i < n; i ++) {
    for (j = 0; j < n; j ++) {
      Mn (a, i, j) = 0.;
      for (k = 0; k < n; k ++) Mn (a, i, j) += Mn (b, i, k) * Mn (c, k, j);
    }
  }
}
Ejemplo n.º 2
0
	void compute() {
		for (int m=-level; m<=level; ++m) {
			for (int n=-level; n<=level; ++n) {
				Float uVal = u(level, m, n), vVal = v(level, m, n), wVal = w(level, m, n);
				Mn(m+level, n+level) =
					  (uVal != 0 ? (uVal * U(level, m, n)) : (Float) 0)
					+ (vVal != 0 ? (vVal * V(level, m, n)) : (Float) 0)
					+ (wVal != 0 ? (wVal * W(level, m, n)) : (Float) 0);
			}
		}
	}
Ejemplo n.º 3
0
double RkPdf::MfRk(const double& x, const double& tau, const double& dm){
  const double r_ckak = ck/ak;
  const double inv_ak = 1.0/ak;
  const double ndmtau = r_ckak*dm*tau;
  const double fact = 1.0/(1.0+ndmtau*ndmtau);
  double Li = 0.0;
  if(x<0.0){
    const double ndm  = dm/(ak-ck);
    const double ntau = tau*(ak-ck);
    Li = inv_ak*fact*(Mn(x,ntau,ndm)+ndmtau*An(x,ntau,ndm));
  }else{
    const double ndm  = dm/(ak+ck);
    const double ntau = tau*(ak+ck);
    Li = inv_ak*fact*(Mp(x,ntau,ndm)+ndmtau*Ap(x,ntau,ndm));
  }
  return Li;
}
Ejemplo n.º 4
0
/* последовательное применение полуочистителей Bn, Bn / 2, …, B2 сортирует произвольную
битоническую последовательность.Эту операцию называют битоническим слиянием и обозначают Mn */
void Mn(long *elements, int k, int direction,int myrank,int nrank,int shift) {
	MPI_Status status; 
	Bn(elements, k, direction);
	int child = myrank + shift;
	if (k>0 && child < nrank) {
		/* Запрашиваем первый свободный процесс */
		/* Поскольку здесь не реализован диспечер задач, то это будет следующий по номеру */
		shift <<= 1;
		/* Отдаём половину массива на обработку этому процессу  */
		MPI_Send(&k, 1, MPI_INT, child, DATA_TAG, MPI_COMM_WORLD); 
		MPI_Send(&direction, 1, MPI_INT, child, DATA_TAG, MPI_COMM_WORLD);
		MPI_Send(&elements[1<<k], 1<<k, MPI_LONG, child, DATA_TAG, MPI_COMM_WORLD); 
		MPI_Send(&shift, 1, MPI_INT, child, DATA_TAG, MPI_COMM_WORLD); 

		/* Сами продолжим обработку */
		Mn(elements,k-1,direction,myrank,nrank,shift);

		/* Получим обработанные элементы обратно */
		MPI_Recv(&elements[1<<k], 1<<k, MPI_LONG, child, DATA_TAG, MPI_COMM_WORLD, &status);
		shift >>= 1;
	} else if (k>0) {
Ejemplo n.º 5
0
void
MovementSolute::solute (const Soil& soil, const SoilWater& soil_water,
                        const double J_above, Chemical& chemical, 
                        const double dt,
                        const Scope& scope, Treelog& msg)
{
  daisy_assert (std::isfinite (J_above));
  const size_t cell_size = geometry ().cell_size ();
  const size_t edge_size = geometry ().edge_size ();

  // Source term transfered from secondary to primary domain.
  std::vector<double> S_extra (cell_size, 0.0);

  // Divide top solute flux according to water.
  std::map<size_t, double> J_tertiary;
  std::map<size_t, double> J_secondary; 
  std::map<size_t, double> J_primary;

  if (J_above > 0.0)
    // Outgoing, divide according to content in primary domain only.
    divide_top_outgoing (geometry (), chemical, J_above, 
                         J_primary, J_secondary, J_tertiary);
  else if (J_above < 0.0)
    // Incomming, divide according to all incomming water.
    divide_top_incomming (geometry (), soil_water, J_above, 
                          J_primary, J_secondary, J_tertiary);
  else
    // No flux.
    zero_top (geometry (), J_primary, J_secondary, J_tertiary);

  // Check result.
  {
    const std::vector<size_t>& edge_above 
      = geometry ().cell_edges (Geometry::cell_above);
    const size_t edge_above_size = edge_above.size ();
    double J_sum = 0.0;
    for (size_t i = 0; i < edge_above_size; i++)
      {
        const size_t edge = edge_above[i];
        const double in_sign 
          = geometry ().cell_is_internal (geometry ().edge_to (edge)) 
          ? 1.0 : -1.0;
        const double area = geometry ().edge_area (edge); // [cm^2 S]
        const double J_edge       // [g/cm^2 S/h]
          = J_tertiary[edge] + J_secondary[edge] + J_primary[edge];
        J_sum += in_sign * J_edge * area; // [g/h]
        if (in_sign * J_tertiary[edge] < 0.0)
          {
            std::ostringstream tmp;
            tmp << "J_tertiary[" << edge << "] = " << J_tertiary[edge]
                << ", in_sign = " << in_sign << ", J_above = " << J_above;
            msg.bug (tmp.str ());
          }
        if (in_sign * J_secondary[edge] < 0.0)
          {
            std::ostringstream tmp;
            tmp << "J_secondary[" << edge << "] = " << J_secondary[edge]
                << ", in_sign = " << in_sign << ", J_above = " << J_above;
            msg.bug (tmp.str ());
          }
      }
    J_sum /= geometry ().surface_area (); // [g/cm^2 S/h]
    daisy_approximate (-J_above, J_sum);
  }

  // We set a fixed concentration below lower boundary, if specified.
  std::map<size_t, double> C_border;

  const double C_below = chemical.C_below ();
  if (C_below >= 0.0)
    {
      const std::vector<size_t>& edge_below 
        = geometry ().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];
          C_border[edge] = C_below;
        }
    }

  // Tertiary transport.
  tertiary->solute (geometry (), soil_water, J_tertiary, dt, chemical, msg);

  // Fully adsorbed.
  if (chemical.adsorption ().full ())
    {
      static const symbol solid_name ("immobile transport");
      Treelog::Open nest (msg, solid_name);
      if (!iszero (J_above))
        {
          std::ostringstream tmp;
          tmp << "J_above = " << J_above << ", expected 0 for full sorbtion";
          msg.error (tmp.str ());
        }

      // Secondary "transport".
      std::vector<double> J2 (edge_size, 0.0); // Flux delivered by flow.
      std::vector<double> Mn (cell_size); // New content.
      for (size_t c = 0; c < cell_size; c++)
        {
          Mn[c] = chemical.M_secondary (c) + chemical.S_secondary (c) * dt;
          if (Mn[c] < 0.0)
            {
              S_extra[c] = Mn[c] / dt;
              Mn[c] = 0.0;
            }
          else
            S_extra[c] = 0.0;
        }
      chemical.set_secondary (soil, soil_water, Mn, J2);

      // Primary "transport".
      primary_transport (geometry (), soil, soil_water,
                         *matrix_solid, sink_sorbed, 0, J_primary, C_border,
                         chemical, S_extra, dt, scope, msg);
      return;
    }

  // Secondary transport activated.
  secondary_transport (geometry (), soil, soil_water, J_secondary, C_border,
                       chemical, S_extra, dt, scope, msg);

  // Solute primary transport.
  for (size_t transport_iteration = 0; 
       transport_iteration < 2; 
       transport_iteration++)
    for (size_t i = 0; i < matrix_solute.size (); i++)
      {
        solute_attempt (i);
        static const symbol solute_name ("solute");
        Treelog::Open nest (msg, solute_name, i, matrix_solute[i]->objid);
        try
          {
            primary_transport (geometry (), soil, soil_water, 
                               *matrix_solute[i], sink_sorbed, 
                               transport_iteration,
                               J_primary, C_border,
                               chemical, S_extra, dt, scope, msg);
            if (i > 0)
              msg.debug ("Succeeded");
            return;
          }
        catch (const char* error)
          {
            msg.debug (std::string ("Solute problem: ") + error);
          }
        catch (const std::string& error)
          {
            msg.debug(std::string ("Solute trouble: ") + error);
          }
        solute_failure (i);
      }
  throw "Matrix solute transport failed";
}
Ejemplo n.º 6
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);
}