int main(int argc, char* argv[]) { // load the mesh Mesh mesh, basemesh; basemesh.load("square.mesh"); for(int i = 0; i < REF_INIT; i++) basemesh.refine_all_elements(); mesh.copy(&basemesh); mesh.refine_towards_boundary(1,3); // initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // create finite element space H1Space space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_bc_values(bc_values); space.set_uniform_order(P_INIT); space.assign_dofs(); // enumerate basis functions space.assign_dofs(); Solution Tprev, // previous time step solution, for the time integration method Titer; // solution converging during the Newton's iteration // initialize the weak formulation WeakForm wf(1); if(TIME_DISCR == 1) { wf.add_biform(0, 0, callback(J_euler), UNSYM, ANY, 1, &Titer); wf.add_liform(0, callback(F_euler), ANY, 2, &Titer, &Tprev); } else { wf.add_biform(0, 0, callback(J_cranic), UNSYM, ANY, 1, &Titer); wf.add_liform(0, callback(F_cranic), ANY, 2, &Titer, &Tprev); } // matrix solver UmfpackSolver solver; // nonlinear system class NonlinSystem nls(&wf, &solver); nls.set_spaces(1, &space); nls.set_pss(1, &pss); // visualize solution and mesh ScalarView view("", 0, 0, 700, 600); view.fix_scale_width(80); OrderView ordview("", 700, 0, 700, 600); // error estimate as a function of physical time GnuplotGraph graph_err; graph_err.set_captions("","Time step","Error"); graph_err.add_row(); // error estimate as a function of DOF GnuplotGraph graph_dofs; graph_dofs.set_captions("","Time step","DOFs"); graph_dofs.add_row(); // initial condition at zero time level //Tprev.set_const(&mesh, 0.0); Tprev.set_dirichlet_lift(&space, &pss); Titer.set_dirichlet_lift(&space, &pss); nls.set_ic(&Titer, &Titer, PROJ_TYPE); // view initial guess for Newton's method // satisfies BC conditions char title[100]; sprintf(title, "Initial iteration"); view.set_title(title); view.show(&Titer); ordview.show(&space); //view.wait_for_keypress(); // this may cause graphics problems // time stepping loop int nstep = (int)(T_FINAL/TAU + 0.5); double cpu = 0.0; Solution sln_coarse, sln_fine; for(int n = 1; n <= nstep; n++) { info("\n---- Time step %d -----------------------------------------------------------------", n); // time measurement begin_time(); // perform periodic unrefinements if (n % UNREF_FREQ == 0) { mesh.copy(&basemesh); space.set_uniform_order(P_INIT); space.assign_dofs(); } // adaptivity loop int at = 0, ndofs; bool done = false; double err_est, cpu; do { info("\n---- Time step %d, adaptivity step %d ---------------------------------------------\n", n, ++at); // Newton's loop for coarse mesh solution int it = 1; double res_l2_norm; if (n > 1 || at > 1) nls.set_ic(&sln_fine, &Titer); else nls.set_ic(&Titer, &Titer); do { info("\n---- Time step %d, adaptivity step %d, Newton step %d (Coarse mesh solution)-------\n", n, at, it++); nls.assemble(); nls.solve(1, &sln_coarse); res_l2_norm = nls.get_residuum_l2_norm(); info("Residuum L2 norm: %g", res_l2_norm); Titer.copy(&sln_coarse); } while (res_l2_norm > NEWTON_TOL_COARSE); // Newton's loop for fine mesh solution it = 1; RefNonlinSystem rs(&nls); rs.prepare(); if (n > 1 || at > 1) rs.set_ic(&sln_fine, &Titer); else rs.set_ic(&Titer, &Titer); do { info("\n---- Time step %d, adaptivity step %d, Newton step %d (Fine mesh solution) --------\n", n, at, it++); rs.assemble(); rs.solve(1, &sln_fine); res_l2_norm = rs.get_residuum_l2_norm(); info("Residuum L2 norm: %g", res_l2_norm); Titer.copy(&sln_fine); } while (res_l2_norm > NEWTON_TOL_REF); // calculate error estimate wrt. fine mesh solution H1OrthoHP hp(1, &space); err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100; info("Error estimate: %g%", err_est); // visualization of solution on the n-th time level sprintf(title, "Temperature, time level %d", n); //view.set_min_max_range(0,100); view.set_title(title); //view.show(&Titer); // to see reference solution view.show(&sln_fine); // to see the solution // visualization of mesh on the n-th time level sprintf(title, "hp-mesh, time level %d", n); ordview.set_title(title); ordview.show(&space); // to see hp-mesh //view.wait_for_keypress(); // if err_est too large, adapt the mesh if (err_est < SPACE_H1_TOL) done = true; else { hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY); ndofs = space.assign_dofs(); if (ndofs >= NDOF_STOP) done = true; } // time measurement cpu += end_time(); } while (!done); // add entry to both time and DOF error graphs graph_err.add_values(0, n, err_est); graph_err.save("error.txt"); graph_dofs.add_values(0, n, space.get_num_dofs()); graph_dofs.save("dofs.txt"); // copying result of the Newton's iteration into Tprev Tprev.copy(&Titer); } // time measurement cpu += end_time(); verbose("Total running time: %g sec", cpu); // wait for keyboard or mouse input View::wait("Waiting for keyboard or mouse input."); return 0; }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. MeshSharedPtr mesh(new Mesh), basemesh(new Mesh); MeshReaderH2D mloader; mloader.load("square.mesh", basemesh); mesh->copy(basemesh); // 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. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof_coarse = Space<double>::get_num_dofs(space); adaptivity.set_space(space); Hermes::Mixins::Loggable::Static::info("ndof_coarse = %d.", ndof_coarse); // Zero initial solution. This is why we use H_OFFSET. MeshFunctionSharedPtr<double> h_time_prev(new ZeroSolution<double>(mesh)), h_time_new(new ZeroSolution<double>(mesh)); // 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. CustomWeakFormRichardsRK wf(constitutive_relations); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, space); // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // Visualize initial condition. char title[100]; ScalarView view("Initial condition", new WinGeom(0, 0, 440, 350)); OrderView ordview("Initial mesh", new WinGeom(445, 0, 440, 350)); view.show(h_time_prev); ordview.show(space); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Time stepping loop. double current_time = 0; int ts = 1; do { // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh->copy(basemesh); space->set_uniform_order(P_INIT); break; case 2: mesh->unrefine_all_elements(); space->set_uniform_order(P_INIT); break; case 3: space->unrefine_all_mesh_elements(); space->adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: throw Hermes::Exceptions::Exception("Wrong global derefinement method."); } space->assign_dofs(); ndof_coarse = Space<double>::get_num_dofs(space); } // Spatial adaptivity loop. Note: h_time_prev must not be changed // during spatial adaptivity. bool done = false; int as = 1; double err_est; do { Hermes::Mixins::Loggable::Static::info("Time step %d, adaptivity step %d:", ts, as); // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<double> ref_space = refSpaceCreator.create_ref_space(); int ndof_ref = Space<double>::get_num_dofs(ref_space); // Time measurement. cpu_time.tick(); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(&wf, ref_space, &bt); // Perform one Runge-Kutta time step according to the selected Butcher's table. Hermes::Mixins::Loggable::Static::info("Runge-Kutta time step (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt.get_size()); try { runge_kutta.set_time(current_time); runge_kutta.set_time_step(time_step); runge_kutta.set_max_allowed_iterations(NEWTON_MAX_ITER); runge_kutta.set_tolerance(NEWTON_TOL); runge_kutta.rk_time_step_newton(h_time_prev, h_time_new); } catch(Exceptions::Exception& e) { e.print_msg(); throw Hermes::Exceptions::Exception("Runge-Kutta time step failed"); } // Project the fine mesh solution onto the coarse mesh. MeshFunctionSharedPtr<double> sln_coarse(new Solution<double>); Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection<double> ogProjection; ogProjection.project_global(space, h_time_new, sln_coarse); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); errorCalculator.calculate_errors(sln_coarse, h_time_new, true); double err_est_rel_total = errorCalculator.get_total_error_squared() * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_ref: %d, err_est_rel: %g%%", Space<double>::get_num_dofs(space), Space<double>::get_num_dofs(ref_space), err_est_rel_total); // Time measurement. cpu_time.tick(); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adaptivity.adapt(&selector); // Increase the counter of performed adaptivity steps. as++; } } while (done == false); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(current_time, Space<double>::get_num_dofs(space)); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(current_time, cpu_time.accumulated()); graph_cpu.save("conv_cpu_est.dat"); // Visualize the solution and mesh-> char title[100]; sprintf(title, "Solution, time %g", current_time); view.set_title(title); view.show_mesh(false); view.show(h_time_new); sprintf(title, "Mesh, time %g", current_time); ordview.set_title(title); ordview.show(space); // Copy last reference solution into h_time_prev. h_time_prev->copy(h_time_new); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views 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); 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, basemesh; MeshReaderH2D mloader; mloader.load("square.mesh", &basemesh); mesh.copy(&basemesh); // 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_coarse = Space<double>::get_num_dofs(&space); info("ndof_coarse = %d.", ndof_coarse); // Zero initial solution. This is why we use H_OFFSET. ZeroSolution h_time_prev(&mesh), h_time_new(&mesh); // 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. CustomWeakFormRichardsRK wf(constitutive_relations); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, &space); // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Visualize initial condition. char title[100]; ScalarView view("Initial condition", new WinGeom(0, 0, 440, 350)); OrderView ordview("Initial mesh", new WinGeom(445, 0, 440, 350)); view.show(&h_time_prev); ordview.show(&space); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Time stepping loop. double current_time = 0; int ts = 1; do { // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh.copy(&basemesh); space.set_uniform_order(P_INIT); break; case 2: mesh.unrefine_all_elements(); space.set_uniform_order(P_INIT); break; case 3: space.unrefine_all_mesh_elements(); space.adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: error("Wrong global derefinement method."); } ndof_coarse = Space<double>::get_num_dofs(&space); } // Spatial adaptivity loop. Note: h_time_prev must not be changed // during spatial adaptivity. bool done = false; int as = 1; double err_est; do { info("Time step %d, adaptivity step %d:", ts, as); // Construct globally refined reference mesh and setup reference space. Space<double>* ref_space = Space<double>::construct_refined_space(&space); int ndof_ref = Space<double>::get_num_dofs(ref_space); // Time measurement. cpu_time.tick(); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(&wf, ref_space, &bt, matrix_solver); // 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 freeze_jacobian = false; bool block_diagonal_jacobian = false; bool verbose = true; double damping_coeff = 1.0; double max_allowed_residual_norm = 1e10; try { runge_kutta.rk_time_step_newton(current_time, time_step, &h_time_prev, &h_time_new, freeze_jacobian, block_diagonal_jacobian, verbose, NEWTON_TOL, NEWTON_MAX_ITER, damping_coeff, max_allowed_residual_norm); } catch(Exceptions::Exception& e) { e.printMsg(); error("Runge-Kutta time step failed"); } // Project the fine mesh solution onto the coarse mesh. Solution<double> sln_coarse; info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection<double>::project_global(&space, &h_time_new, &sln_coarse, matrix_solver); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt<double>* adaptivity = new Adapt<double>(&space); double err_est_rel_total = adaptivity->calc_err_est(&sln_coarse, &h_time_new) * 100; // Report results. info("ndof_coarse: %d, ndof_ref: %d, err_est_rel: %g%%", Space<double>::get_num_dofs(&space), Space<double>::get_num_dofs(ref_space), err_est_rel_total); // Time measurement. cpu_time.tick(); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting the coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); if (Space<double>::get_num_dofs(&space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete adaptivity; if(!done) { delete h_time_new.get_space(); delete h_time_new.get_mesh(); } } while (done == false); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(current_time, Space<double>::get_num_dofs(&space)); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(current_time, cpu_time.accumulated()); graph_cpu.save("conv_cpu_est.dat"); // Visualize the solution and mesh. char title[100]; sprintf(title, "Solution, time %g", current_time); view.set_title(title); view.show_mesh(false); view.show(&h_time_new); sprintf(title, "Mesh, time %g", current_time); ordview.set_title(title); ordview.show(&space); // Copy last reference solution into h_time_prev. h_time_prev.copy(&h_time_new); delete h_time_new.get_mesh(); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views 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); if (bt.is_explicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Turn off adaptive time stepping if R-K method is not embedded. if (bt.is_embedded() == false && ADAPTIVE_TIME_STEP_ON == true) { Hermes::Mixins::Loggable::Static::warn("R-K method not embedded, turning off adaptive time stepping."); ADAPTIVE_TIME_STEP_ON = false; } // Load the mesh. MeshSharedPtr mesh(new Mesh), basemesh(new Mesh); MeshReaderH2D mloader; mloader.load("wall.mesh", basemesh); mesh->copy(basemesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary(BDY_RIGHT, 2); mesh->refine_towards_boundary(BDY_FIRE, INIT_REF_NUM_BDY); // Initialize essential boundary conditions (none). EssentialBCs<double> bcs; // Initialize an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof = Space<double>::get_num_dofs(space); Hermes::Mixins::Loggable::Static::info("ndof = %d.", ndof); // Convert initial condition into a Solution. MeshFunctionSharedPtr<double> sln_prev_time(new ConstantSolution<double> (mesh, TEMP_INIT)); // Initialize the weak formulation. double current_time = 0; CustomWeakFormHeatRK wf(BDY_FIRE, BDY_AIR, ALPHA_FIRE, ALPHA_AIR, RHO, HEATCAP, TEMP_EXT_AIR, TEMP_INIT, ¤t_time); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, space); // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // Visualize initial condition. char title[100]; ScalarView sln_view("Initial condition", new WinGeom(0, 0, 1500, 360)); OrderView ordview("Initial mesh", new WinGeom(0, 410, 1500, 360)); ScalarView time_error_view("Temporal error", new WinGeom(0, 800, 1500, 360)); time_error_view.fix_scale_width(40); ScalarView space_error_view("Spatial error", new WinGeom(0, 1220, 1500, 360)); space_error_view.fix_scale_width(40); sln_view.show(sln_prev_time); ordview.show(space); // Graph for time step history. SimpleGraph time_step_graph; if (ADAPTIVE_TIME_STEP_ON) Hermes::Mixins::Loggable::Static::info("Time step history will be saved to file time_step_history.dat."); // Class for projections. OGProjection<double> ogProjection; // Time stepping loop: int ts = 1; do { Hermes::Mixins::Loggable::Static::info("Begin time step %d.", ts); // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh->copy(basemesh); space->set_uniform_order(P_INIT); break; case 2: space->unrefine_all_mesh_elements(); space->set_uniform_order(P_INIT); break; case 3: space->unrefine_all_mesh_elements(); //space->adjust_element_order(-1, P_INIT); space->adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: throw Hermes::Exceptions::Exception("Wrong global derefinement method."); } space->assign_dofs(); ndof = Space<double>::get_num_dofs(space); } // Spatial adaptivity loop. Note: sln_prev_time must not be // changed during spatial adaptivity. MeshFunctionSharedPtr<double> ref_sln(new Solution<double>()); MeshFunctionSharedPtr<double> time_error_fn(new Solution<double>(mesh)); bool done = false; int as = 1; double err_est; do { // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<double> ref_space = refSpaceCreator.create_ref_space(); // Initialize Runge-Kutta time stepping on the reference mesh. RungeKutta<double> runge_kutta(&wf, ref_space, &bt); try { ogProjection.project_global(ref_space, sln_prev_time, sln_prev_time); } catch(Exceptions::Exception& e) { std::cout << e.what() << std::endl; Hermes::Mixins::Loggable::Static::error("Projection failed."); return -1; } // Runge-Kutta step on the fine mesh-> Hermes::Mixins::Loggable::Static::info("Runge-Kutta time step on fine mesh (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; bool jacobian_changed = false; try { runge_kutta.set_time(current_time); runge_kutta.set_time_step(time_step); runge_kutta.set_max_allowed_iterations(NEWTON_MAX_ITER); runge_kutta.set_tolerance(NEWTON_TOL_FINE); runge_kutta.rk_time_step_newton(sln_prev_time, ref_sln, bt.is_embedded() ? time_error_fn : NULL); } catch(Exceptions::Exception& e) { std::cout << e.what() << std::endl; Hermes::Mixins::Loggable::Static::error("Runge-Kutta time step failed"); return -1; } /* If ADAPTIVE_TIME_STEP_ON == true, estimate temporal error. If too large or too small, then adjust it and restart the time step. */ double rel_err_time = 0; if (bt.is_embedded() == true) { Hermes::Mixins::Loggable::Static::info("Calculating temporal error estimate."); // Show temporal error. char title[100]; sprintf(title, "Temporal error est, spatial adaptivity step %d", as); time_error_view.set_title(title); //time_error_view.show_mesh(false); time_error_view.show(time_error_fn); rel_err_time = Global<double>::calc_norm(time_error_fn.get(), HERMES_H1_NORM) / Global<double>::calc_norm(ref_sln.get(), HERMES_H1_NORM) * 100; if (ADAPTIVE_TIME_STEP_ON == false) Hermes::Mixins::Loggable::Static::info("rel_err_time: %g%%", rel_err_time); } if (ADAPTIVE_TIME_STEP_ON) { if (rel_err_time > TIME_ERR_TOL_UPPER) { Hermes::Mixins::Loggable::Static::info("rel_err_time %g%% is above upper limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER); Hermes::Mixins::Loggable::Static::info("Decreasing tau from %g to %g s and restarting time step.", time_step, time_step * TIME_STEP_DEC_RATIO); time_step *= TIME_STEP_DEC_RATIO; continue; } else if (rel_err_time < TIME_ERR_TOL_LOWER) { Hermes::Mixins::Loggable::Static::info("rel_err_time = %g%% is below lower limit %g%%", rel_err_time, TIME_ERR_TOL_LOWER); Hermes::Mixins::Loggable::Static::info("Increasing tau from %g to %g s.", time_step, time_step * TIME_STEP_INC_RATIO); time_step *= TIME_STEP_INC_RATIO; } else { Hermes::Mixins::Loggable::Static::info("rel_err_time = %g%% is in acceptable interval (%g%%, %g%%)", rel_err_time, TIME_ERR_TOL_LOWER, TIME_ERR_TOL_UPPER); } // Add entry to time step history graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); } /* Estimate spatial errors and perform mesh refinement */ Hermes::Mixins::Loggable::Static::info("Spatial adaptivity step %d.", as); // Project the fine mesh solution onto the coarse mesh. MeshFunctionSharedPtr<double> sln(new Solution<double>()); Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh for error estimation."); ogProjection.project_global(space, ref_sln, sln); // Show spatial error. sprintf(title, "Spatial error est, spatial adaptivity step %d", as); MeshFunctionSharedPtr<double> space_error_fn(new DiffFilter<double>(Hermes::vector<MeshFunctionSharedPtr<double> >(ref_sln, sln))); space_error_view.set_title(title); //space_error_view.show_mesh(false); MeshFunctionSharedPtr<double> abs_sef(new AbsFilter(space_error_fn)); space_error_view.show(abs_sef); // Calculate element errors and spatial error estimate. Hermes::Mixins::Loggable::Static::info("Calculating spatial error estimate."); adaptivity.set_space(space); double err_rel_space = errorCalculator.get_total_error_squared() * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof: %d, ref_ndof: %d, err_rel_space: %g%%", Space<double>::get_num_dofs(space), Space<double>::get_num_dofs(ref_space), err_rel_space); // If err_est too large, adapt the mesh. if (err_rel_space < SPACE_ERR_TOL) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adaptivity.adapt(&selector); if (Space<double>::get_num_dofs(space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. if(!done) } while (done == false); // Visualize the solution and mesh-> char title[100]; sprintf(title, "Solution, time %g s", current_time); sln_view.set_title(title); //sln_view.show_mesh(false); sln_view.show(ref_sln); sprintf(title, "Mesh, time %g s", current_time); ordview.set_title(title); ordview.show(space); // Copy last reference solution into sln_prev_time sln_prev_time->copy(ref_sln); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // load the mesh Mesh mesh; H2DReader mloader; mloader.load("lshape3q.mesh", &mesh); // mloader.load("lshape3t.mesh", &mesh); // initialize the shapeset and the cache HcurlShapeset shapeset; PrecalcShapeset pss(&shapeset); // create finite element space HcurlSpace space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_uniform_order(P_INIT); // enumerate basis functions space.assign_dofs(); // initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, callback(bilinear_form), SYM); wf.add_biform_surf(0, 0, callback(bilinear_form_surf)); wf.add_liform_surf(0, linear_form_surf, linear_form_surf_ord); // visualize solution and mesh OrderView ordview("Polynomial Orders", 600, 0, 600, 500); VectorView vecview("Real part of Electric Field - VectorView", 0, 0, 600, 500); /* // view the basis functions VectorBaseView bview; vbview.show(&space); vbview.wait_for_keypress(); */ // matrix solver UmfpackSolver solver; // DOF and CPU convergence graphs SimpleGraph graph_dof_est, graph_dof_exact, graph_cpu_est, graph_cpu_exact; // adaptivity loop int it = 1, ndofs; bool done = false; double cpu = 0.0; Solution sln_coarse, sln_fine; do { info("\n---- Adaptivity step %d ---------------------------------------------\n", it++); // time measurement begin_time(); // solve the coarse mesh problem LinSystem sys(&wf, &solver); sys.set_spaces(1, &space); sys.set_pss(1, &pss); sys.assemble(); sys.solve(1, &sln_coarse); // time measurement cpu += end_time(); // calculating error wrt. exact solution ExactSolution ex(&mesh, exact); double err_exact = 100 * hcurl_error(&sln_coarse, &ex); info("Exact solution error: %g%%", err_exact); // show real part of the solution and mesh ordview.show(&space); RealFilter real(&sln_coarse); vecview.set_min_max_range(0, 1); vecview.show(&real, EPS_HIGH); // time measurement begin_time(); // solve the fine mesh problem RefSystem rs(&sys); rs.assemble(); rs.solve(1, &sln_fine); // calculate error estimate wrt. fine mesh solution HcurlOrthoHP hp(1, &space); double err_est_adapt = hp.calc_error(&sln_coarse, &sln_fine) * 100; double err_est_hcurl = hcurl_error(&sln_coarse, &sln_fine) * 100; info("Error estimate (adapt): %g%%", err_est_adapt); info("Error estimate (hcurl): %g%%", err_est_hcurl); // add entries to DOF convergence graphs graph_dof_exact.add_values(space.get_num_dofs(), err_exact); graph_dof_exact.save("conv_dof_exact.dat"); graph_dof_est.add_values(space.get_num_dofs(), err_est_hcurl); graph_dof_est.save("conv_dof_est.dat"); // add entries to CPU convergence graphs graph_cpu_exact.add_values(cpu, err_exact); graph_cpu_exact.save("conv_cpu_exact.dat"); graph_cpu_est.add_values(cpu, err_est_hcurl); graph_cpu_est.save("conv_cpu_est.dat"); // if err_est_adapt too large, adapt the mesh if (err_est_adapt < ERR_STOP) done = true; else { hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY); ndofs = space.assign_dofs(); if (ndofs >= NDOF_STOP) done = true; } // time measurement cpu += end_time(); } while (!done); verbose("Total running time: %g sec", cpu); // show the fine solution - this is the final result vecview.set_title("Final solution"); vecview.show(&sln_fine); // wait for keyboard or mouse input View::wait("Waiting for all views to be closed."); return 0; }