Esempio n. 1
0
result_t
vec_cast(const source_t& source, typename detail::enable_if_c<!has_ptr_or_ref<result_t>::value>::type* = NULL){
	return initial_values(source);
}
// NB : matrix is passed in Column-Major storage. 
void
lod_cn_travelling_wave(double* const inout_matrix,
                       const int space_nb_x,
                       const int space_nb_y,
                       const double final_time,
                       const double tau,
                       const double eps)
{
  double h_x = 1./((double)space_nb_x-1.), h_y = 1./((double)space_nb_y-1.);
  Eigen::VectorXd x_border, y_border, x(space_nb_x), y(space_nb_y);
  Eigen::MatrixXd values, after_x, after_y, after_reaction;
  Eigen::SparseMatrix<double> operator_x, operator_y, laplace_x, unit_matrix_x, laplace_y, unit_matrix_y;

  // Boundaries.
  x_border.setLinSpaced(space_nb_x, 0., 1.);
  y_border.setLinSpaced(space_nb_y, 0., 1.);
  // Initial values.
  initial_values(values, x_border, y_border, eps);
  // Operators initialization;
  laplace_operator_1d(laplace_x, space_nb_x);
  identity_operator(unit_matrix_x, space_nb_x);
  laplace_operator_1d(laplace_y, space_nb_y);
  identity_operator(unit_matrix_y, space_nb_y);
  space_operator(operator_x, laplace_x, (tau*eps)/(h_x*h_x), unit_matrix_x);
  space_operator(operator_y, laplace_y, (tau*eps)/(h_y*h_y), unit_matrix_y);
#ifdef DEBUG_LOD_CN
debug_print("init values", values, 5, 5);
debug_print("laplace x", laplace_x, 5, 5);
debug_print("I x", unit_matrix_x, 5, 5);
debug_print("laplace y", laplace_y, 5, 5);
debug_print("I y", unit_matrix_y, 5, 5);
debug_print("Op x", operator_x, 5, 5);
debug_print("Op y", operator_y, 5, 5);
#endif

  double time = 0.;
  const double tcoeff = 1.;
  while (time < final_time)
  {
    // Step in x direction.
    // NB. Operators x and y are hermitian, so that we can commute them.
    // Apply an operator in x direction.
#ifdef DEBUG_LOD_CN
debug_print("values", values, 5, 5);
#endif
    after_x = values*operator_x;
    bc_x(y, y_border, time, 0., eps);
    after_x.col(0) = y*tcoeff;
    bc_x(y, y_border, time, 1., eps);
    after_x.col(space_nb_x-1) = y*tcoeff;
#ifdef DEBUG_LOD_CN
debug_print("after_x", after_x, 5, 5);
#endif
    // Apply an operator in y direction.
    after_y = operator_y*values;
    bc_y(x, x_border, time, 0., eps);
    after_y.row(0) = x.transpose()*tcoeff;
    bc_y(x, x_border, time, 1., eps);
    after_y.row(space_nb_y-1) = x.transpose()*tcoeff;
#ifdef DEBUG_LOD_CN
debug_print("after_y", after_y, 5, 5);
#endif
    // Apply the reaction operator.
    auto transform = ::boost::bind(reaction_operator, _1, tau/eps);
    after_reaction = after_y+after_y.unaryExpr(transform); 
#ifdef DEBUG_LOD_CN
debug_print("after_reaction", after_reaction, 5, 5);
#endif
    // Time advance.
    time += tau;
    // Second application of an operator in y direction.
    after_y = operator_y*after_reaction;
    bc_y(x, x_border, time, 0., eps);
    after_y.row(0) = x.transpose()*tcoeff;
    bc_y(x, x_border, time, 1., eps);
    after_y.row(space_nb_y-1) = x.transpose()*tcoeff;
#ifdef DEBUG_LOD_CN
debug_print("after_y", after_y, 5, 5);
#endif
    // Second application of an operator in x direction.
    values = after_y*operator_x;
    bc_x(y, y_border, time, 0., eps);
    values.col(0) = y*tcoeff;
    bc_x(y, y_border, time, 1., eps);
    values.col(space_nb_x-1) = y*tcoeff;
  }
  // Copy to the return value.
  memcpy(inout_matrix, values.data(), space_nb_x*space_nb_y*sizeof(double));
}