int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("square.mesh", mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary("Bdy", INIT_BDY_REF_NUM); // Initialize boundary conditions. CustomEssentialBCNonConst bc_essential("Bdy"); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof = space->get_num_dofs(); // Initialize previous iteration solution for the Picard's method. MeshFunctionSharedPtr<double> init_condition(new ConstantSolution<double>(mesh, INIT_COND_CONST)); // Initialize the weak formulation. CustomNonlinearity lambda(alpha); Hermes2DFunction<double> src(-heat_src); CustomWeakFormPicard wf(init_condition, &lambda, &src); // Initialize the Picard solver. PicardSolver<double> picard(&wf, space); picard.set_max_allowed_iterations(PICARD_MAX_ITER); logger.info("Default tolerance"); try { picard.solve(init_condition); } catch(std::exception& e) { std::cout << e.what(); } int iter_1 = picard.get_num_iters(); logger.info("Adjusted tolerance without Anderson"); // Perform the Picard's iteration (Anderson acceleration on by default). picard.clear_tolerances(); picard.set_tolerance(PICARD_TOL, Hermes::Solvers::SolutionChangeAbsolute); try { picard.solve(init_condition); } catch(std::exception& e) { std::cout << e.what(); } int iter_2 = picard.get_num_iters(); // Translate the coefficient vector into a Solution. MeshFunctionSharedPtr<double> sln(new Solution<double>); Solution<double>::vector_to_solution(picard.get_sln_vector(), space, sln); logger.info("Default tolerance without Anderson and good initial guess"); PicardSolver<double> picard2(&wf, space); picard2.set_tolerance(1e-3, Hermes::Solvers::SolutionChangeRelative); picard2.set_max_allowed_iterations(PICARD_MAX_ITER); try { picard2.solve(sln); } catch(std::exception& e) { std::cout << e.what(); } int iter_3 = picard2.get_num_iters(); logger.info("Default tolerance with Anderson and good initial guess"); picard2.use_Anderson_acceleration(true); picard2.set_num_last_vector_used(PICARD_NUM_LAST_ITER_USED); picard2.set_anderson_beta(PICARD_ANDERSON_BETA); try { picard2.solve(sln); } catch(std::exception& e) { std::cout << e.what(); } int iter_4 = picard2.get_num_iters(); #ifdef SHOW_OUTPUT // Visualise the solution and mesh. ScalarView s_view("Solution", new WinGeom(0, 0, 440, 350)); s_view.show_mesh(false); s_view.show(sln); OrderView o_view("Mesh", new WinGeom(450, 0, 420, 350)); o_view.show(space); // Wait for all views to be closed. View::wait(); #endif bool success = Testing::test_value(iter_1, 14, "# of iterations 1", 1); // Tested value as of September 2013. success = Testing::test_value(iter_2, 12, "# of iterations 2", 1) & success; // Tested value as of September 2013. success = Testing::test_value(iter_3, 3, "# of iterations 3", 1) & success; // Tested value as of September 2013. success = Testing::test_value(iter_4, 3, "# of iterations 4", 1) & success; // Tested value as of September 2013. if(success) { printf("Success!\n"); return 0; } else { printf("Failure!\n"); return -1; } }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("square.mesh", &mesh); // Initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary("Top", INIT_REF_NUM_BDY); // Initialize boundary conditions. CustomEssentialBCNonConst bc_essential(Hermes::vector<std::string>("Bottom", "Right", "Top", "Left")); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d.", ndof); // Zero initial solutions. This is why we use H_OFFSET. ZeroSolution h_time_prev(&mesh), h_iter_prev(&mesh); // Initialize views. ScalarView view("Initial condition", new WinGeom(0, 0, 600, 500)); view.fix_scale_width(80); // Visualize the initial condition. view.show(&h_time_prev); // Initialize the constitutive relations. ConstitutiveRelations* constitutive_relations; if(constitutive_relations_type == CONSTITUTIVE_GENUCHTEN) constitutive_relations = new ConstitutiveRelationsGenuchten(ALPHA, M, N, THETA_S, THETA_R, K_S, STORATIVITY); else constitutive_relations = new ConstitutiveRelationsGardner(ALPHA, THETA_S, THETA_R, K_S); // Initialize the weak formulation. double current_time = 0; CustomWeakFormRichardsIEPicard wf(time_step, &h_time_prev, &h_iter_prev, constitutive_relations); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, &space); // Initialize the Picard solver. PicardSolver<double> picard(&dp, &h_iter_prev, matrix_solver); picard.set_verbose_output(true); // Time stepping: int ts = 1; do { info("---- Time step %d, time %3.5f s", ts, current_time); // Perform the Picard's iteration (Anderson acceleration on by default). if (!picard.solve(PICARD_TOL, PICARD_MAX_ITER, PICARD_NUM_LAST_ITER_USED, PICARD_ANDERSON_BETA)) error("Picard's iteration failed."); // Translate the coefficient vector into a Solution. Solution<double>::vector_to_solution(picard.get_sln_vector(), &space, &h_iter_prev); // Increase current time and time step counter. current_time += time_step; ts++; // Visualize the solution. char title[100]; sprintf(title, "Time %g s", current_time); view.set_title(title); view.show(&h_iter_prev); // Save the next time level solution. h_time_prev.copy(&h_iter_prev); } while (current_time < T_FINAL); // Wait for the view to be closed. View::wait(); return 0; }