int main(int argc, char** argv) { // - Start libmesh --------------------------------------------------------- const bool MASTER_bPerfLog_carl_libmesh = true; libMesh::LibMeshInit init(argc, argv); libMesh::PerfLog perf_log("Main program", MASTER_bPerfLog_carl_libmesh); // - Displacement conditions ----------------------------------------------- // boundary_displacement x_max_BIG(1.0,0,0); // boundary_displacement x_min_BIG(-1.0,0,0); boundary_id_cube boundary_ids; // - Set up inputs GetPot command_line(argc, argv); GetPot field_parser; std::string input_filename; if (command_line.search(1, "--inputfile")) { input_filename = command_line.next(input_filename); field_parser.parse_input_file(input_filename, "#", "\n", " \t\n"); } else { field_parser = command_line; } carl::coupling_generation_input_params input_params; carl::get_input_params(field_parser, input_params); const unsigned int dim = 3; libmesh_example_requires(dim == LIBMESH_DIM, "3D support"); // Set up the communicator and the rank variables libMesh::Parallel::Communicator& WorldComm = init.comm(); libMesh::Parallel::Communicator LocalComm; int rank = WorldComm.rank(); int nodes = WorldComm.size(); WorldComm.split(rank,rank,LocalComm); // - Read the meshes ------------------------------------------------------- // - Parallelized meshes: A, B, mediator and weight perf_log.push("Meshes - Parallel","Read files:"); libMesh::Mesh mesh_BIG(WorldComm, dim); // mesh_BIG.allow_renumbering(false); mesh_BIG.read(input_params.mesh_BIG_file); mesh_BIG.prepare_for_use(); libMesh::Mesh mesh_micro(WorldComm, dim); // mesh_micro.allow_renumbering(false); mesh_micro.read(input_params.mesh_micro_file); mesh_micro.prepare_for_use(); libMesh::Mesh mesh_mediator(WorldComm, dim); mesh_mediator.allow_renumbering(false); mesh_mediator.read(input_params.mesh_mediator_file); mesh_mediator.prepare_for_use(); libMesh::Mesh mesh_weight(WorldComm, dim); mesh_weight.allow_renumbering(false); mesh_weight.read(input_params.mesh_weight_file); mesh_weight.prepare_for_use(); // // DEBUG - Test: print info per proc // { // std::ofstream mesh_info_ofstream; // mesh_info_ofstream.open("meshes/parallel_test/output/mesh_A_" + std::to_string(rank) + "_info.txt"); // mesh_BIG.print_info(mesh_info_ofstream); // mesh_info_ofstream.close(); // // WorldComm.barrier(); // // mesh_info_ofstream.open("meshes/parallel_test/output/mesh_B_" + std::to_string(rank) + "_info.txt"); // mesh_micro.print_info(mesh_info_ofstream); // mesh_info_ofstream.close(); // // WorldComm.barrier(); // // mesh_info_ofstream.open("meshes/parallel_test/output/mesh_inter_" + std::to_string(rank) + "_info.txt"); // mesh_inter.print_info(mesh_info_ofstream); // mesh_info_ofstream.close(); // // WorldComm.barrier(); // } perf_log.pop("Meshes - Parallel","Read files:"); // - Local meshes: restrict A and restrict B // -> libMesh's default mesh IS the SerialMesh, which creates a copy of // itself on each processor, but partitions the iterators over each // processor to allow the parallelization of the code. The usage of // ParallelMesh is still a bit risky, and, performance-wise, is worse // than SerialMesh for less than a few thousand processors. perf_log.push("Meshes - Serial","Read files:"); libMesh::ReplicatedMesh mesh_R_BIG(WorldComm, dim); mesh_R_BIG.allow_renumbering(false); mesh_R_BIG.read(input_params.mesh_restrict_BIG_file); mesh_R_BIG.prepare_for_use(); libMesh::ReplicatedMesh mesh_R_micro(WorldComm, dim); mesh_R_micro.allow_renumbering(false); mesh_R_micro.read(input_params.mesh_restrict_micro_file); mesh_R_micro.prepare_for_use(); // // DEBUG - Test: print info per proc // { // std::ofstream mesh_info_ofstream; // mesh_info_ofstream.open("meshes/parallel_test/output/mesh_RA_" + std::to_string(rank) + "_info.txt"); // mesh_R_BIG.print_info(mesh_info_ofstream); // mesh_info_ofstream.close(); // // WorldComm.barrier(); // // mesh_info_ofstream.open("meshes/parallel_test/output/mesh_RB_" + std::to_string(rank) + "_info.txt"); // mesh_R_micro.print_info(mesh_info_ofstream); // mesh_info_ofstream.close(); // // WorldComm.barrier(); // // mesh_info_ofstream.open("meshes/parallel_test/output/mesh_mediator_" + std::to_string(rank) + "_info.txt"); // mesh_mediator.print_info(mesh_info_ofstream); // mesh_info_ofstream.close(); // // std::ofstream mesh_data; // mesh_data.open("meshes/parallel_test/output/mesh_A_data_" + std::to_string(rank) + ".dat"); // libMesh::MeshBase::const_element_iterator el = mesh_BIG.active_local_elements_begin(); // const libMesh::MeshBase::const_element_iterator end_el = mesh_BIG.active_local_elements_end(); // // for ( ; el != end_el; ++el) // { // const libMesh::Elem* elem = *el; // mesh_data << elem->id() << " " << elem->point(0) << " " << elem->point(1) << " " << elem->point(2)<< " " << elem->point(3)<< std::endl; // } // mesh_data.close(); // } // - Local mesh: intersection mesh libMesh::Mesh mesh_inter(LocalComm, dim); mesh_inter.allow_renumbering(false); std::string local_inter_mesh_filename = input_params.mesh_inter_file + "_r_" + std::to_string(rank) + "_n_" + std::to_string(nodes) + ".e"; std::string local_inter_table_filename = input_params.intersection_table_full + "_r_" + std::to_string(rank) + "_n_" + std::to_string(nodes) + "_inter_table.dat"; std::string global_inter_table_filename = input_params.intersection_table_full + "_global_inter_pairs.dat"; mesh_inter.read(local_inter_mesh_filename); mesh_inter.prepare_for_use(); perf_log.pop("Meshes - Serial","Read files:"); /* * To do on the first proc * - Read and build the equivalence tables between R_X and X, e_X - DONE * - Read and build the intersection pairs table between A and B, p_AB - DONE * - Read and build the intersection indexes table, I_F - DONE * * Broadcast e_X, p_AB, I_F - DONE * * Build on each proc * - The restricted intersection pairs table, p_R,AB- DONE * - A local intersection indexes table, I_L - DONE * * Convert the pairs table to the libMesh indexing - DONE */ perf_log.push("Equivalence / intersection tables","Read files:"); std::unordered_map<int,std::pair<int,int> > local_intersection_pairs_map; std::unordered_map<int,std::pair<int,int> > local_intersection_restricted_pairs_map; std::unordered_map<int,int> local_intersection_meshI_to_inter_map; std::unordered_map<int,int> equivalence_table_BIG_to_R_BIG; std::unordered_map<int,int> equivalence_table_micro_to_R_micro; std::unordered_map<int,int> equivalence_table_R_BIG_to_BIG; std::unordered_map<int,int> equivalence_table_R_micro_to_micro; // Start by reading and broadcasting the equivalence tables carl::set_equivalence_tables( WorldComm, input_params.equivalence_table_restrict_BIG_file, input_params.equivalence_table_restrict_micro_file, equivalence_table_BIG_to_R_BIG, equivalence_table_micro_to_R_micro, equivalence_table_R_BIG_to_BIG, equivalence_table_R_micro_to_micro); if(input_params.b_UseMesh_BIG_AsMediator) { carl::set_local_intersection_tables( WorldComm, mesh_inter, local_inter_table_filename, input_params.equivalence_table_restrict_BIG_file, input_params.equivalence_table_restrict_micro_file, equivalence_table_BIG_to_R_BIG, equivalence_table_micro_to_R_micro, local_intersection_pairs_map, local_intersection_restricted_pairs_map, local_intersection_meshI_to_inter_map); } else if(input_params.b_UseMesh_micro_AsMediator) { carl::set_local_intersection_tables( WorldComm, mesh_inter, local_inter_table_filename, input_params.equivalence_table_restrict_micro_file, input_params.equivalence_table_restrict_BIG_file, equivalence_table_micro_to_R_micro, equivalence_table_BIG_to_R_BIG, local_intersection_pairs_map, local_intersection_restricted_pairs_map, local_intersection_meshI_to_inter_map); } std::unordered_multimap<int,int> inter_mediator_BIG; std::unordered_multimap<int,int> inter_mediator_micro; if(input_params.b_Repartition_micro) carl::repartition_system_meshes(WorldComm,mesh_micro,mesh_BIG,local_intersection_pairs_map); carl::set_global_mediator_system_intersection_lists( WorldComm, global_inter_table_filename, equivalence_table_BIG_to_R_BIG, equivalence_table_R_BIG_to_BIG, inter_mediator_BIG, inter_mediator_micro); perf_log.pop("Equivalence / intersection tables","Read files:"); perf_log.push("Weight function domain","Read files:"); // Set weight functions int domain_Idx_BIG = -1; int nb_of_domain_Idx = 1; std::vector<int> domain_Idx_micro; std::vector<int> domain_Idx_coupling; carl::set_weight_function_domain_idx( input_params.weight_domain_idx_file, domain_Idx_BIG, nb_of_domain_Idx, domain_Idx_micro, domain_Idx_coupling ); WorldComm.barrier(); perf_log.pop("Weight function domain","Read files:"); // - Generate the equation systems ----------------------------------------- perf_log.push("Initialization","System initialization:"); carl::coupled_system CoupledTest(WorldComm,input_params.solver_type); libMesh::EquationSystems& equation_systems_inter = CoupledTest.add_inter_EquationSystem("InterSys", mesh_inter); // Add the weight function mesh CoupledTest.add_alpha_mask("MicroSys",mesh_weight); CoupledTest.set_alpha_mask_parameters("MicroSys",domain_Idx_BIG,domain_Idx_micro[0],domain_Idx_coupling[0]); perf_log.pop("Initialization","System initialization:"); // - Build the BIG system -------------------------------------------------- perf_log.push("Macro system","System initialization:"); libMesh::EquationSystems& equation_systems_BIG = CoupledTest.set_BIG_EquationSystem("BigSys", mesh_BIG); // [MACRO] Set up the physical properties libMesh::LinearImplicitSystem& elasticity_system_BIG = add_elasticity(equation_systems_BIG); // [MACRO] Defining the boundaries with Dirichlet conditions //set_displaced_border_translation(elasticity_system_BIG, x_min_BIG,boundary_ids.MIN_X); set_clamped_border(elasticity_system_BIG, boundary_ids.MIN_X); // [MACRO] Build stress system libMesh::ExplicitSystem& stress_system_BIG = add_stress(equation_systems_BIG); equation_systems_BIG.init(); perf_log.pop("Macro system","System initialization:"); // - Build the micro system ------------------------------------------------ perf_log.push("Micro system","System initialization:"); libMesh::EquationSystems& equation_systems_micro = CoupledTest.add_micro_EquationSystem<libMesh::PetscMatrix<libMesh::Number> >("MicroSys", mesh_micro); // [MICRO] Set up the physical properties libMesh::LinearImplicitSystem& elasticity_system_micro = add_elasticity(equation_systems_micro); // [MICRO] Build stress system libMesh::ExplicitSystem& stress_system_micro = add_stress(equation_systems_micro); equation_systems_micro.init(); perf_log.pop("Micro system","System initialization:"); // - Build the RESTRICTED BIG system --------------------------------------- perf_log.push("RESTRICTED macro system","System initialization:"); libMesh::EquationSystems& equation_systems_R_BIG = CoupledTest.set_Restricted_BIG_EquationSystem("BigSys", mesh_R_BIG); // [R. MACRO] Set up the physical properties libMesh::ExplicitSystem& elasticity_system_R_BIG = add_explicit_elasticity(equation_systems_R_BIG); carl::reduced_system_init(elasticity_system_R_BIG); perf_log.pop("RESTRICTED macro system","System initialization:"); // - Build the RESTRICTED micro system ------------------------------------------------ perf_log.push("RESTRICTED micro system","System initialization:"); libMesh::EquationSystems& equation_systems_R_micro = CoupledTest.add_Restricted_micro_EquationSystem("MicroSys", mesh_R_micro); // [R. MICRO] Set up the physical properties libMesh::ExplicitSystem& elasticity_system_R_micro = add_explicit_elasticity(equation_systems_R_micro); carl::reduced_system_init(elasticity_system_R_micro); perf_log.pop("RESTRICTED micro system","System initialization:"); // - Build the mediator system --------------------------------------------- perf_log.push("Mediator system","System initialization:"); libMesh::EquationSystems& equation_systems_mediator = CoupledTest.add_mediator_EquationSystem("MediatorSys", mesh_mediator); libMesh::LinearImplicitSystem& elasticity_system_mediator = add_elasticity(equation_systems_mediator); equation_systems_mediator.init(); WorldComm.barrier(); perf_log.pop("Mediator system","System initialization:"); // - Build the dummy inter system ------------------------------------------ perf_log.push("Intersection system","System initialization:"); libMesh::ExplicitSystem& elasticity_system_inter = add_explicit_elasticity(equation_systems_inter); carl::reduced_system_init(elasticity_system_inter); WorldComm.barrier(); perf_log.pop("Intersection system","System initialization:"); perf_log.push("Physical properties","System initialization:"); double BIG_E = 0; double BIG_Mu = 0; double coupling_const = -1; std::ifstream phys_params_file(input_params.physical_params_file); carl::jump_lines(phys_params_file); phys_params_file >> BIG_E >> BIG_Mu; phys_params_file.close(); set_constant_physical_properties(equation_systems_BIG,BIG_E,BIG_Mu); set_constant_physical_properties(equation_systems_micro,BIG_E,BIG_Mu); perf_log.pop("Physical properties","System initialization:"); // - Set the coupling matrix ----------------------------------------------- perf_log.push("Set coupling matrices"); coupling_const = BIG_E; CoupledTest.set_coupling_parameters("MicroSys",coupling_const,input_params.mean_distance); CoupledTest.use_H1_coupling("MicroSys"); CoupledTest.assemble_coupling_elasticity_3D_parallel("BigSys","MicroSys", "InterSys","MediatorSys", mesh_R_BIG, mesh_R_micro, local_intersection_pairs_map, local_intersection_restricted_pairs_map, local_intersection_meshI_to_inter_map, inter_mediator_BIG, inter_mediator_micro); std::cout << std::endl; std::cout << "| ---> Constants " << std::endl; std::cout << "| Macro :" << std::endl; std::cout << "| E : " << BIG_E << std::endl; std::cout << "| Mu (lamba_2) : " << BIG_Mu << std::endl; std::cout << "| lambda_1 : " << eval_lambda_1(BIG_E,BIG_Mu) << std::endl; std::cout << "| Coupling :" << std::endl; std::cout << "| kappa : " << coupling_const << std::endl; std::cout << "| e : " << input_params.mean_distance << std::endl; switch(input_params.solver_type) { case carl::LATIN_MODIFIED_STIFFNESS: case carl::LATIN_ORIGINAL_STIFFNESS: { std::cout << "| LATIN :" << std::endl; std::cout << "| k_dA, k_dB : " << input_params.k_dA << " " << input_params.k_dB << std::endl; std::cout << "| k_cA, k_cB : " << input_params.k_cA << " " << input_params.k_cB << std::endl; break; } case carl::CG: { break; } } perf_log.pop("Set coupling matrices"); std::cout << "| restart file : " << input_params.coupled_restart_file_base << "*" << std::endl; std::cout << std::endl << "| --> Testing the solver " << std::endl << std::endl; perf_log.push("Set up","Coupled Solver:"); if(input_params.b_PrintRestartFiles || input_params.b_UseRestartFiles) { CoupledTest.set_restart( input_params.b_UseRestartFiles, input_params.b_PrintRestartFiles, input_params.coupled_restart_file_base); } std::cout << std::endl << "| --> Setting the solver " << std::endl << std::endl; switch(input_params.solver_type) { case carl::LATIN_MODIFIED_STIFFNESS: case carl::LATIN_ORIGINAL_STIFFNESS: { CoupledTest.set_LATIN_solver( "MicroSys","Elasticity", assemble_elasticity_with_weight, assemble_elasticity_with_weight_micro_and_traction, input_params.k_dA, input_params.k_dB, input_params.k_cA, input_params.k_cB, input_params.LATIN_eps, input_params.LATIN_conv_max, input_params.LATIN_relax); break; } case carl::CG: { CoupledTest.use_null_space_micro("MicroSys",true); CoupledTest.set_cg_preconditioner_type(input_params.CG_precond_type); CoupledTest.set_CG_solver( "MicroSys","Elasticity", assemble_elasticity_with_weight, assemble_elasticity_with_weight_micro_and_traction, input_params.CG_coupled_conv_abs,input_params.CG_coupled_conv_rel, input_params.CG_coupled_conv_max,input_params.CG_coupled_div, input_params.CG_coupled_conv_corr); break; } } perf_log.pop("Set up","Coupled Solver:"); // Solve ! perf_log.push("Solve","Coupled Solver:"); CoupledTest.solve("MicroSys","Elasticity",input_params.coupled_convergence_output); perf_log.pop("Solve","Coupled Solver:"); // Calculate stress perf_log.push("Compute stress - micro","Output:"); compute_stresses(equation_systems_micro); perf_log.pop("Compute stress - micro","Output:"); perf_log.push("Compute stress - macro","Output:"); compute_stresses(equation_systems_BIG); perf_log.pop("Compute stress - macro","Output:"); // Export solution #ifdef LIBMESH_HAVE_EXODUS_API if(input_params.b_PrintOutput) { perf_log.push("Save output","Output:"); libMesh::ExodusII_IO exo_io_micro(mesh_micro, /*single_precision=*/true); std::set<std::string> system_names_micro; system_names_micro.insert("Elasticity"); exo_io_micro.write_equation_systems(input_params.output_file_micro,equation_systems_micro,&system_names_micro); exo_io_micro.write_element_data(equation_systems_micro); libMesh::ExodusII_IO exo_io_BIG(mesh_BIG, /*single_precision=*/true); std::set<std::string> system_names_BIG; system_names_BIG.insert("Elasticity"); exo_io_BIG.write_equation_systems(input_params.output_file_BIG,equation_systems_BIG,&system_names_BIG); exo_io_BIG.write_element_data(equation_systems_BIG); perf_log.pop("Save output","Output:"); } #endif if(input_params.b_ExportScalingData) { CoupledTest.print_perf_log(input_params.scaling_data_file); } return 0; }
// The main program. int main (int argc, char** argv) { // Skip adaptive examples on a non-adaptive libMesh build #ifndef LIBMESH_ENABLE_AMR libmesh_example_requires(false, "--enable-amr"); #else // Skip this 2D example if libMesh was compiled as 1D-only. libmesh_example_requires(2 <= LIBMESH_DIM, "2D support"); // Initialize libMesh. LibMeshInit init (argc, argv); // This doesn't converge with Trilinos for some reason... libmesh_example_requires(libMesh::default_solver_package() == PETSC_SOLVERS, "--enable-petsc"); libMesh::out << "Started " << argv[0] << std::endl; // Make sure the general input file exists, and parse it { std::ifstream i("general.in"); if (!i) libmesh_error_msg('[' << init.comm().rank() << "] Can't find general.in; exiting early."); } GetPot infile("general.in"); // Read in parameters from the input file FEMParameters param(init.comm()); param.read(infile); // Create a mesh with the given dimension, distributed // across the default MPI communicator. Mesh mesh(init.comm(), param.dimension); // And an object to refine it UniquePtr<MeshRefinement> mesh_refinement(new MeshRefinement(mesh)); // And an EquationSystems to run on it EquationSystems equation_systems (mesh); libMesh::out << "Building mesh" << std::endl; // Build a unit square ElemType elemtype; if (param.elementtype == "tri" || param.elementtype == "unstructured") elemtype = TRI3; else elemtype = QUAD4; MeshTools::Generation::build_square (mesh, param.coarsegridx, param.coarsegridy, param.domain_xmin, param.domain_xmin + param.domain_edge_width, param.domain_ymin, param.domain_ymin + param.domain_edge_length, elemtype); libMesh::out << "Building system" << std::endl; HeatSystem & system = equation_systems.add_system<HeatSystem> ("HeatSystem"); set_system_parameters(system, param); libMesh::out << "Initializing systems" << std::endl; // Initialize the system equation_systems.init (); // Refine the grid again if requested for (unsigned int i=0; i != param.extrarefinements; ++i) { mesh_refinement->uniformly_refine(1); equation_systems.reinit(); } libMesh::out << "Setting primal initial conditions" << std::endl; read_initial_parameters(); system.project_solution(initial_value, initial_grad, equation_systems.parameters); // Output the H1 norm of the initial conditions libMesh::out << "|U(" << system.time << ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl << std::endl; // Add an adjoint vector, this will be computed after the forward // time stepping is complete // // Tell the library not to save adjoint solutions during the forward // solve // // Tell the library not to project this vector, and hence, memory // solution history to not save it. // // Make this vector ghosted so we can localize it to each element // later. const std::string & adjoint_solution_name = "adjoint_solution0"; system.add_vector("adjoint_solution0", false, GHOSTED); // Close up any resources initial.C needed finish_initialization(); // Plot the initial conditions write_output(equation_systems, 0, "primal"); // Print information about the mesh and system to the screen. mesh.print_info(); equation_systems.print_info(); // In optimized mode we catch any solver errors, so that we can // write the proper footers before closing. In debug mode we just // let the exception throw so that gdb can grab it. #ifdef NDEBUG try { #endif // Now we begin the timestep loop to compute the time-accurate // solution of the equations. for (unsigned int t_step=param.initial_timestep; t_step != param.initial_timestep + param.n_timesteps; ++t_step) { // A pretty update message libMesh::out << " Solving time step " << t_step << ", time = " << system.time << std::endl; // Solve the forward problem at time t, to obtain the solution at time t + dt system.solve(); // Output the H1 norm of the computed solution libMesh::out << "|U(" << system.time + system.deltat << ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl; // Advance to the next timestep in a transient problem libMesh::out << "Advancing timestep" << std::endl << std::endl; system.time_solver->advance_timestep(); // Write out this timestep write_output(equation_systems, t_step+1, "primal"); } // End timestep loop ///////////////// Now for the Adjoint Solution ////////////////////////////////////// // Now we will solve the backwards in time adjoint problem libMesh::out << std::endl << "Solving the adjoint problem" << std::endl; // We need to tell the library that it needs to project the adjoint, so // MemorySolutionHistory knows it has to save it // Tell the library to project the adjoint vector, and hence, memory solution history to // save it system.set_vector_preservation(adjoint_solution_name, true); libMesh::out << "Setting adjoint initial conditions Z(" << system.time << ")" <<std::endl; // Need to call adjoint_advance_timestep once for the initial condition setup libMesh::out<<"Retrieving solutions at time t="<<system.time<<std::endl; system.time_solver->adjoint_advance_timestep(); // Output the H1 norm of the retrieved solutions (u^i and u^i+1) libMesh::out << "|U(" << system.time + system.deltat << ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl; libMesh::out << "|U(" << system.time << ")|= " << system.calculate_norm(system.get_vector("_old_nonlinear_solution"), 0, H1) << std::endl; // The first thing we have to do is to apply the adjoint initial // condition. The user should supply these. Here they are specified // in the functions adjoint_initial_value and adjoint_initial_gradient system.project_vector(adjoint_initial_value, adjoint_initial_grad, equation_systems.parameters, system.get_adjoint_solution(0)); // Since we have specified an adjoint solution for the current // time (T), set the adjoint_already_solved boolean to true, so // we dont solve unneccesarily in the adjoint sensitivity method system.set_adjoint_already_solved(true); libMesh::out << "|Z(" << system.time << ")|= " << system.calculate_norm(system.get_adjoint_solution(), 0, H1) << std::endl << std::endl; write_output(equation_systems, param.n_timesteps, "dual"); // Now that the adjoint initial condition is set, we will start the // backwards in time adjoint integration // For loop stepping backwards in time for (unsigned int t_step=param.initial_timestep; t_step != param.initial_timestep + param.n_timesteps; ++t_step) { //A pretty update message libMesh::out << " Solving adjoint time step " << t_step << ", time = " << system.time << std::endl; // The adjoint_advance_timestep function calls the retrieve // function of the memory_solution_history class via the // memory_solution_history object we declared earlier. The // retrieve function sets the system primal vectors to their // values at the current timestep. libMesh::out << "Retrieving solutions at time t=" << system.time << std::endl; system.time_solver->adjoint_advance_timestep(); // Output the H1 norm of the retrieved solution libMesh::out << "|U(" << system.time + system.deltat << ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl; libMesh::out << "|U(" << system.time << ")|= " << system.calculate_norm(system.get_vector("_old_nonlinear_solution"), 0, H1) << std::endl; system.set_adjoint_already_solved(false); system.adjoint_solve(); // Now that we have solved the adjoint, set the // adjoint_already_solved boolean to true, so we dont solve // unneccesarily in the error estimator system.set_adjoint_already_solved(true); libMesh::out << "|Z(" << system.time << ")|= " << system.calculate_norm(system.get_adjoint_solution(), 0, H1) << std::endl << std::endl; // Get a pointer to the primal solution vector NumericVector<Number> & primal_solution = *system.solution; // Get a pointer to the solution vector of the adjoint problem for QoI 0 NumericVector<Number> & dual_solution_0 = system.get_adjoint_solution(0); // Swap the primal and dual solutions so we can write out the adjoint solution primal_solution.swap(dual_solution_0); write_output(equation_systems, param.n_timesteps - (t_step + 1), "dual"); // Swap back primal_solution.swap(dual_solution_0); } // End adjoint timestep loop // Now that we have computed both the primal and adjoint solutions, we compute the sensitivties to the parameter p // dQ/dp = partialQ/partialp - partialR/partialp // partialQ/partialp = (Q(p+dp) - Q(p-dp))/(2*dp), this is not supported by the library yet // partialR/partialp = (R(u,z;p+dp) - R(u,z;p-dp))/(2*dp), where // R(u,z;p+dp) = int_{0}^{T} f(z;p+dp) - <partialu/partialt, z>(p+dp) - <g(u),z>(p+dp) // To do this we need to step forward in time, and compute the perturbed R at each time step and accumulate it // Then once all time steps are over, we can compute (R(u,z;p+dp) - R(u,z;p-dp))/(2*dp) // Now we begin the timestep loop to compute the time-accurate // adjoint sensitivities for (unsigned int t_step=param.initial_timestep; t_step != param.initial_timestep + param.n_timesteps; ++t_step) { // A pretty update message libMesh::out << "Retrieving " << t_step << ", time = " << system.time << std::endl; // Retrieve the primal and adjoint solutions at the current timestep system.time_solver->retrieve_timestep(); libMesh::out << "|U(" << system.time + system.deltat << ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl; libMesh::out << "|U(" << system.time << ")|= " << system.calculate_norm(system.get_vector("_old_nonlinear_solution"), 0, H1) << std::endl; libMesh::out << "|Z(" << system.time << ")|= " << system.calculate_norm(system.get_adjoint_solution(0), 0, H1) << std::endl << std::endl; // Call the postprocess function which we have overloaded to compute // accumulate the perturbed residuals dynamic_cast<HeatSystem &>(system).perturb_accumulate_residuals(dynamic_cast<HeatSystem &>(system).get_parameter_vector()); // Move the system time forward (retrieve_timestep does not do this) system.time += system.deltat; } // A pretty update message libMesh::out << "Retrieving final time = " << system.time << std::endl; // Retrieve the primal and adjoint solutions at the current timestep system.time_solver->retrieve_timestep(); libMesh::out << "|U(" << system.time + system.deltat << ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl; libMesh::out << "|U(" << system.time << ")|= " << system.calculate_norm(system.get_vector("_old_nonlinear_solution"), 0, H1) << std::endl; libMesh::out << "|Z(" << system.time << ")|= " << system.calculate_norm(system.get_adjoint_solution(0), 0, H1) << std::endl << std::endl; // Call the postprocess function which we have overloaded to compute // accumulate the perturbed residuals dynamic_cast<HeatSystem &>(system).perturb_accumulate_residuals(dynamic_cast<HeatSystem &>(system).get_parameter_vector()); // Now that we computed the accumulated, perturbed residuals, we can compute the // approximate sensitivity Number sensitivity_0_0 = (dynamic_cast<HeatSystem &>(system)).compute_final_sensitivity(); // Print it out libMesh::out << "Sensitivity of QoI 0 w.r.t parameter 0 is: " << sensitivity_0_0 << std::endl; // Hard coded assert to ensure that the actual numbers we are // getting are what they should be // The 2e-4 tolerance is chosen to ensure success even with // 32-bit floats libmesh_assert_less(std::abs(sensitivity_0_0 - (-5.37173)), 2.e-4); #ifdef NDEBUG } catch (...) { libMesh::err << '[' << mesh.processor_id() << "] Caught exception; exiting early." << std::endl; } #endif libMesh::err << '[' << mesh.processor_id() << "] Completing output." << std::endl; // All done. return 0; #endif // LIBMESH_ENABLE_AMR }
int main(int argc, char* argv[]) { GRINS::Runner grins(argc,argv); // This is a tough problem to get to converge without PETSc libmesh_example_requires (libMesh::default_solver_package() != libMesh::LASPACK_SOLVERS, "--enable-petsc"); grins.init(); const GetPot & inputfile = grins.get_input_file(); GRINS::Simulation & sim = grins.get_simulation(); //FIXME: We need to move this to within the Simulation object somehow... std::string restart_file = inputfile( "restart-options/restart_file", "none" ); if( restart_file == "none" ) { // Asssign initial temperature value std::string system_name = inputfile( "screen-options/system_name", "GRINS" ); std::shared_ptr<libMesh::EquationSystems> es = sim.get_equation_system(); const libMesh::System& system = es->get_system(system_name); libMesh::Parameters ¶ms = es->parameters; libMesh::Real T_init = inputfile("Materials/TestMaterial/ReferenceTemperature/value", 0.0); libMesh::Real p0_init = inputfile("Materials/TestMaterial/ThermodynamicPressure/value", 0.0); libMesh::Real& dummy_T = params.set<libMesh::Real>("T_init"); dummy_T = T_init; libMesh::Real& dummy_p0 = params.set<libMesh::Real>("p0_init"); dummy_p0 = p0_init; system.project_solution( initial_values, NULL, params ); } grins.run(); libMesh::Real qoi = sim.get_qoi_value(0); // Note that this is a *really* coarse mesh. This is just for testing // and not even close to the real QoI for this problem. // Erroneous value from libMesh 0.9.2.2 // const libMesh::Real exact_qoi = 4.8158910676325055; // Value after libMesh 7acb6fc9 bugfix const libMesh::Real exact_qoi = 4.8654229502012685; const libMesh::Real tol = 1.0e-9; int return_flag = 0; libMesh::Real rel_error = std::fabs( (qoi-exact_qoi)/exact_qoi ); if( rel_error > tol ) { // Skip this test until we know what changed // return_flag = 1; return_flag = 77; std::cerr << std::setprecision(16) << std::scientific << "Error: QoI value mismatch." << std::endl << "Computed qoi = " << qoi << std::endl << "Exact qoi = " << exact_qoi << std::endl << "Relative error = " << rel_error << std::endl; } return return_flag; }
int main(int argc, char** argv) { // --- Initialize libMesh libMesh::LibMeshInit init(argc, argv); // Do performance log? libMesh::PerfLog perf_log("Main program"); // libMesh's C++ / MPI communicator wrapper libMesh::Parallel::Communicator& WorldComm = init.comm(); // --- Set up inputs // Command line parser GetPot command_line(argc, argv); // File parser GetPot field_parser; // If there is an input file, parse it to get the parameters. Else, parse the command line std::string input_filename; if (command_line.search(2, "--inputfile", "-i")) { input_filename = command_line.next(input_filename); field_parser.parse_input_file(input_filename, "#", "\n", " \t\n"); } else { field_parser = command_line; } carl::libmesh_apply_solution_input_params input_params; carl::get_input_params(field_parser, input_params); // Check libMesh installation dimension const unsigned int dim = 3; libmesh_example_requires(dim == LIBMESH_DIM, "3D support"); // - Parallelized meshes A libMesh::Mesh system_mesh(WorldComm, dim); system_mesh.read(input_params.input_mesh); system_mesh.prepare_for_use(); // Set the equation systems object libMesh::EquationSystems equation_systems(system_mesh); // Add linear elasticity and stress libMesh::LinearImplicitSystem& elasticity_system = add_elasticity(equation_systems); add_stress(equation_systems); // Initialize the equation systems equation_systems.init(); // Homogeneous physical properties set_homogeneous_physical_properties(equation_systems, input_params.physical_params_file); // Read the solution vector libMesh::PetscVector<libMesh::Real> * sol_vec_ptr = libMesh::cast_ptr<libMesh::PetscVector<libMesh::Real> * >(elasticity_system.solution.get()); carl::read_PETSC_vector(sol_vec_ptr->vec(),input_params.input_vector, WorldComm.get()); // Close it and update elasticity_system.solution->close(); elasticity_system.update(); // Calculate the stress compute_stresses(equation_systems); // Export solution #ifdef LIBMESH_HAVE_EXODUS_API libMesh::ExodusII_IO exo_io_interface(system_mesh, /*single_precision=*/true); std::set<std::string> system_names; system_names.insert("Elasticity"); exo_io_interface.write_equation_systems(input_params.output_mesh,equation_systems,&system_names); exo_io_interface.write_element_data(equation_systems); #endif return 0; }