Example #1
0
	expression_node operator() (const binary_operation_node& node) const
	{
		ast_evaluator eval;
		binary_op_evaluator bin_op_eval_visitor(node.op);
		expression_node eval_lhs(eval(node.lhs)), eval_rhs(eval(node.rhs));
		return boost::apply_visitor(bin_op_eval_visitor, eval_lhs, eval_rhs);
	}
static int evaluate_residual(void* context, real_t t, real_t* x, real_t* R)
{
  START_FUNCTION_TIMER();
  euler_ode_t* integ = context;
  int status = eval_rhs(integ, t, x, R);
  if (status == 0)
  {
    for (int i = 0; i < integ->num_local_values; ++i)
      R[i] = x[i] - integ->x_old[i] - integ->dt * R[i];
  }
  STOP_FUNCTION_TIMER();
  return status;
}
static bool euler_step(void* context, real_t max_dt, real_t* t, real_t* x)
{
  START_FUNCTION_TIMER();
  euler_ode_t* integ = context;
  integ->dt = max_dt;
  real_t theta = integ->theta;
  int N_local = integ->num_local_values;

  if (theta == 0.0)
  {
    // No implicitness here! Just compute the RHS and mash it into 
    // our solution.

    // Copy the solution into place.
    memcpy(integ->x_new, x, sizeof(real_t) * N_local);

    int status = eval_rhs(integ, *t, integ->x_new, integ->f1);
    if (status != 0)
    {
      log_debug("euler_ode_integrator: explicit call to RHS failed.");
      STOP_FUNCTION_TIMER();
      return false;
    }
    for (int i = 0; i < N_local; ++i)
      x[i] += max_dt * integ->f1[i];
    *t += max_dt;
    STOP_FUNCTION_TIMER();
    return true;
  }
  else
  {
    real_t dt = max_dt;

    // Copy the solution into place.
    memcpy(integ->x_new, x, sizeof(real_t) * N_local);

    // Compute the right-hand function at t.
    real_t t1 = *t;
    int status = eval_rhs(integ, t1, integ->x_new, integ->f1);
    if (status != 0) 
    {
      log_debug("euler_ode_integrator: implicit call to RHS at t failed.");
      STOP_FUNCTION_TIMER();
      return false;
    }

    // Okay, let's do this iteration thing.
    bool converged = false;
    for (int i = 0; i < integ->max_iters; ++i)
    {
      // Copy our latest iterate into our previous one.
      memcpy(integ->x_old, integ->x_new, sizeof(real_t) * N_local);

      // Compute the right-hand function at t + dt.
      real_t t2 = t1 + dt;
      status = eval_rhs(integ, t2, integ->x_new, integ->f2);
      if (status != 0)
      {
        log_debug("euler_ode_integrator: implicit call to RHS at t + dt failed.");
        break; // Error, not converged.
      }

      // Update x_new: x_new <- x_orig + dt * RHS.
      for (int j = 0; j < N_local; ++j)
        integ->x_new[j] = x[j] + dt * ((1.0 - theta) * integ->f1[j] + theta * integ->f2[j]);

      // Compute the relative and absolute norms of the change to the solution.
      real_t rel_norm = 0.0, abs_norm = 0.0;
      integ->compute_norms(integ->comm, integ->x_old, integ->x_new, integ->num_local_values,
                           &rel_norm, &abs_norm);
       
      log_debug("euler_ode_integrator: iteration %d/%d", i+1, integ->max_iters);
      log_debug("  rel_norm = %g, abs_norm = %g", rel_norm, abs_norm);

      // Check for convergence.
      if ((rel_norm < integ->rel_tol) && (abs_norm < integ->abs_tol))
      {
        memcpy(x, integ->x_new, sizeof(real_t) * N_local);
        converged = true;
        *t += dt;
        break;
      }
    }

    STOP_FUNCTION_TIMER();
    return converged;
  }
}