int main(int argc, char** argv) { // Initialize libMesh. LibMeshInit init (argc, argv); // Skip adaptive examples on a non-adaptive libMesh build #ifndef LIBMESH_ENABLE_AMR libmesh_example_assert(false, "--enable-amr"); #else // Parse the input file GetPot input_file("adaptivity_ex3.in"); // Read in parameters from the input file const unsigned int max_r_steps = input_file("max_r_steps", 3); const unsigned int max_r_level = input_file("max_r_level", 3); const Real refine_percentage = input_file("refine_percentage", 0.5); const Real coarsen_percentage = input_file("coarsen_percentage", 0.5); const unsigned int uniform_refine = input_file("uniform_refine",0); const std::string refine_type = input_file("refinement_type", "h"); const std::string approx_type = input_file("approx_type", "LAGRANGE"); const unsigned int approx_order = input_file("approx_order", 1); const std::string element_type = input_file("element_type", "tensor"); const int extra_error_quadrature = input_file("extra_error_quadrature", 0); const int max_linear_iterations = input_file("max_linear_iterations", 5000); const bool output_intermediate = input_file("output_intermediate", false); dim = input_file("dimension", 2); const std::string indicator_type = input_file("indicator_type", "kelly"); singularity = input_file("singularity", true); // Skip higher-dimensional examples on a lower-dimensional libMesh build libmesh_example_assert(dim <= LIBMESH_DIM, "2D/3D support"); // Output file for plotting the error as a function of // the number of degrees of freedom. std::string approx_name = ""; if (element_type == "tensor") approx_name += "bi"; if (approx_order == 1) approx_name += "linear"; else if (approx_order == 2) approx_name += "quadratic"; else if (approx_order == 3) approx_name += "cubic"; else if (approx_order == 4) approx_name += "quartic"; std::string output_file = approx_name; output_file += "_"; output_file += refine_type; if (uniform_refine == 0) output_file += "_adaptive.m"; else output_file += "_uniform.m"; std::ofstream out (output_file.c_str()); out << "% dofs L2-error H1-error" << std::endl; out << "e = [" << std::endl; // Create a mesh. Mesh mesh; // Read in the mesh if (dim == 1) MeshTools::Generation::build_line(mesh,1,-1.,0.); else if (dim == 2) mesh.read("lshaped.xda"); else mesh.read("lshaped3D.xda"); // Use triangles if the config file says so if (element_type == "simplex") MeshTools::Modification::all_tri(mesh); // We used first order elements to describe the geometry, // but we may need second order elements to hold the degrees // of freedom if (approx_order > 1 || refine_type != "h") mesh.all_second_order(); // Mesh Refinement object MeshRefinement mesh_refinement(mesh); mesh_refinement.refine_fraction() = refine_percentage; mesh_refinement.coarsen_fraction() = coarsen_percentage; mesh_refinement.max_h_level() = max_r_level; // Create an equation systems object. EquationSystems equation_systems (mesh); // Declare the system and its variables. // Creates a system named "Laplace" LinearImplicitSystem& system = equation_systems.add_system<LinearImplicitSystem> ("Laplace"); // Adds the variable "u" to "Laplace", using // the finite element type and order specified // in the config file system.add_variable("u", static_cast<Order>(approx_order), Utility::string_to_enum<FEFamily>(approx_type)); // Give the system a pointer to the matrix assembly // function. system.attach_assemble_function (assemble_laplace); // Initialize the data structures for the equation system. equation_systems.init(); // Set linear solver max iterations equation_systems.parameters.set<unsigned int>("linear solver maximum iterations") = max_linear_iterations; // Linear solver tolerance. equation_systems.parameters.set<Real>("linear solver tolerance") = std::pow(TOLERANCE, 2.5); // Prints information about the system to the screen. equation_systems.print_info(); // Construct ExactSolution object and attach solution functions ExactSolution exact_sol(equation_systems); exact_sol.attach_exact_value(exact_solution); exact_sol.attach_exact_deriv(exact_derivative); // Use higher quadrature order for more accurate error results exact_sol.extra_quadrature_order(extra_error_quadrature); // A refinement loop. for (unsigned int r_step=0; r_step<max_r_steps; r_step++) { std::cout << "Beginning Solve " << r_step << std::endl; // Solve the system "Laplace", just like example 2. system.solve(); std::cout << "System has: " << equation_systems.n_active_dofs() << " degrees of freedom." << std::endl; std::cout << "Linear solver converged at step: " << system.n_linear_iterations() << ", final residual: " << system.final_linear_residual() << std::endl; #ifdef LIBMESH_HAVE_EXODUS_API // After solving the system write the solution // to a ExodusII-formatted plot file. if (output_intermediate) { OStringStream outfile; outfile << "lshaped_" << r_step << ".e"; ExodusII_IO (mesh).write_equation_systems (outfile.str(), equation_systems); } #endif // #ifdef LIBMESH_HAVE_EXODUS_API // Compute the error. exact_sol.compute_error("Laplace", "u"); // Print out the error values std::cout << "L2-Error is: " << exact_sol.l2_error("Laplace", "u") << std::endl; std::cout << "H1-Error is: " << exact_sol.h1_error("Laplace", "u") << std::endl; // Print to output file out << equation_systems.n_active_dofs() << " " << exact_sol.l2_error("Laplace", "u") << " " << exact_sol.h1_error("Laplace", "u") << std::endl; // Possibly refine the mesh if (r_step+1 != max_r_steps) { std::cout << " Refining the mesh..." << std::endl; if (uniform_refine == 0) { // The \p ErrorVector is a particular \p StatisticsVector // for computing error information on a finite element mesh. ErrorVector error; if (indicator_type == "exact") { // The \p ErrorEstimator class interrogates a // finite element solution and assigns to each // element a positive error value. // This value is used for deciding which elements to // refine and which to coarsen. // For these simple test problems, we can use // numerical quadrature of the exact error between // the approximate and analytic solutions. // However, for real problems, we would need an error // indicator which only relies on the approximate // solution. ExactErrorEstimator error_estimator; error_estimator.attach_exact_value(exact_solution); error_estimator.attach_exact_deriv(exact_derivative); // We optimize in H1 norm, the default // error_estimator.error_norm = H1; // Compute the error for each active element using // the provided indicator. Note in general you // will need to provide an error estimator // specifically designed for your application. error_estimator.estimate_error (system, error); } else if (indicator_type == "patch") { // The patch recovery estimator should give a // good estimate of the solution interpolation // error. PatchRecoveryErrorEstimator error_estimator; error_estimator.estimate_error (system, error); } else if (indicator_type == "uniform") { // Error indication based on uniform refinement // is reliable, but very expensive. UniformRefinementEstimator error_estimator; error_estimator.estimate_error (system, error); } else { libmesh_assert_equal_to (indicator_type, "kelly"); // The Kelly error estimator is based on // an error bound for the Poisson problem // on linear elements, but is useful for // driving adaptive refinement in many problems KellyErrorEstimator error_estimator; error_estimator.estimate_error (system, error); } // Write out the error distribution OStringStream ss; ss << r_step; #ifdef LIBMESH_HAVE_EXODUS_API std::string error_output = "error_"+ss.str()+".e"; #else std::string error_output = "error_"+ss.str()+".gmv"; #endif error.plot_error( error_output, mesh ); // This takes the error in \p error and decides which elements // will be coarsened or refined. Any element within 20% of the // maximum error on any element will be refined, and any // element within 10% of the minimum error on any element might // be coarsened. Note that the elements flagged for refinement // will be refined, but those flagged for coarsening _might_ be // coarsened. mesh_refinement.flag_elements_by_error_fraction (error); // If we are doing adaptive p refinement, we want // elements flagged for that instead. if (refine_type == "p") mesh_refinement.switch_h_to_p_refinement(); // If we are doing "matched hp" refinement, we // flag elements for both h and p if (refine_type == "matchedhp") mesh_refinement.add_p_to_h_refinement(); // If we are doing hp refinement, we // try switching some elements from h to p if (refine_type == "hp") { HPCoarsenTest hpselector; hpselector.select_refinement(system); } // If we are doing "singular hp" refinement, we // try switching most elements from h to p if (refine_type == "singularhp") { // This only differs from p refinement for // the singular problem libmesh_assert (singularity); HPSingularity hpselector; // Our only singular point is at the origin hpselector.singular_points.push_back(Point()); hpselector.select_refinement(system); } // This call actually refines and coarsens the flagged // elements. mesh_refinement.refine_and_coarsen_elements(); } else if (uniform_refine == 1) { if (refine_type == "h" || refine_type == "hp" || refine_type == "matchedhp") mesh_refinement.uniformly_refine(1); if (refine_type == "p" || refine_type == "hp" || refine_type == "matchedhp") mesh_refinement.uniformly_p_refine(1); } // This call reinitializes the \p EquationSystems object for // the newly refined mesh. One of the steps in the // reinitialization is projecting the \p solution, // \p old_solution, etc... vectors from the old mesh to // the current one. equation_systems.reinit (); } } #ifdef LIBMESH_HAVE_EXODUS_API // Write out the solution // After solving the system write the solution // to a ExodusII-formatted plot file. ExodusII_IO (mesh).write_equation_systems ("lshaped.e", equation_systems); #endif // #ifdef LIBMESH_HAVE_EXODUS_API // Close up the output file. out << "];" << std::endl; out << "hold on" << std::endl; out << "plot(e(:,1), e(:,2), 'bo-');" << std::endl; out << "plot(e(:,1), e(:,3), 'ro-');" << std::endl; // out << "set(gca,'XScale', 'Log');" << std::endl; // out << "set(gca,'YScale', 'Log');" << std::endl; out << "xlabel('dofs');" << std::endl; out << "title('" << approx_name << " elements');" << std::endl; out << "legend('L2-error', 'H1-error');" << std::endl; // out << "disp('L2-error linear fit');" << std::endl; // out << "polyfit(log10(e(:,1)), log10(e(:,2)), 1)" << std::endl; // out << "disp('H1-error linear fit');" << std::endl; // out << "polyfit(log10(e(:,1)), log10(e(:,3)), 1)" << std::endl; #endif // #ifndef LIBMESH_ENABLE_AMR // All done. return 0; }
int main(int argc, char** argv){ //initialize libMesh LibMeshInit init(argc, argv); //parameters GetPot infile("fem_system_params.in"); const bool transient = infile("transient", true); const Real deltat = infile("deltat", 0.005); unsigned int n_timesteps = infile("n_timesteps", 20); const int nx = infile("nx",100); const int ny = infile("ny",100); const int nz = infile("nz",100); //const unsigned int dim = 3; const unsigned int max_r_steps = infile("max_r_steps", 3); const unsigned int max_r_level = infile("max_r_level", 3); const Real refine_percentage = infile("refine_percentage", 0.1); const Real coarsen_percentage = infile("coarsen_percentage", 0.0); const std::string indicator_type = infile("indicator_type", "kelly"); const bool write_error = infile("write_error",false); const bool flag_by_elem_frac = infile("flag_by_elem_frac",true); #ifdef LIBMESH_HAVE_EXODUS_API const unsigned int write_interval = infile("write_interval", 5); #endif // Create a mesh, with dimension to be overridden later, distributed // across the default MPI communicator. Mesh mesh(init.comm()); //create mesh unsigned int dim; if(nz == 0){ //to check if oscillations happen in 2D as well... dim = 2; MeshTools::Generation::build_square(mesh, nx, ny, 497150.0, 501750.0, 537350.0, 540650.0, QUAD9); }else{ dim = 3; MeshTools::Generation::build_cube(mesh, nx, ny, nz, 497150.0, 501750.0, 537350.0, 540650.0, 0.0, 100.0, HEX27); } // Print information about the mesh to the screen. mesh.print_info(); // Create an equation systems object. EquationSystems equation_systems (mesh); //name system ContamTransSysInv & system = equation_systems.add_system<ContamTransSysInv>("ContamTransInv"); //solve as steady or transient if(transient){ //system.time_solver = AutoPtr<TimeSolver>(new EulerSolver(system)); //backward Euler system.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system)); std::cout << "\n\nAaahhh transience not yet available!\n" << std::endl; n_timesteps = 1; } else{ system.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system)); libmesh_assert_equal_to (n_timesteps, 1); //this doesn't seem to work? } // Initialize the system equation_systems.init (); //initial conditions read_initial_parameters(); system.project_solution(initial_value, initial_grad, equation_systems.parameters); finish_initialization(); // Set the time stepping options... system.deltat = deltat; //...and the nonlinear solver options... NewtonSolver *solver = new NewtonSolver(system); system.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver); solver->quiet = infile("solver_quiet", true); solver->verbose = !solver->quiet; solver->max_nonlinear_iterations = infile("max_nonlinear_iterations", 15); solver->relative_step_tolerance = infile("relative_step_tolerance", 1.e-3); solver->relative_residual_tolerance = infile("relative_residual_tolerance", 0.0); solver->absolute_residual_tolerance = infile("absolute_residual_tolerance", 0.0); // And the linear solver options solver->max_linear_iterations = infile("max_linear_iterations", 10000); solver->initial_linear_tolerance = infile("initial_linear_tolerance",1.e-13); solver->minimum_linear_tolerance = infile("minimum_linear_tolerance",1.e-13); solver->linear_tolerance_multiplier = infile("linear_tolerance_multiplier",1.e-3); // Mesh Refinement object - to test effect of constant refined mesh (not refined at every timestep) MeshRefinement mesh_refinement(mesh); mesh_refinement.refine_fraction() = refine_percentage; mesh_refinement.coarsen_fraction() = coarsen_percentage; mesh_refinement.max_h_level() = max_r_level; // Print information about the system to the screen. equation_systems.print_info(); ExodusII_IO exodusIO = ExodusII_IO(mesh); //for writing multiple timesteps to one file for (unsigned int r_step=0; r_step<max_r_steps; r_step++) { std::cout << "\nBeginning Solve " << r_step+1 << std::endl; for (unsigned int t_step=0; t_step != n_timesteps; ++t_step) { std::cout << "\n\nSolving time step " << t_step << ", time = " << system.time << std::endl; system.solve(); system.postprocess(); // Advance to the next timestep in a transient problem system.time_solver->advance_timestep(); } //end stepping through time loop std::cout << "\n Refining the mesh..." << std::endl; // The \p ErrorVector is a particular \p StatisticsVector // for computing error information on a finite element mesh. ErrorVector error; if (indicator_type == "patch") { // The patch recovery estimator should give a // good estimate of the solution interpolation // error. PatchRecoveryErrorEstimator error_estimator; error_estimator.set_patch_reuse(false); //anisotropy trips up reuse error_estimator.estimate_error (system, error); } else if (indicator_type == "kelly") { // The Kelly error estimator is based on // an error bound for the Poisson problem // on linear elements, but is useful for // driving adaptive refinement in many problems KellyErrorEstimator error_estimator; error_estimator.estimate_error (system, error); } // Write out the error distribution if(write_error){ std::ostringstream ss; ss << r_step; #ifdef LIBMESH_HAVE_EXODUS_API std::string error_output = "error_"+ss.str()+".e"; #else std::string error_output = "error_"+ss.str()+".gmv"; #endif error.plot_error( error_output, mesh ); } // This takes the error in \p error and decides which elements // will be coarsened or refined. if(flag_by_elem_frac) mesh_refinement.flag_elements_by_elem_fraction(error); else mesh_refinement.flag_elements_by_error_fraction (error); // This call actually refines and coarsens the flagged // elements. mesh_refinement.refine_and_coarsen_elements(); // This call reinitializes the \p EquationSystems object for // the newly refined mesh. One of the steps in the // reinitialization is projecting the \p solution, // \p old_solution, etc... vectors from the old mesh to // the current one. equation_systems.reinit (); std::cout << "System has: " << equation_systems.n_active_dofs() << " degrees of freedom." << std::endl; } //end refinement loop //use that final refinement for (unsigned int t_step=0; t_step != n_timesteps; ++t_step) { std::cout << "\n\nSolving time step " << t_step << ", time = " << system.time << std::endl; system.solve(); system.postprocess(); Number QoI_computed = system.get_QoI_value("computed", 0); std::cout<< "Computed QoI is " << std::setprecision(17) << QoI_computed << std::endl; // Advance to the next timestep in a transient problem system.time_solver->advance_timestep(); } //end stepping through time loop #ifdef LIBMESH_HAVE_EXODUS_API for (unsigned int t_step=0; t_step != n_timesteps; ++t_step) { // Write out this timestep if we're requested to if ((t_step+1)%write_interval == 0) { std::ostringstream ex_file_name; std::ostringstream tplot_file_name; // We write the file in the ExodusII format. //ex_file_name << "out_" // << std::setw(3) // << std::setfill('0') // << std::right // << t_step+1 // << ".e"; tplot_file_name << "out_" << std::setw(3) << std::setfill('0') << std::right << t_step+1 << ".plt"; //ExodusII_IO(mesh).write_timestep(ex_file_name.str(), // equation_systems, // 1, /* This number indicates how many time steps // are being written to the file */ // system.time); exodusIO.write_timestep("output.exo", equation_systems, t_step+1, system.time); //outputs all timesteps in one file TecplotIO(mesh).write_equation_systems(tplot_file_name.str(), equation_systems); } } #endif // #ifdef LIBMESH_HAVE_EXODUS_API // All done. return 0; } //end main