bool RungeKutta::rk_time_step(double current_time, double time_step, Hermes::vector<Solution*> slns_time_prev, Hermes::vector<Solution*> slns_time_new, bool jacobian_changed, bool verbose, double newton_tol, int newton_max_iter,double newton_damping_coeff, double newton_max_allowed_residual_norm) { return rk_time_step(current_time, time_step, slns_time_prev, slns_time_new, Hermes::vector<Solution*>(), jacobian_changed, verbose, newton_tol, newton_max_iter, newton_damping_coeff, newton_max_allowed_residual_norm); }
// This is the same as the rk_time_step() function above but it does not have the err_vec vector. bool rk_time_step(double current_time, double time_step, ButcherTable* const bt, scalar* coeff_vec, DiscreteProblem* dp, MatrixSolverType matrix_solver, bool verbose, bool is_linear, double newton_tol, int newton_max_iter, double newton_damping_coeff, double newton_max_allowed_residual_norm) { return rk_time_step(current_time, time_step, bt, coeff_vec, NULL, dp, matrix_solver, verbose, is_linear, newton_tol, newton_max_iter, newton_damping_coeff, newton_max_allowed_residual_norm); }
bool RungeKutta::rk_time_step(double current_time, double time_step, Solution* sln_time_prev, Solution* sln_time_new, Solution* error_fn, bool jacobian_changed, bool verbose, double newton_tol, int newton_max_iter, double newton_damping_coeff, double newton_max_allowed_residual_norm) { Hermes::vector<Solution*> slns_time_prev = Hermes::vector<Solution*>(); slns_time_prev.push_back(sln_time_prev); Hermes::vector<Solution*> slns_time_new = Hermes::vector<Solution*>(); slns_time_new.push_back(sln_time_new); Hermes::vector<Solution*> error_fns = Hermes::vector<Solution*>(); error_fns.push_back(error_fn); return rk_time_step(current_time, time_step, slns_time_prev, slns_time_new, error_fns, jacobian_changed, verbose, newton_tol, newton_max_iter, newton_damping_coeff, newton_max_allowed_residual_norm); }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("cathedral.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_AIR, INIT_REF_NUM_BDY); mesh.refine_towards_boundary(BDY_GROUND, INIT_REF_NUM_BDY); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<std::string>(BDY_GROUND)); bc_types.add_bc_newton(BDY_AIR); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_const(BDY_GROUND, TEMP_INIT); // Initialize an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous time level solution (initialized by the external temperature). Solution u_prev_time(&mesh, TEMP_INIT); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(callback(stac_jacobian_vol)); wf.add_vector_form(callback(stac_residual_vol)); wf.add_matrix_form_surf(callback(stac_jacobian_surf), BDY_AIR); wf.add_vector_form_surf(callback(stac_residual_surf), BDY_AIR); // Project the initial condition on the FE space to obtain initial solution coefficient vector. info("Projecting initial condition to translate initial condition into a vector."); scalar* coeff_vec = new scalar[ndof]; OGProjection::project_global(&space, &u_prev_time, coeff_vec, matrix_solver); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Initialize views. ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600)); Tview.set_min_max_range(0,20); Tview.fix_scale_width(30); // Time stepping loop: double current_time = 0.0; int ts = 1; do { // Perform one Runge-Kutta time step according to the selected Butcher's table. info("Runge-Kutta time step (t = %g, tau = %g, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; bool is_linear = true; if (!rk_time_step(current_time, time_step, &bt, coeff_vec, &dp, matrix_solver, verbose, is_linear)) { error("Runge-Kutta time step failed, try to decrease time step size."); } // Convert coeff_vec into a new time level solution. Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Update time. current_time += time_step; // Show the new time level solution. char title[100]; sprintf(title, "Time %3.2f, exterior temperature %3.5f", current_time, temp_ext(current_time)); Tview.set_title(title); Tview.show(&u_prev_time); // Increase counter of time steps. ts++; } while (current_time < T_FINAL); // Cleanup. delete [] coeff_vec; // Wait for the view to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("cathedral.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_AIR, INIT_REF_NUM_BDY); mesh.refine_towards_boundary(BDY_GROUND, INIT_REF_NUM_BDY); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<std::string>(BDY_GROUND)); bc_types.add_bc_newton(BDY_AIR); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_const(BDY_GROUND, TEMP_INIT); // Initialize an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous time level solution (initialized by the external temperature). Solution u_prev_time(&mesh, TEMP_INIT); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(callback(stac_jacobian)); wf.add_vector_form(callback(stac_residual)); wf.add_matrix_form_surf(callback(bilinear_form_surf), BDY_AIR); wf.add_vector_form_surf(callback(linear_form_surf), BDY_AIR); // Project the initial condition on the FE space to obtain initial solution coefficient vector. info("Projecting initial condition to translate initial condition into a vector."); scalar* coeff_vec = new scalar[ndof]; OGProjection::project_global(&space, &u_prev_time, coeff_vec, matrix_solver); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Time stepping loop: double current_time = 0.0; int ts = 1; do { // Perform one Runge-Kutta time step according to the selected Butcher's table. info("Runge-Kutta time step (t = %g, tau = %g, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; if (!rk_time_step(current_time, time_step, &bt, coeff_vec, &dp, matrix_solver, verbose, NEWTON_TOL, NEWTON_MAX_ITER)) { error("Runge-Kutta time step failed, try to decrease time step size."); } // Convert coeff_vec into a new time level solution. Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Update time. current_time += time_step; // Increase counter of time steps. ts++; } while (current_time < time_step*5); double sum = 0; for (int i = 0; i < ndof; i++) sum += coeff_vec[i]; printf("sum = %g\n", sum); int success = 1; if (fabs(sum - 3617.55) > 1e-1) success = 0; // Cleanup. delete [] coeff_vec; if (success == 1) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("cathedral.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_AIR, INIT_REF_NUM_BDY); mesh.refine_towards_boundary(BDY_GROUND, INIT_REF_NUM_BDY); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<std::string>(BDY_GROUND)); bc_types.add_bc_newton(BDY_AIR); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_const(BDY_GROUND, TEMP_INIT); // Initialize an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous and next time level solutions. Solution* sln_time_prev = new Solution(&mesh, TEMP_INIT); Solution* sln_time_new = new Solution(&mesh); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(callback(stac_jacobian_vol)); wf.add_vector_form(callback(stac_residual_vol), HERMES_ANY, sln_time_prev); wf.add_matrix_form_surf(callback(stac_jacobian_surf), BDY_AIR, sln_time_prev); wf.add_vector_form_surf(callback(stac_residual_surf), BDY_AIR, sln_time_prev); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Time stepping loop: double current_time = time_step; int ts = 1; do { // Perform one Runge-Kutta time step according to the selected Butcher's table. info("Runge-Kutta time step (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; bool is_linear = true; if (!rk_time_step(current_time, time_step, &bt, sln_time_prev, sln_time_new, &dp, matrix_solver, verbose, is_linear)) { error("Runge-Kutta time step failed, try to decrease time step size."); } // Convert coeff_vec into a new time level solution. //Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Increase current time and time step counter. current_time += time_step; ts++; } while (current_time < T_FINAL); info("Coordinate (-2.0, 2.0) value = %lf", sln_time_new->get_pt_value(-2.0, 2.0)); info("Coordinate (-1.0, 2.0) value = %lf", sln_time_new->get_pt_value(-1.0, 2.0)); info("Coordinate ( 0.0, 2.0) value = %lf", sln_time_new->get_pt_value(0.0, 2.0)); info("Coordinate ( 1.0, 2.0) value = %lf", sln_time_new->get_pt_value(1.0, 2.0)); info("Coordinate ( 2.0, 2.0) value = %lf", sln_time_new->get_pt_value(2.0, 2.0)); bool success = true; if (fabs(sln_time_new->get_pt_value(-2.0, 2.0) - 9.999982) > 1E-6) success = false; if (fabs(sln_time_new->get_pt_value(-1.0, 2.0) - 10.000002) > 1E-6) success = false; if (fabs(sln_time_new->get_pt_value( 0.0, 2.0) - 9.999995) > 1E-6) success = false; if (fabs(sln_time_new->get_pt_value( 1.0, 2.0) - 10.000002) > 1E-6) success = false; if (fabs(sln_time_new->get_pt_value( 2.0, 2.0) - 9.999982) > 1E-6) success = false; if (success) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("wall.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_BOTTOM, INIT_REF_NUM_BDY); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_neumann(Hermes::vector<int>(BDY_RIGHT, BDY_LEFT)); bc_types.add_bc_newton(Hermes::vector<int>(BDY_BOTTOM, BDY_TOP)); // Initialize an H1 space with default shapeset. H1Space space(&mesh, &bc_types, NULL, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous and next time level solutions. Solution* sln_time_prev = new Solution(&mesh, TEMP_INIT); Solution* sln_time_new = new Solution(&mesh); Solution* time_error_fn = new Solution(&mesh, 0.0); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(stac_jacobian_vol, stac_jacobian_vol_ord, HERMES_NONSYM, HERMES_ANY, sln_time_prev); wf.add_vector_form(stac_residual_vol, stac_residual_vol_ord, HERMES_ANY, sln_time_prev); wf.add_matrix_form_surf(stac_jacobian_bottom, stac_jacobian_bottom_ord, BDY_BOTTOM, sln_time_prev); wf.add_vector_form_surf(stac_residual_bottom, stac_residual_bottom_ord, BDY_BOTTOM, sln_time_prev); wf.add_matrix_form_surf(stac_jacobian_top, stac_jacobian_top_ord, BDY_TOP, sln_time_prev); wf.add_vector_form_surf(stac_residual_top, stac_residual_top_ord, BDY_TOP, sln_time_prev); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Initialize views. ScalarView Tview("Temperature", new WinGeom(0, 0, 1500, 400)); Tview.fix_scale_width(40); ScalarView eview("Temporal error", new WinGeom(0, 450, 1500, 400)); eview.fix_scale_width(40); // Graph for time step history. SimpleGraph time_step_graph; info("Time step history will be saved to file time_step_history.dat."); // Time stepping loop: double current_time = 0; int ts = 1; do { // Perform one Runge-Kutta time step according to the selected Butcher's table. info("Runge-Kutta time step (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; bool is_linear = true; if (!rk_time_step(current_time, time_step, &bt, sln_time_prev, sln_time_new, time_error_fn, &dp, matrix_solver, verbose, is_linear)) { error("Runge-Kutta time step failed, try to decrease time step size."); } // Plot error function. char title[100]; sprintf(title, "Temporal error, t = %g", current_time); eview.set_title(title); AbsFilter abs_tef(time_error_fn); eview.show(&abs_tef, HERMES_EPS_VERYHIGH); // Calculate relative time stepping error and decide whether the // time step can be accepted. If not, then the time step size is // reduced and the entire time step repeated. If yes, then another // check is run, and if the relative error is very low, time step // is increased. double rel_err_time = calc_norm(time_error_fn, HERMES_H1_NORM) / calc_norm(sln_time_new, HERMES_H1_NORM) * 100; info("rel_err_time = %g%%", rel_err_time); if (rel_err_time > TIME_TOL_UPPER) { info("rel_err_time above upper limit %g%% -> decreasing time step from %g to %g and restarting time step.", TIME_TOL_UPPER, time_step, time_step * TIME_STEP_DEC_RATIO); time_step *= TIME_STEP_DEC_RATIO; continue; } if (rel_err_time < TIME_TOL_LOWER) { info("rel_err_time = below lower limit %g%% -> increasing time step from %g to %g", TIME_TOL_UPPER, time_step, time_step * TIME_STEP_INC_RATIO); time_step *= TIME_STEP_INC_RATIO; } // Add entry to the timestep graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); // Update time. current_time += time_step; // Show the new time level solution. sprintf(title, "Time %3.2f s", current_time); Tview.set_title(title); Tview.show(sln_time_new); // Copy solution for the new time step. sln_time_prev->copy(sln_time_new); // Increase counter of time steps. ts++; } while (current_time < T_FINAL); // Cleanup. delete sln_time_prev; delete sln_time_new; delete time_error_fn; // Wait for the view to be closed. View::wait(); return 0; }