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