main(int argc, char* argv[]){ static vec u(M+1), utp1(M+1), utp2(M+1); static vec sol(M+1); int k,n; std::string op=argv[1]; init(u,sol); val dx=1.0/M, tn, dt=T/N, dx2=dx*dx, up, un; val r=NU*dt/dx2; // r = nu*dt/dx^2 for(n=1;n<=N;n++){ utp2=u; // u^n-1 tn=n*dt; u(0)=0.0; // a(tn) for(k=1;k<M;k++){ up=u(k-1); un=u(k+1); if(n==1) u(k)=exact_sol(k*dx,tn); else u(k)=utp1(k)+2*r*(un-2*u(k)+up); // u_k = 2*r*(u_k+1 - 2*u_k + u_k-1) sol(k)=exact_sol(k*dx,tn); } utp1=utp2; u(M)= 0.0; // b(tn) output(tn, dx, u, sol, op); } return 0; }
// Exact solution. scalar3 exact(double x, double y, double z, scalar3 &dx, scalar3 &dy, scalar3 &dz) { scalar3 ex(0.0, 0.0, 0.0); exact_sol(x, y, z, ex[0], ex[1], dx[1], dy[0]); return ex; }
int run( char* argv[], GRINS::Runner & grins ) { grins.init(); grins.run(); GRINS::Simulation & sim = grins.get_simulation(); // Get equation systems to create ExactSolution object std::shared_ptr<libMesh::EquationSystems> es = sim.get_equation_system(); //es->write("foobar.xdr"); // Create Exact solution object and attach exact solution quantities libMesh::ExactSolution exact_sol(*es); libMesh::EquationSystems es_ref( es->get_mesh() ); // Filename of file where comparison solution is stashed std::string solution_file = std::string(argv[2]); es_ref.read( solution_file ); exact_sol.attach_reference_solution( &es_ref ); // Compute error and get it in various norms exact_sol.compute_error("StretchedElasticSheet", "u"); exact_sol.compute_error("StretchedElasticSheet", "v"); exact_sol.compute_error("StretchedElasticSheet", "w"); double u_l2error = exact_sol.l2_error("StretchedElasticSheet", "u"); double u_h1error = exact_sol.h1_error("StretchedElasticSheet", "u"); double v_l2error = exact_sol.l2_error("StretchedElasticSheet", "v"); double v_h1error = exact_sol.h1_error("StretchedElasticSheet", "v"); double w_l2error = exact_sol.l2_error("StretchedElasticSheet", "w"); double w_h1error = exact_sol.h1_error("StretchedElasticSheet", "w"); int return_flag = 0; double tol = 5.0e-8; if( u_l2error > tol || u_h1error > tol || v_l2error > tol || v_h1error > tol || w_l2error > tol || w_h1error > tol ) { return_flag = 1; std::cout << "Tolerance exceeded for thermally driven flow test." << std::endl << "tolerance = " << tol << std::endl << "u l2 error = " << u_l2error << std::endl << "u h1 error = " << u_h1error << std::endl << "v l2 error = " << v_l2error << std::endl << "v h1 error = " << v_h1error << std::endl << "w l2 error = " << w_l2error << std::endl << "w h1 error = " << w_h1error << std::endl; } return return_flag; }
// Exact solution. scalar3 &exact(double x, double y, double z, scalar3 &dx, scalar3 &dy, scalar3 &dz) { static scalar3 ex; ex[0] = ex[1] = ex[2] = 0; exact_sol(x, y, z, ex[0], ex[1], dx[1], dy[0]); return ex; }
void init(vec &u, vec &sol){ int k; val dx=1.0/M, xk; for(k=0;k<=M;k++){ xk=k*dx; u(k)=f(xk); sol(k)=exact_sol(xk,0); } }
scalar2 exact(double x, double y, scalar2& dx, scalar2& dy) { static scalar2 ex(0.0, 0.0); exact_sol(x,y, ex[0], ex[1], dx[1], dy[0]); dx[0] = 0.0; // not important dy[1] = 0.0; // not important return ex; }
int main(int argc, char* argv[]) { #ifdef GRINS_USE_GRVY_TIMERS GRVY::GRVY_Timer_Class grvy_timer; grvy_timer.Init("GRINS Timer"); #endif // Check command line count. if( argc < 2 ) { // TODO: Need more consistent error handling. std::cerr << "Error: Must specify libMesh input file." << std::endl; exit(1); // TODO: something more sophisticated for parallel runs? } // libMesh input file should be first argument std::string libMesh_input_filename = argv[1]; // Create our GetPot object. GetPot libMesh_inputfile( libMesh_input_filename ); #ifdef GRINS_USE_GRVY_TIMERS grvy_timer.BeginTimer("Initialize Solver"); #endif // Initialize libMesh library. libMesh::LibMeshInit libmesh_init(argc, argv); GRINS::SimulationBuilder sim_builder; GRINS::SharedPtr<GRINS::BoundaryConditionsFactory> bc_factory( new ParabolicBCFactory ); sim_builder.attach_bc_factory(bc_factory); GRINS::Simulation grins( libMesh_inputfile, sim_builder, libmesh_init.comm() ); #ifdef GRINS_USE_GRVY_TIMERS grvy_timer.EndTimer("Initialize Solver"); // Attach GRVY timer to solver grins.attach_grvy_timer( &grvy_timer ); #endif // Solve grins.run(); // Get equation systems to create ExactSolution object GRINS::SharedPtr<libMesh::EquationSystems> es = grins.get_equation_system(); // Create Exact solution object and attach exact solution quantities libMesh::ExactSolution exact_sol(*es); exact_sol.attach_exact_value(&exact_solution); exact_sol.attach_exact_deriv(&exact_derivative); // Compute error and get it in various norms exact_sol.compute_error("GRINS", "u"); double l2error = exact_sol.l2_error("GRINS", "u"); double h1error = exact_sol.h1_error("GRINS", "u"); int return_flag = 0; const double tol = 1.0e-8; if( l2error > tol || h1error > tol ) { return_flag = 1; std::cout << "Tolerance exceeded for velocity in Poiseuille test." << std::endl << "l2 error = " << l2error << std::endl << "h1 error = " << h1error << std::endl; } // Compute error and get it in various norms exact_sol.compute_error("GRINS", "p"); l2error = exact_sol.l2_error("GRINS", "p"); h1error = exact_sol.h1_error("GRINS", "p"); if( l2error > tol || h1error > tol ) { return_flag = 1; std::cout << "Tolerance exceeded for pressure in Poiseuille test." << std::endl << "l2 error = " << l2error << std::endl << "h1 error = " << h1error << std::endl; } return return_flag; }
int main(int argc, char* argv[]) { #ifdef GRINS_USE_GRVY_TIMERS GRVY::GRVY_Timer_Class grvy_timer; grvy_timer.Init("GRINS Timer"); #endif // Check command line count. if( argc < 3 ) { // TODO: Need more consistent error handling. std::cerr << "Error: Must specify libMesh input file and solution file." << std::endl; exit(1); // TODO: something more sophisticated for parallel runs? } // libMesh input file should be first argument std::string libMesh_input_filename = argv[1]; // Create our GetPot object. GetPot libMesh_inputfile( libMesh_input_filename ); #ifdef GRINS_USE_GRVY_TIMERS grvy_timer.BeginTimer("Initialize Solver"); #endif // Initialize libMesh library. libMesh::LibMeshInit libmesh_init(argc, argv); GRINS::SimulationBuilder sim_builder; sim_builder.attach_bc_factory( GRINS::SharedPtr<GRINS::BoundaryConditionsFactory>( new GRINS::ThermallyDrivenFlowTestBCFactory( libMesh_inputfile ) ) ); GRINS::Simulation grins( libMesh_inputfile, sim_builder, libmesh_init.comm() ); #ifdef GRINS_USE_GRVY_TIMERS grvy_timer.EndTimer("Initialize Solver"); // Attach GRVY timer to solver grins.attach_grvy_timer( &grvy_timer ); #endif // Do solve here grins.run(); // Get equation systems to create ExactSolution object GRINS::SharedPtr<libMesh::EquationSystems> es = grins.get_equation_system(); //es->write("foobar.xdr"); // Create Exact solution object and attach exact solution quantities libMesh::ExactSolution exact_sol(*es); libMesh::EquationSystems es_ref( es->get_mesh() ); // Filename of file where comparison solution is stashed std::string solution_file = std::string(argv[2]); es_ref.read( solution_file ); exact_sol.attach_reference_solution( &es_ref ); // Compute error and get it in various norms exact_sol.compute_error("GRINS", "u"); exact_sol.compute_error("GRINS", "v"); if( (es->get_mesh()).mesh_dimension() == 3 ) exact_sol.compute_error("GRINS", "w"); exact_sol.compute_error("GRINS", "p"); exact_sol.compute_error("GRINS", "T"); double u_l2error = exact_sol.l2_error("GRINS", "u"); double u_h1error = exact_sol.h1_error("GRINS", "u"); double v_l2error = exact_sol.l2_error("GRINS", "v"); double v_h1error = exact_sol.h1_error("GRINS", "v"); double p_l2error = exact_sol.l2_error("GRINS", "p"); double p_h1error = exact_sol.h1_error("GRINS", "p"); double T_l2error = exact_sol.l2_error("GRINS", "T"); double T_h1error = exact_sol.h1_error("GRINS", "T"); double w_l2error = 0.0, w_h1error = 0.0; if( (es->get_mesh()).mesh_dimension() == 3 ) { w_l2error = exact_sol.l2_error("GRINS", "w"); w_h1error = exact_sol.h1_error("GRINS", "w"); } int return_flag = 0; // This is the tolerance of the iterative linear solver so // it's unreasonable to expect anything better than this. double tol = 8.0e-9; if( u_l2error > tol || u_h1error > tol || v_l2error > tol || v_h1error > tol || w_l2error > tol || w_h1error > tol || p_l2error > tol || p_h1error > tol || T_l2error > tol || T_h1error > tol ) { return_flag = 1; std::cout << "Tolerance exceeded for thermally driven flow test." << std::endl << "tolerance = " << tol << std::endl << "u l2 error = " << u_l2error << std::endl << "u h1 error = " << u_h1error << std::endl << "v l2 error = " << v_l2error << std::endl << "v h1 error = " << v_h1error << std::endl << "w l2 error = " << w_l2error << std::endl << "w h1 error = " << w_h1error << std::endl << "p l2 error = " << p_l2error << std::endl << "p h1 error = " << p_h1error << std::endl << "T l2 error = " << T_l2error << std::endl << "T h1 error = " << T_h1error << std::endl; } return return_flag; }
int run( int argc, char* argv[], const GetPot& input ) { // Initialize libMesh library. libMesh::LibMeshInit libmesh_init(argc, argv); GRINS::SimulationBuilder sim_builder; std::tr1::shared_ptr<GRINS::BoundaryConditionsFactory> bc_factory( new NitridationCalibration::BoundaryConditionsFactory(input) ); sim_builder.attach_bc_factory( bc_factory ); std::tr1::shared_ptr<GRINS::QoIFactory> qoi_factory( new NitridationCalibration::QoIFactory ); sim_builder.attach_qoi_factory( qoi_factory ); GRINS::Simulation grins( input, sim_builder, libmesh_init.comm()); //FIXME: We need to move this to within the Simulation object somehow... std::string restart_file = input( "restart-options/restart_file", "none" ); std::tr1::shared_ptr<NitridationCalibration::TubeTempBC> wall_temp; std::string system_name = input( "screen-options/system_name", "GRINS" ); if( restart_file == "none" ) { // Asssign initial temperature value std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system(); const libMesh::System& system = es->get_system(system_name); libMesh::Parameters ¶ms = es->parameters; libMesh::Real& w_N2 = params.set<libMesh::Real>( "w_N2" ); w_N2 = input( "Physics/ReactingLowMachNavierStokes/bound_species_1", 0.0, 0 ); libMesh::Real& w_N = params.set<libMesh::Real>( "w_N" ); w_N = input( "Physics/ReactingLowMachNavierStokes/bound_species_1", 0.0, 1 ); wall_temp.reset( new NitridationCalibration::TubeTempBC( input ) ); std::tr1::shared_ptr<NitridationCalibration::TubeTempBC>& dummy = params.set<std::tr1::shared_ptr<NitridationCalibration::TubeTempBC> >( "wall_temp" ); dummy = wall_temp; system.project_solution( initial_values, NULL, params ); } grins.run(); // Get equation systems to create ExactSolution object std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system(); //es->write("foobar.xdr"); // Create Exact solution object and attach exact solution quantities libMesh::ExactSolution exact_sol(*es); libMesh::EquationSystems es_ref( es->get_mesh() ); // Filename of file where comparison solution is stashed std::string solution_file = std::string(argv[2]); es_ref.read( solution_file ); exact_sol.attach_reference_solution( &es_ref ); // Compute error and get it in various norms exact_sol.compute_error(system_name, "u"); exact_sol.compute_error(system_name, "v"); if( (es->get_mesh()).mesh_dimension() == 3 ) exact_sol.compute_error(system_name, "w"); exact_sol.compute_error(system_name, "p"); exact_sol.compute_error(system_name, "T"); exact_sol.compute_error(system_name, "w_N2"); exact_sol.compute_error(system_name, "w_N"); exact_sol.compute_error(system_name, "w_CN"); double u_l2error = exact_sol.l2_error(system_name, "u"); double u_h1error = exact_sol.h1_error(system_name, "u"); double v_l2error = exact_sol.l2_error(system_name, "v"); double v_h1error = exact_sol.h1_error(system_name, "v"); double p_l2error = exact_sol.l2_error(system_name, "p"); double p_h1error = exact_sol.h1_error(system_name, "p"); double T_l2error = exact_sol.l2_error(system_name, "T"); double T_h1error = exact_sol.h1_error(system_name, "T"); double wN_l2error = exact_sol.l2_error(system_name, "w_N"); double wN_h1error = exact_sol.h1_error(system_name, "w_N"); double wN2_l2error = exact_sol.l2_error(system_name, "w_N2"); double wN2_h1error = exact_sol.h1_error(system_name, "w_N2"); double wCN_l2error = exact_sol.l2_error(system_name, "w_CN"); double wCN_h1error = exact_sol.h1_error(system_name, "w_CN"); double w_l2error = 0.0, w_h1error = 0.0; if( (es->get_mesh()).mesh_dimension() == 3 ) { w_l2error = exact_sol.l2_error(system_name, "w"); w_h1error = exact_sol.h1_error(system_name, "w"); } int return_flag = 0; // This is the tolerance of the iterative linear solver so // it's unreasonable to expect anything better than this. double tol = 5.0e-10; if( u_l2error > tol || u_h1error > tol || v_l2error > tol || v_h1error > tol || w_l2error > tol || w_h1error > tol || p_l2error > tol || p_h1error > tol || T_l2error > tol || T_h1error > tol || wN_l2error > tol || wN_h1error > tol || wN2_l2error > tol || wN2_h1error > tol || wCN_l2error > tol || wCN_h1error > tol ) { return_flag = 1; std::cout << "Tolerance exceeded for solution fields." << std::endl << "tolerance = " << tol << std::endl << "u l2 error = " << u_l2error << std::endl << "u h1 error = " << u_h1error << std::endl << "v l2 error = " << v_l2error << std::endl << "v h1 error = " << v_h1error << std::endl << "w l2 error = " << w_l2error << std::endl << "w h1 error = " << w_h1error << std::endl << "p l2 error = " << p_l2error << std::endl << "p h1 error = " << p_h1error << std::endl << "T l2 error = " << T_l2error << std::endl << "T h1 error = " << T_h1error << std::endl << "w_N l2 error = " << wN_l2error << std::endl << "w_N h1 error = " << wN_h1error << std::endl << "w_N2 l2 error = " << wN2_l2error << std::endl << "w_N2 h1 error = " << wN2_h1error << std::endl << "w_CN l2 error = " << wCN_l2error << std::endl << "w_CN h1 error = " << wCN_h1error << std::endl; } // Now test QoI Values const libMesh::Real mass_loss_reg = atof(argv[3]); const libMesh::Real avg_N_reg = atof(argv[4]); /* The value we compute is negative by convention, but the data are given as positive by convention, so convert to data convention. */ const libMesh::Real mass_loss_comp = std::fabs(grins.get_qoi_value(0)); const libMesh::Real avg_N_comp = grins.get_qoi_value(1); const double qoi_tol = 1.0e-9; const double mass_loss_error = std::fabs( (mass_loss_comp - mass_loss_reg)/mass_loss_reg ); const double avg_N_error = std::fabs( (avg_N_comp - avg_N_reg)/avg_N_reg ); if( mass_loss_error > qoi_tol || avg_N_error > qoi_tol ) { return_flag = 1; std::cout << "Tolerance exceeded for qoi values." << std::endl << "tolerance = " << qoi_tol << std::endl << "mass loss = " << mass_loss_comp << std::endl << "avg N = " << avg_N_comp << std::endl << "mass loss error = " << mass_loss_error << std::endl << "avg N error = " << avg_N_error << std::endl; } return return_flag; }
int main(int argc, char **args) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H3DReader mloader; mloader.load("lshape_hex.mesh3d", &mesh); // Perform initial mesh refinement. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ); // Create an Hcurl space with default shapeset. HcurlSpace space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(biform<double, scalar>, biform<Ord, Ord>, HERMES_SYM); wf.add_matrix_form_surf(biform_surf, biform_surf_ord); wf.add_vector_form_surf(liform_surf, liform_surf_ord); // Set exact solution. ExactSolution exact_sol(&mesh, exact); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Adaptivity loop. int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space, 1); // Initialize discrete problem. bool is_linear = true; DiscreteProblem dp(&wf, ref_space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the reference problem. info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space)); dp.assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system on reference mesh. If successful, obtain the solution. info("Solving on reference mesh."); Solution ref_sln(ref_space->get_mesh()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the reference solution on the coarse mesh. Solution sln(space.get_mesh()); info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver, HERMES_HCURL_NORM); // Time measurement. cpu_time.tick(); // Output solution and mesh with polynomial orders. if (solution_output) { out_fn_vtk(&sln, "sln", as); out_orders_vtk(&space, "order", as); } // Skip the visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_HCURL_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt) * 100; // Calculate exact error. solutions_for_adapt = false; double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact_sol, solutions_for_adapt) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%.", err_est_rel, err_exact_rel); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est_rel is too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); adaptivity->adapt(THRESHOLD); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete ref_space->get_mesh(); delete ref_space; delete matrix; delete rhs; delete solver; delete adaptivity; // Increase the counter of performed adaptivity steps. as++; } while (!done); return 0; }
int run( int argc, char* argv[], const GetPot& input, GetPot& command_line ) { // Initialize libMesh library. libMesh::LibMeshInit libmesh_init(argc, argv); GRINS::SimulationBuilder sim_builder; GRINS::Simulation grins( input, sim_builder, libmesh_init.comm() ); //FIXME: We need to move this to within the Simulation object somehow... std::string restart_file = input( "restart-options/restart_file", "none" ); if( restart_file == "none" ) { // Asssign initial temperature value std::string system_name = input( "screen-options/system_name", "GRINS" ); std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system(); const libMesh::System& system = es->get_system(system_name); libMesh::Parameters ¶ms = es->parameters; libMesh::Real& w_N2 = params.set<libMesh::Real>( "w_N2" ); w_N2 = input( "Physics/ReactingLowMachNavierStokes/bound_species_0", 0.0, 0.0 ); libMesh::Real& w_N = params.set<libMesh::Real>( "w_N" ); w_N = input( "Physics/ReactingLowMachNavierStokes/bound_species_0", 0.0, 1.0 ); system.project_solution( initial_values, NULL, params ); } grins.run(); // Get equation systems to create ExactSolution object std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system(); // Create Exact solution object and attach exact solution quantities libMesh::ExactSolution exact_sol(*es); libMesh::EquationSystems es_ref( es->get_mesh() ); // Filename of file where comparison solution is stashed std::string solution_file = command_line("soln-data", "DIE!"); es_ref.read( solution_file ); exact_sol.attach_reference_solution( &es_ref ); // Now grab the variables for which we want to compare unsigned int n_vars = command_line.vector_variable_size("vars"); std::vector<std::string> vars(n_vars); for( unsigned int v = 0; v < n_vars; v++ ) { vars[v] = command_line("vars", "DIE!", v); } // Now grab the norms to compute for each variable error unsigned int n_norms = command_line.vector_variable_size("norms"); std::vector<std::string> norms(n_norms); for( unsigned int n = 0; n < n_norms; n++ ) { norms[n] = command_line("norms", "DIE!", n); if( norms[n] != std::string("L2") && norms[n] != std::string("H1") ) { std::cerr << "ERROR: Invalid norm input " << norms[n] << std::endl << " Valid values are: L2" << std::endl << " H1" << std::endl; } } const std::string& system_name = grins.get_multiphysics_system_name(); // Now compute error for each variable for( unsigned int v = 0; v < n_vars; v++ ) { exact_sol.compute_error(system_name, vars[v]); } int return_flag = 0; double tol = command_line("tol", 1.0e-10); // Now test error for each variable, for each norm for( unsigned int v = 0; v < n_vars; v++ ) { for( unsigned int n = 0; n < n_norms; n++ ) { test_error_norm( exact_sol, system_name, vars[v], norms[n], tol, return_flag ); } } return return_flag; }
int main(int argc, char* argv[]) { // Check command line count. if( argc < 4 ) { // TODO: Need more consistent error handling. std::cerr << "Error: Must specify libMesh input file, regression file, and regression tolerance." << std::endl; exit(1); // TODO: something more sophisticated for parallel runs? } // libMesh input file should be first argument std::string libMesh_input_filename = argv[1]; // Create our GetPot object. GetPot libMesh_inputfile( libMesh_input_filename ); // Initialize libMesh library. LibMeshInit libmesh_init(argc, argv); GRINS::SimulationBuilder sim_builder; GRINS::Simulation grins( libMesh_inputfile, sim_builder, libmesh_init.comm() ); grins.run(); // Get equation systems to create ExactSolution object std::tr1::shared_ptr<EquationSystems> es = grins.get_equation_system(); //es->write("foobar.xdr"); // Create Exact solution object and attach exact solution quantities ExactSolution exact_sol(*es); EquationSystems es_ref( es->get_mesh() ); // Filename of file where comparison solution is stashed std::string solution_file = std::string(argv[2]); es_ref.read( solution_file ); exact_sol.attach_reference_solution( &es_ref ); std::string system_name = libMesh_inputfile( "screen-options/system_name", "GRINS" ); // Compute error and get it in various norms exact_sol.compute_error(system_name, "u"); exact_sol.compute_error(system_name, "v"); exact_sol.compute_error(system_name, "p"); double u_l2error = exact_sol.l2_error(system_name, "u"); double u_h1error = exact_sol.h1_error(system_name, "u"); double v_l2error = exact_sol.l2_error(system_name, "v"); double v_h1error = exact_sol.h1_error(system_name, "v"); double p_l2error = exact_sol.l2_error(system_name, "p"); double p_h1error = exact_sol.h1_error(system_name, "p"); int return_flag = 0; // This is the tolerance of the iterative linear solver so // it's unreasonable to expect anything better than this. double tol = atof(argv[3]); if( u_l2error > tol || u_h1error > tol || v_l2error > tol || v_h1error > tol || p_l2error > tol || p_h1error > tol ) { return_flag = 1; std::cout << "Tolerance exceeded for thermally driven flow test." << std::endl << "tolerance = " << tol << std::endl << "u l2 error = " << u_l2error << std::endl << "u h1 error = " << u_h1error << std::endl << "v l2 error = " << v_l2error << std::endl << "v h1 error = " << v_h1error << std::endl << "p l2 error = " << p_l2error << std::endl << "p h1 error = " << p_h1error << std::endl; } return return_flag; }
// exact solution scalar2& exact(double x, double y, scalar2& dx, scalar2& dy) { static scalar2 ex; exact_sol(x,y, ex[0], ex[1], dx[1], dy[0]); return ex; }
int main() { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Create coarse mesh, set Dirichlet BC, enumerate basis functions. Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, DIR_BC_RIGHT, P_INIT, NEQ); // Enumerate basis functions, info for user. int ndof = Space::get_num_dofs(space); info("ndof: %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(jacobian); wf.add_vector_form(residual); // Initialize the FE problem. bool is_linear = false; DiscreteProblem *dp_coarse = new DiscreteProblem(&wf, space, is_linear); if(JFNK == 0) { // Newton's loop on coarse mesh. // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec_coarse = new double[Space::get_num_dofs(space)]; get_coeff_vector(space, coeff_vec_coarse); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof_coarse = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp_coarse->assemble(coeff_vec_coarse, matrix_coarse, rhs_coarse); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs_coarse); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL_COARSE && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i = 0; i < ndof_coarse; i++) rhs_coarse->set(i, -rhs_coarse->get(i)); // Solve the linear system. if(!solver_coarse->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof_coarse; i++) coeff_vec_coarse[i] += solver_coarse->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec_coarse, space); it++; } // Cleanup. delete matrix_coarse; delete rhs_coarse; delete solver_coarse; delete [] coeff_vec_coarse; } else jfnk_cg(dp_coarse, space, MATRIX_SOLVER_TOL, MATRIX_SOLVER_MAXITER, JFNK_EPSILON, NEWTON_TOL_COARSE, NEWTON_MAX_ITER, matrix_solver); // Cleanup. delete dp_coarse; // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; SimpleGraph graph_dof_exact, graph_cpu_exact; // Adaptivity loop: int as = 1; double ftr_errors[MAX_ELEM_NUM]; // This array decides what // elements will be refined. bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(space); // Initialize the FE problem. bool is_linear = false; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); if(JFNK == 0) { // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Newton's loop on the fine mesh. info("Solving on fine mesh:"); // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec = new double[Space::get_num_dofs(ref_space)]; get_coeff_vector(ref_space, coeff_vec); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(ref_space); // Assemble the Jacobian matrix and residual vector. dp->assemble(coeff_vec, matrix, rhs); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(ref_space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL_REF && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i = 0; i < ndof; i++) rhs->set(i, -rhs->get(i)); // Solve the linear system. if(!solver->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec, ref_space); it++; } // Cleanup. delete matrix; delete rhs; delete solver; delete [] coeff_vec; } else jfnk_cg(dp, ref_space, MATRIX_SOLVER_TOL, MATRIX_SOLVER_MAXITER, JFNK_EPSILON, NEWTON_TOL_COARSE, NEWTON_MAX_ITER, matrix_solver); // Cleanup. delete dp; // Starting with second adaptivity step, obtain new coarse // mesh solution via projecting the fine mesh solution. if(as > 1) { info("Projecting the fine mesh solution onto the coarse mesh."); // Project the fine mesh solution (defined on space_ref) onto the coarse mesh (defined on space). OGProjection::project_global(space, ref_space, matrix_solver); } double max_qoi_err_est = 0; for (int i=0; i < space->get_n_active_elem(); i++) { if (GOAL_ORIENTED == 1) { // Use quantity of interest. double qoi_est = quantity_of_interest(space, X_QOI); double qoi_ref_est = quantity_of_interest(ref_space, X_QOI); ftr_errors[i] = fabs(qoi_ref_est - qoi_est); } else { // Use global norm double err_est_array[MAX_ELEM_NUM]; ftr_errors[i] = calc_err_est(NORM, space, ref_space, err_est_array); } // Info for user. info("Elem [%d]: absolute error (est) = %g%%", i, ftr_errors[i]); // Time measurement. cpu_time.tick(); // Calculating maximum of QOI FTR error for plotting purposes if (GOAL_ORIENTED == 1) { if (ftr_errors[i] > max_qoi_err_est) max_qoi_err_est = ftr_errors[i]; } else { double qoi_est = quantity_of_interest(space, X_QOI); double qoi_ref_est = quantity_of_interest(ref_space, X_QOI); double err_est = fabs(qoi_ref_est - qoi_est); if (err_est > max_qoi_err_est) max_qoi_err_est = err_est; } } // Add entries to convergence graphs. if (EXACT_SOL_PROVIDED) { double qoi_est = quantity_of_interest(space, X_QOI); double u[MAX_EQN_NUM], dudx[MAX_EQN_NUM]; exact_sol(X_QOI, u, dudx); double err_qoi_exact = fabs(u[0] - qoi_est); // Info for user. info("Relative error (exact) = %g %%", err_qoi_exact); // Add entry to DOF and CPU convergence graphs. graph_dof_exact.add_values(Space::get_num_dofs(space), err_qoi_exact); graph_cpu_exact.add_values(cpu_time.accumulated(), err_qoi_exact); } // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(space), max_qoi_err_est); graph_cpu_est.add_values(cpu_time.accumulated(), max_qoi_err_est); // Decide whether the max. FTR error in the quantity of interest // is sufficiently small. if(max_qoi_err_est < TOL_ERR_QOI) break; // Returns updated coarse and fine meshes, with the last // coarse and fine mesh solutions on them, respectively. // The coefficient vectors and numbers of degrees of freedom // on both meshes are also updated. adapt(NORM, ADAPT_TYPE, THRESHOLD, ftr_errors, space, ref_space); as++; // Plot meshes, results, and errors. adapt_plotting(space, ref_space, NORM, EXACT_SOL_PROVIDED, exact_sol); // Cleanup. delete ref_space; } while (done == false); info("Total running time: %g s", cpu_time.accumulated()); // Save convergence graphs. graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.save("conv_cpu_exact.dat"); // Test variable. bool success = true; info("ndof = %d.", Space::get_num_dofs(space)); if (Space::get_num_dofs(space) > 150) success = false; if (success) { info("Success!"); return ERROR_SUCCESS; } else { info("Failure!"); return ERROR_FAILURE; } }
int main() { // Create coarse mesh, set Dirichlet BC, enumerate // basis functions Mesh *mesh = new Mesh(A, B, N_elem, P_init, N_eq); mesh->set_bc_left_dirichlet(0, Val_dir_left); mesh->set_bc_right_dirichlet(0, Val_dir_right); mesh->assign_dofs(); // Create discrete problem on coarse mesh DiscreteProblem *dp = new DiscreteProblem(); dp->add_matrix_form(0, 0, jacobian); dp->add_vector_form(0, residual); // Convergence graph wrt. the number of degrees of freedom // (goal-oriented adaptivity) GnuplotGraph graph_ftr; graph_ftr.set_log_y(); graph_ftr.set_captions("Convergence History", "Degrees of Freedom", "QOI error"); graph_ftr.add_row("QOI error - FTR (exact)", "k", "-", "o"); graph_ftr.add_row("QOI error - FTR (est)", "k", "--"); // Main adaptivity loop int adapt_iterations = 1; double ftr_errors[MAX_ELEM_NUM]; // This array decides what // elements will be refined. ElemPtr2 ref_ftr_pairs[MAX_ELEM_NUM]; // To store element pairs from the // FTR solution. Decides how // elements will be hp-refined. for (int i=0; i < MAX_ELEM_NUM; i++) { ref_ftr_pairs[i][0] = new Element(); ref_ftr_pairs[i][1] = new Element(); } while(1) { printf("============ Adaptivity step %d ============\n", adapt_iterations); printf("N_dof = %d\n", mesh->get_n_dof()); // Newton's loop on coarse mesh int success; if(JFNK == 0) { newton(dp, mesh, NULL, NEWTON_TOL_COARSE, NEWTON_MAXITER); } else { jfnk_cg(dp, mesh, MATRIX_SOLVER_TOL, MATRIX_SOLVER_MAXITER, JFNK_EPSILON, NEWTON_TOL_COARSE, NEWTON_MAXITER); } // For every element perform its fast trial refinement (FTR), // calculate the norm of the difference between the FTR // solution and the coarse mesh solution, and store the // error in the ftr_errors[] array. int n_elem = mesh->get_n_active_elem(); double max_qoi_err_est = 0; for (int i=0; i < n_elem; i++) { printf("=== Starting FTR of Elem [%d]\n", i); // Replicate coarse mesh including solution. Mesh *mesh_ref_local = mesh->replicate(); // Perform FTR of element 'i' mesh_ref_local->reference_refinement(i, 1); printf("Elem [%d]: fine mesh created (%d DOF).\n", i, mesh_ref_local->assign_dofs()); // Newton's loop on the FTR mesh if(JFNK == 0) { newton(dp, mesh_ref_local, NULL, NEWTON_TOL_COARSE, NEWTON_MAXITER); } else { jfnk_cg(dp, mesh_ref_local, MATRIX_SOLVER_TOL, MATRIX_SOLVER_MAXITER, JFNK_EPSILON, NEWTON_TOL_REF, NEWTON_MAXITER); } // Print FTR solution (enumerated) Linearizer *lxx = new Linearizer(mesh_ref_local); char out_filename[255]; sprintf(out_filename, "solution_ref_%d.gp", i); lxx->plot_solution(out_filename); delete lxx; // Calculate FTR errors for refinement purposes if (GOAL_ORIENTED == 1) { // Use quantity of interest. double qoi_est = quantity_of_interest(mesh, X_QOI); double qoi_ref_est = quantity_of_interest(mesh_ref_local, X_QOI); ftr_errors[i] = fabs(qoi_ref_est - qoi_est); } else { // Use global norm double err_est_array[MAX_ELEM_NUM]; ftr_errors[i] = calc_error_estimate(NORM, mesh, mesh_ref_local, err_est_array); } // Calculating maximum of QOI FTR error for plotting purposes if (GOAL_ORIENTED == 1) { if (ftr_errors[i] > max_qoi_err_est) max_qoi_err_est = ftr_errors[i]; } else { double qoi_est = quantity_of_interest(mesh, X_QOI); double qoi_ref_est = quantity_of_interest(mesh_ref_local, X_QOI); double err_est = fabs(qoi_ref_est - qoi_est); if (err_est > max_qoi_err_est) max_qoi_err_est = err_est; } // Copy the reference element pair for element 'i' // into the ref_ftr_pairs[i][] array Iterator *I = new Iterator(mesh); Iterator *I_ref = new Iterator(mesh_ref_local); Element *e, *e_ref; while (1) { e = I->next_active_element(); e_ref = I_ref->next_active_element(); if (e->id == i) { e_ref->copy_into(ref_ftr_pairs[e->id][0]); // coarse element 'e' was split in space if (e->level != e_ref->level) { e_ref = I_ref->next_active_element(); e_ref->copy_into(ref_ftr_pairs[e->id][1]); } break; } } delete I; delete I_ref; delete mesh_ref_local; } // Add entries to convergence graphs if (EXACT_SOL_PROVIDED) { double qoi_est = quantity_of_interest(mesh, X_QOI); double u[MAX_EQN_NUM], dudx[MAX_EQN_NUM]; exact_sol(X_QOI, u, dudx); double err_qoi_exact = fabs(u[0] - qoi_est); // plotting error in quantity of interest wrt. exact value graph_ftr.add_values(0, mesh->get_n_dof(), err_qoi_exact); } graph_ftr.add_values(1, mesh->get_n_dof(), max_qoi_err_est); // Decide whether the max. FTR error in the quantity of interest // is sufficiently small if(max_qoi_err_est < TOL_ERR_QOI) break; // debug if (adapt_iterations == 3) break; // Returns updated coarse mesh with the last solution on it. adapt(NORM, ADAPT_TYPE, THRESHOLD, ftr_errors, mesh, ref_ftr_pairs); adapt_iterations++; } // Plot meshes, results, and errors adapt_plotting(mesh, ref_ftr_pairs, NORM, EXACT_SOL_PROVIDED, exact_sol); // Save convergence graph graph_ftr.save("conv_dof.gp"); printf("Done.\n"); return 1; }
int main(int argc, char* argv[]) { #ifdef GRINS_USE_GRVY_TIMERS GRVY::GRVY_Timer_Class grvy_timer; grvy_timer.Init("GRINS Timer"); #endif // Check command line count. if( argc < 3 ) { // TODO: Need more consistent error handling. std::cerr << "Error: Must specify libMesh input file." << std::endl; exit(1); // TODO: something more sophisticated for parallel runs? } // libMesh input file should be first argument std::string libMesh_input_filename = argv[1]; // Create our GetPot object. GetPot libMesh_inputfile( libMesh_input_filename ); // GetPot doesn't throw an error for a nonexistent file? { std::ifstream i(libMesh_input_filename.c_str()); if (!i) { std::cerr << "Error: Could not read from libMesh input file " << libMesh_input_filename << std::endl; exit(1); } } // Initialize libMesh library. libMesh::LibMeshInit libmesh_init(argc, argv); libMesh::out << "Starting GRINS with command:\n"; for (int i=0; i != argc; ++i) libMesh::out << argv[i] << ' '; libMesh::out << std::endl; GRINS::SimulationBuilder sim_builder; GRINS::Simulation grins( libMesh_inputfile, sim_builder, libmesh_init.comm() ); std::string system_name = libMesh_inputfile( "screen-options/system_name", "GRINS" ); // Get equation systems GRINS::SharedPtr<libMesh::EquationSystems> es = grins.get_equation_system(); const libMesh::System& system = es->get_system(system_name); libMesh::Parameters ¶ms = es->parameters; system.project_solution( initial_values, NULL, params ); grins.run(); //es->write("suspended_cable_test.xdr"); // Create Exact solution object and attach exact solution quantities libMesh::ExactSolution exact_sol(*es); libMesh::EquationSystems es_ref( es->get_mesh() ); // Filename of file where comparison solution is stashed std::string solution_file = std::string(argv[2]); es_ref.read( solution_file ); exact_sol.attach_reference_solution( &es_ref ); // Compute error and get it in various norms exact_sol.compute_error(system_name, "u"); exact_sol.compute_error(system_name, "v"); exact_sol.compute_error(system_name, "w"); double u_l2error = exact_sol.l2_error(system_name, "u"); double u_h1error = exact_sol.h1_error(system_name, "u"); double v_l2error = exact_sol.l2_error(system_name, "v"); double v_h1error = exact_sol.h1_error(system_name, "v"); double w_l2error = exact_sol.l2_error(system_name, "w"); double w_h1error = exact_sol.h1_error(system_name, "w"); int return_flag = 0; double tol = 5.0e-8; if( u_l2error > tol || u_h1error > tol || v_l2error > tol || v_h1error > tol || w_l2error > tol || w_h1error > tol ) { return_flag = 1; std::cout << "Tolerance exceeded for suspended cable test." << std::endl << "tolerance = " << tol << std::endl << "u l2 error = " << u_l2error << std::endl << "u h1 error = " << u_h1error << std::endl << "v l2 error = " << v_l2error << std::endl << "v h1 error = " << v_h1error << std::endl << "w l2 error = " << w_l2error << std::endl << "w h1 error = " << w_h1error << std::endl; } return return_flag; }