/** * A function to log information about application's performance */ static void writePerfLog(const tParams & params, const CPointCloud & pc, const COpticalField & of, const CBaseRenderer *ren) { /* check if creating a log was actually requested and that the input parameters are valid */ if ((params.perf_log == NULL) || (ren == NULL)) { return; } std::cout << "Writing performance log" << std::endl; std::ofstream perf_log(params.perf_log, std::ofstream::app); if (!perf_log) { std::cerr << "Failed to create performance log" << std::endl; return; } perf_log << "================================================================================" << std::endl; perf_log << "date : " << Utils::fmtDateTime("%H:%M:%S %d.%m.%Y", time(NULL)) << std::endl; #ifdef HOLOREN_DEBUG perf_log << "build type : debug" << std::endl; #else perf_log << "build type : release" << std::endl; #endif perf_log << "input file : \"" << params.ifilename << '\"' << std::endl; perf_log << "point sources : " << pc.size() << std::endl; perf_log << "optical field (rows x cols) : " << of.getNumRows() << 'x' << of.getNumCols() << std::endl; if (params.renderer == REN_OPENCL) { const COpenCLRenderer *ocl_ren = static_cast<const COpenCLRenderer *>(ren); perf_log << "algorithm : " << COpenCLRenderer::algToStr(params.alg_type) << std::endl; perf_log << "chunk size : " << ocl_ren->getChunkSize() << std::endl; } perf_log << "rendering time : " << g_timer << std::endl; perf_log << "================================================================================" << std::endl; perf_log.close(); return; }
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; }
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; }
// The matrix assembly function to be called at each time step to // prepare for the linear solve. void assemble_solid (EquationSystems& es, const std::string& system_name) { //es.print_info(); #if LOG_ASSEMBLE_PERFORMANCE PerfLog perf_log("Assemble"); perf_log.push("assemble stiffness"); #endif // Get a reference to the auxiliary system //TransientExplicitSystem& aux_system = es.get_system<TransientExplicitSystem>("Newton-update"); // It is a good idea to make sure we are assembling // the proper system. libmesh_assert (system_name == "Newton-update"); // Get a constant reference to the mesh object. const MeshBase& mesh = es.get_mesh(); // The dimension that we are running const unsigned int dim = mesh.mesh_dimension(); // Get a reference to the Stokes system object. TransientLinearImplicitSystem & newton_update = es.get_system<TransientLinearImplicitSystem> ("Newton-update"); // New TransientLinearImplicitSystem & last_non_linear_soln = es.get_system<TransientLinearImplicitSystem> ("Last-non-linear-soln"); TransientLinearImplicitSystem & fluid_system_vel = es.get_system<TransientLinearImplicitSystem> ("fluid-system-vel"); #if VELOCITY TransientLinearImplicitSystem& velocity = es.get_system<TransientLinearImplicitSystem>("velocity-system"); #endif #if UN_MINUS_ONE TransientLinearImplicitSystem & unm1 = es.get_system<TransientLinearImplicitSystem> ("unm1-system"); #endif test(62); const System & ref_sys = es.get_system("Reference-Configuration"); test(63); // Numeric ids corresponding to each variable in the system const unsigned int u_var = last_non_linear_soln .variable_number ("u"); const unsigned int v_var = last_non_linear_soln .variable_number ("v"); const unsigned int w_var = last_non_linear_soln .variable_number ("w"); #if INCOMPRESSIBLE const unsigned int p_var = last_non_linear_soln .variable_number ("p"); #endif #if FLUID_P_CONST const unsigned int m_var = fluid_system_vel.variable_number ("fluid_M"); std::vector<unsigned int> dof_indices_m; #endif // Get the Finite Element type for "u". Note this will be // the same as the type for "v". FEType fe_vel_type = last_non_linear_soln.variable_type(u_var); test(64); #if INCOMPRESSIBLE // Get the Finite Element type for "p". FEType fe_pres_type = last_non_linear_soln .variable_type(p_var); #endif // Build a Finite Element object of the specified type for // the velocity variables. AutoPtr<FEBase> fe_vel (FEBase::build(dim, fe_vel_type)); #if INCOMPRESSIBLE // Build a Finite Element object of the specified type for // the pressure variables. AutoPtr<FEBase> fe_pres (FEBase::build(dim, fe_pres_type)); #endif // A Gauss quadrature rule for numerical integration. // Let the \p FEType object decide what order rule is appropriate. QGauss qrule (dim, fe_vel_type.default_quadrature_order()); // Tell the finite element objects to use our quadrature rule. fe_vel->attach_quadrature_rule (&qrule); test(65); // AutoPtr<QBase> qrule2(fe_vel_type.default_quadrature_rule(dim)); // fe_vel->attach_quadrature_rule (qrule2.get()); #if INCOMPRESSIBLE fe_pres->attach_quadrature_rule (&qrule); #endif // The element Jacobian * quadrature weight at each integration point. const std::vector<Real>& JxW = fe_vel->get_JxW(); // The element shape functions evaluated at the quadrature points. const std::vector<std::vector<Real> >& phi = fe_vel->get_phi(); // The element shape function gradients for the velocity // variables evaluated at the quadrature points. const std::vector<std::vector<RealGradient> >& dphi = fe_vel->get_dphi(); test(66); #if INCOMPRESSIBLE // The element shape functions for the pressure variable // evaluated at the quadrature points. const std::vector<std::vector<Real> >& psi = fe_pres->get_phi(); #endif const std::vector<Point>& coords = fe_vel->get_xyz(); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap & dof_map = last_non_linear_soln .get_dof_map(); #if FLUID_P_CONST const DofMap & dof_map_fluid = fluid_system_vel .get_dof_map(); #endif // K will be the jacobian // F will be the Residual DenseMatrix<Number> Ke; DenseVector<Number> Fe; DenseSubMatrix<Number> Kuu(Ke), Kuv(Ke), Kuw(Ke), Kvu(Ke), Kvv(Ke), Kvw(Ke), Kwu(Ke), Kwv(Ke), Kww(Ke); #if INCOMPRESSIBLE DenseSubMatrix<Number> Kup(Ke),Kvp(Ke),Kwp(Ke), Kpu(Ke), Kpv(Ke), Kpw(Ke), Kpp(Ke); #endif; DenseSubVector<Number> Fu(Fe), Fv(Fe), Fw(Fe); #if INCOMPRESSIBLE DenseSubVector<Number> Fp(Fe); #endif // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<unsigned int> dof_indices; std::vector<unsigned int> dof_indices_u; std::vector<unsigned int> dof_indices_v; std::vector<unsigned int> dof_indices_w; #if INCOMPRESSIBLE std::vector<unsigned int> dof_indices_p; #endif #if INERTIA test(67); const unsigned int a_var = last_non_linear_soln.variable_number ("a"); const unsigned int b_var = last_non_linear_soln.variable_number ("b"); const unsigned int c_var = last_non_linear_soln.variable_number ("c"); //B block DenseSubMatrix<Number> Kua(Ke), Kub(Ke), Kuc(Ke), Kva(Ke), Kvb(Ke), Kvc(Ke), Kwa(Ke), Kwb(Ke), Kwc(Ke); //C block DenseSubMatrix<Number> Kau(Ke), Kav(Ke), Kaw(Ke), Kbu(Ke), Kbv(Ke), Kbw(Ke), Kcu(Ke), Kcv(Ke), Kcw(Ke); //D block DenseSubMatrix<Number> Kaa(Ke), Kab(Ke), Kac(Ke), Kba(Ke), Kbb(Ke), Kbc(Ke), Kca(Ke), Kcb(Ke), Kcc(Ke); DenseSubVector<Number> Fa(Fe), Fb(Fe), Fc(Fe); std::vector<unsigned int> dof_indices_a; std::vector<unsigned int> dof_indices_b; std::vector<unsigned int> dof_indices_c; test(68); #endif DenseMatrix<Real> stiff; DenseVector<Real> res; VectorValue<Gradient> grad_u_mat; VectorValue<Gradient> grad_u_mat_old; const Real dt = es.parameters.get<Real>("dt"); const Real progress = es.parameters.get<Real>("progress"); #if PORO DenseVector<Real> p_stiff; DenseVector<Real> p_res; PoroelasticConfig material(dphi,psi); #endif // Just calculate jacobian contribution when we need to material.calculate_linearized_stiffness = true; MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { test(69); const Elem* elem = *el; dof_map.dof_indices (elem, dof_indices); dof_map.dof_indices (elem, dof_indices_u, u_var); dof_map.dof_indices (elem, dof_indices_v, v_var); dof_map.dof_indices (elem, dof_indices_w, w_var); #if INCOMPRESSIBLE dof_map.dof_indices (elem, dof_indices_p, p_var); #endif const unsigned int n_dofs = dof_indices.size(); const unsigned int n_u_dofs = dof_indices_u.size(); const unsigned int n_v_dofs = dof_indices_v.size(); const unsigned int n_w_dofs = dof_indices_w.size(); #if INCOMPRESSIBLE const unsigned int n_p_dofs = dof_indices_p.size(); #endif #if FLUID_P_CONST dof_map_fluid.dof_indices (elem, dof_indices_m, m_var); #endif //elem->print_info(); fe_vel->reinit (elem); #if INCOMPRESSIBLE fe_pres->reinit (elem); #endif Ke.resize (n_dofs, n_dofs); Fe.resize (n_dofs); Kuu.reposition (u_var*n_u_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs); Kuv.reposition (u_var*n_u_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs); Kuw.reposition (u_var*n_u_dofs, w_var*n_u_dofs, n_u_dofs, n_w_dofs); #if INCOMPRESSIBLE Kup.reposition (u_var*n_u_dofs, p_var*n_u_dofs, n_u_dofs, n_p_dofs); #endif Kvu.reposition (v_var*n_v_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs); Kvv.reposition (v_var*n_v_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs); Kvw.reposition (v_var*n_v_dofs, w_var*n_v_dofs, n_v_dofs, n_w_dofs); #if INCOMPRESSIBLE Kvp.reposition (v_var*n_v_dofs, p_var*n_v_dofs, n_v_dofs, n_p_dofs); #endif Kwu.reposition (w_var*n_w_dofs, u_var*n_w_dofs, n_w_dofs, n_u_dofs); Kwv.reposition (w_var*n_w_dofs, v_var*n_w_dofs, n_w_dofs, n_v_dofs); Kww.reposition (w_var*n_w_dofs, w_var*n_w_dofs, n_w_dofs, n_w_dofs); #if INCOMPRESSIBLE Kwp.reposition (w_var*n_w_dofs, p_var*n_w_dofs, n_w_dofs, n_p_dofs); Kpu.reposition (p_var*n_u_dofs, u_var*n_u_dofs, n_p_dofs, n_u_dofs); Kpv.reposition (p_var*n_u_dofs, v_var*n_u_dofs, n_p_dofs, n_v_dofs); Kpw.reposition (p_var*n_u_dofs, w_var*n_u_dofs, n_p_dofs, n_w_dofs); Kpp.reposition (p_var*n_u_dofs, p_var*n_u_dofs, n_p_dofs, n_p_dofs); #endif Fu.reposition (u_var*n_u_dofs, n_u_dofs); Fv.reposition (v_var*n_u_dofs, n_v_dofs); Fw.reposition (w_var*n_u_dofs, n_w_dofs); #if INCOMPRESSIBLE Fp.reposition (p_var*n_u_dofs, n_p_dofs); #endif #if INERTIA //B block Kua.reposition (u_var*n_u_dofs, 3*n_u_dofs + n_p_dofs, n_u_dofs, n_u_dofs); Kub.reposition (u_var*n_u_dofs, 4*n_u_dofs + n_p_dofs, n_u_dofs, n_v_dofs); Kuc.reposition (u_var*n_u_dofs, 5*n_u_dofs + n_p_dofs, n_u_dofs, n_w_dofs); Kva.reposition (v_var*n_v_dofs, 3*n_u_dofs + n_p_dofs, n_v_dofs, n_u_dofs); Kvb.reposition (v_var*n_v_dofs, 4*n_u_dofs + n_p_dofs, n_v_dofs, n_v_dofs); Kvc.reposition (v_var*n_v_dofs, 5*n_u_dofs + n_p_dofs, n_v_dofs, n_w_dofs); Kwa.reposition (w_var*n_w_dofs, 3*n_u_dofs + n_p_dofs, n_w_dofs, n_u_dofs); Kwb.reposition (w_var*n_w_dofs, 4*n_u_dofs + n_p_dofs, n_w_dofs, n_v_dofs); Kwc.reposition (w_var*n_w_dofs, 5*n_u_dofs + n_p_dofs, n_w_dofs, n_w_dofs); test(701); //C block Kau.reposition (3*n_u_dofs + n_p_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs); Kav.reposition (3*n_u_dofs + n_p_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs); Kaw.reposition (3*n_u_dofs + n_p_dofs, w_var*n_u_dofs, n_u_dofs, n_w_dofs); Kbu.reposition (4*n_u_dofs + n_p_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs); Kbv.reposition (4*n_u_dofs + n_p_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs); Kbw.reposition (4*n_u_dofs + n_p_dofs, w_var*n_v_dofs, n_v_dofs, n_w_dofs); Kcu.reposition (5*n_u_dofs + n_p_dofs, u_var*n_w_dofs, n_w_dofs, n_u_dofs); Kcv.reposition (5*n_u_dofs + n_p_dofs, v_var*n_w_dofs, n_w_dofs, n_v_dofs); Kcw.reposition (5*n_u_dofs + n_p_dofs, w_var*n_w_dofs, n_w_dofs, n_w_dofs); //D block Kaa.reposition (3*n_u_dofs + n_p_dofs, 3*n_u_dofs + n_p_dofs, n_u_dofs, n_u_dofs); Kab.reposition (3*n_u_dofs + n_p_dofs, 4*n_u_dofs + n_p_dofs, n_u_dofs, n_v_dofs); Kac.reposition (3*n_u_dofs + n_p_dofs, 5*n_u_dofs + n_p_dofs, n_u_dofs, n_w_dofs); Kba.reposition (4*n_u_dofs + n_p_dofs, 3*n_u_dofs + n_p_dofs, n_v_dofs, n_u_dofs); Kbb.reposition (4*n_u_dofs + n_p_dofs, 4*n_u_dofs + n_p_dofs, n_v_dofs, n_v_dofs); Kbc.reposition (4*n_u_dofs + n_p_dofs, 5*n_u_dofs + n_p_dofs, n_v_dofs, n_w_dofs); Kca.reposition (5*n_u_dofs + n_p_dofs, 3*n_u_dofs + n_p_dofs, n_w_dofs, n_u_dofs); Kcb.reposition (5*n_u_dofs + n_p_dofs, 4*n_u_dofs + n_p_dofs, n_w_dofs, n_v_dofs); Kcc.reposition (5*n_u_dofs + n_p_dofs, 5*n_u_dofs + n_p_dofs, n_w_dofs, n_w_dofs); Fa.reposition (3*n_u_dofs + n_p_dofs, n_u_dofs); Fb.reposition (4*n_u_dofs + n_p_dofs, n_v_dofs); Fc.reposition (5*n_u_dofs + n_p_dofs, n_w_dofs); dof_map.dof_indices (elem, dof_indices_a, a_var); dof_map.dof_indices (elem, dof_indices_b, b_var); dof_map.dof_indices (elem, dof_indices_c, c_var); test(71); #endif System& aux_system = es.get_system<System>("Reference-Configuration"); std::vector<unsigned int> undefo_index; std::vector<unsigned int> vel_index; for (unsigned int qp=0; qp<qrule.n_points(); qp++) { Point rX; for (unsigned int l=0; l<n_u_dofs; l++) { rX(0) += phi[l][qp]*ref_sys.current_local_solution->el(dof_indices_u[l]); rX(1) += phi[l][qp]*ref_sys.current_local_solution->el(dof_indices_v[l]); rX(2) += phi[l][qp]*ref_sys.current_local_solution->el(dof_indices_w[l]); } #if INERTIA || DT test(72); Real rho_s=15; Point current_x; for (unsigned int l=0; l<n_u_dofs; l++) { current_x(0) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_u[l]); current_x(1) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_v[l]); current_x(2) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_w[l]); } Point old_x; for (unsigned int l=0; l<n_u_dofs; l++) { old_x(0) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_u[l]); old_x(1) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_v[l]); old_x(2) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_w[l]); } #if INERTIA Point old_vel; for (unsigned int l=0; l<n_u_dofs; l++) { old_vel(0) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_a[l]); old_vel(1) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_b[l]); old_vel(2) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_c[l]); } Point current_vel; for (unsigned int l=0; l<n_u_dofs; l++) { current_vel(0) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_a[l]); current_vel(1) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_b[l]); current_vel(2) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_c[l]); } #endif #if UN_MINUS_ONE Point unm1_x; for (unsigned int l=0; l<n_u_dofs; l++) { unm1_x(0) += phi[l][qp]*unm1.old_local_solution->el(dof_indices_u[l]); unm1_x(1) += phi[l][qp]*unm1.old_local_solution->el(dof_indices_v[l]); unm1_x(2) += phi[l][qp]*unm1.old_local_solution->el(dof_indices_w[l]); } #endif Point value_acc; Point value_acc_alt; #if DT for (unsigned int d = 0; d < dim; ++d) { value_acc_alt(d) = (rho_s)*( ((current_x(d)-rX(d))-(old_x(d)-rX(d)))-((old_x(d)-rX(d))- (unm1_x(d)-rX(d))) ); value_acc(d) = (rho_s)*((current_x(d))-2*(old_x(d))+ (unm1_x(d))); value_acc(d) = (rho_s)*((current_x(d))-(old_x(d))); } #endif Point res_1; Point res_2; #if INERTIA for (unsigned int d = 0; d < dim; ++d) { res_1(d) = (rho_s)*((current_vel(d))-(old_vel(d))); res_2(d) = current_x(d)-dt*current_vel(d)-old_x(d); } /* std::cout<<" current_vel "<<current_vel<<std::endl; std::cout<<" res_1 "<<res_1<<std::endl; std::cout<<" res_2 "<<res_2<<std::endl; */ #endif test(73); #endif Number p_solid = 0.; #if MOVING_MESH grad_u_mat(0) = grad_u_mat(1) = grad_u_mat(2) = 0; for (unsigned int d = 0; d < dim; ++d) { std::vector<Number> u_undefo; //Fills the vector di with the global degree of freedom indices for the element. :dof_indicies aux_system.get_dof_map().dof_indices(elem, undefo_index,d); aux_system.current_local_solution->get(undefo_index, u_undefo); for (unsigned int l = 0; l != n_u_dofs; l++) grad_u_mat(d).add_scaled(dphi[l][qp], u_undefo[l]); } #endif //#include "fixed_mesh_in_solid_assemble_code.txt" #if INCOMPRESSIBLE for (unsigned int l=0; l<n_p_dofs; l++) { p_solid += psi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_p[l]); } #endif #if INCOMPRESSIBLE Real m=0; Real p_fluid=0; #if FLUID_VEL for (unsigned int l=0; l<n_p_dofs; l++) { p_fluid += psi[l][qp]*fluid_system_vel.current_local_solution->el(dof_indices_p[l]); } //As outlined in Chappel p=(p_curr-p_old)/2 Real p_fluid_old=0; for (unsigned int l=0; l<n_p_dofs; l++) { p_fluid_old += psi[l][qp]*fluid_system_vel.old_local_solution->el(dof_indices_p[l]); } p_fluid=0.5*p_fluid+0.5*p_fluid_old; Real m_old=0; #if FLUID_P_CONST for (unsigned int l=0; l<n_p_dofs; l++) { m += psi[l][qp]*fluid_system_vel.current_local_solution->el(dof_indices_m[l]); } for (unsigned int l=0; l<n_p_dofs; l++) { m_old += psi[l][qp]*fluid_system_vel.old_local_solution->el(dof_indices_m[l]); } #endif material.init_for_qp(grad_u_mat, p_solid, qp, 1.0*m+0.0*m_old, p_fluid); #endif #endif //#if INCOMPRESSIBLE #if INCOMPRESSIBLE && ! PORO material.init_for_qp(grad_u_mat, p_solid, qp); #endif for (unsigned int i=0; i<n_u_dofs; i++) { res.resize(dim); material.get_residual(res, i); res.scale(JxW[qp]); #if INERTIA res.scale(dt); #endif #if DT res.scale(dt); #endif //std::cout<< "res "<<res<<std::endl; Fu(i) += res(0); Fv(i) += res(1) ; Fw(i) += res(2); #if GRAVITY Real grav=0.0; Fu(i) += progress*grav*JxW[qp]*phi[i][qp]; #endif #if INERTIA Fu(i) += JxW[qp]*phi[i][qp]*res_1(0); Fv(i) += JxW[qp]*phi[i][qp]*res_1(1); Fw(i) += JxW[qp]*phi[i][qp]*res_1(2); Fa(i) += JxW[qp]*phi[i][qp]*res_2(0); Fb(i) += JxW[qp]*phi[i][qp]*res_2(1); Fc(i) += JxW[qp]*phi[i][qp]*res_2(2); #endif // Matrix contributions for the uu and vv couplings. for (unsigned int j=0; j<n_u_dofs; j++) { material.get_linearized_stiffness(stiff, i, j); stiff.scale(JxW[qp]); #if DT res.scale(dt); #endif #if INERTIA stiff.scale(dt); Kua(i,j)+= rho_s*JxW[qp]*phi[i][qp]*phi[j][qp]; Kvb(i,j)+= rho_s*JxW[qp]*phi[i][qp]*phi[j][qp]; Kwc(i,j)+= rho_s*JxW[qp]*phi[i][qp]*phi[j][qp]; Kau(i,j)+= JxW[qp]*phi[i][qp]*phi[j][qp]; Kbv(i,j)+= JxW[qp]*phi[i][qp]*phi[j][qp]; Kcw(i,j)+= JxW[qp]*phi[i][qp]*phi[j][qp]; Kaa(i,j)+= -dt*JxW[qp]*phi[i][qp]*phi[j][qp]; Kbb(i,j)+= -dt*JxW[qp]*phi[i][qp]*phi[j][qp]; Kcc(i,j)+= -dt*JxW[qp]*phi[i][qp]*phi[j][qp]; #endif Kuu(i,j)+= stiff(u_var, u_var); Kuv(i,j)+= stiff(u_var, v_var); Kuw(i,j)+= stiff(u_var, w_var); Kvu(i,j)+= stiff(v_var, u_var); Kvv(i,j)+= stiff(v_var, v_var); Kvw(i,j)+= stiff(v_var, w_var); Kwu(i,j)+= stiff(w_var, u_var); Kwv(i,j)+= stiff(w_var, v_var); Kww(i,j)+= stiff(w_var, w_var); #if GRAVITY Kuu(i,j)+= 1*JxW[qp]*phi[i][qp]*phi[j][qp]; #endif } } #if INCOMPRESSIBLE && FLUID_P_CONST for (unsigned int i = 0; i < n_p_dofs; i++) { material.get_p_residual(p_res, i); p_res.scale(JxW[qp]); Fp(i) += p_res(0); } for (unsigned int i = 0; i < n_u_dofs; i++) { for (unsigned int j = 0; j < n_p_dofs; j++) { material.get_linearized_uvw_p_stiffness(p_stiff, i, j); p_stiff.scale(JxW[qp]); Kup(i, j) += p_stiff(0); Kvp(i, j) += p_stiff(1); Kwp(i, j) += p_stiff(2); } } for (unsigned int i = 0; i < n_p_dofs; i++) { for (unsigned int j = 0; j < n_u_dofs; j++) { material.get_linearized_p_uvw_stiffness(p_stiff, i, j); p_stiff.scale(JxW[qp]); Kpu(i, j) += p_stiff(0); Kpv(i, j) += p_stiff(1); Kpw(i, j) += p_stiff(2); } } #endif #if CHAP && ! FLUID_P_CONST for (unsigned int i = 0; i < n_p_dofs; i++) { Fp(i) += 0*JxW[qp]*psi[i][qp]; } for (unsigned int i = 0; i < n_p_dofs; i++) { for (unsigned int j = 0; j < n_p_dofs; j++) { Kpp(i, j) += 1*JxW[qp]*psi[i][qp]*psi[j][qp]; } } #endif }//end of qp loop newton_update.matrix->add_matrix (Ke, dof_indices); newton_update.rhs->add_vector (Fe, dof_indices); } // end of element loop // dof_map.constrain_element_matrix_and_vector (Ke, Fe, dof_indices); newton_update.rhs->close(); newton_update.matrix->close(); #if LOG_ASSEMBLE_PERFORMANCE perf_log.pop("assemble stiffness"); #endif #if LOG_ASSEMBLE_PERFORMANCE perf_log.push("assemble bcs"); #endif //Assemble the boundary conditions. assemble_bcs(es); #if LOG_ASSEMBLE_PERFORMANCE perf_log.pop("assemble bcs"); #endif std::ofstream lhs_out("lhsoutS3.dat"); Ke.print(lhs_out); lhs_out.close(); return; }
void Biharmonic::JR::bounds(NumericVector<Number> &XL, NumericVector<Number>& XU, NonlinearImplicitSystem&) { // sys is actually ignored, since it should be the same as *this. // Declare a performance log. Give it a descriptive // string to identify what part of the code we are // logging, since there may be many PerfLogs in an // application. PerfLog perf_log ("Biharmonic bounds", false); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap& dof_map = get_dof_map(); // Get a constant reference to the Finite Element type // for the first (and only) variable in the system. FEType fe_type = dof_map.variable_type(0); // Build a Finite Element object of the specified type. Since the // \p FEBase::build() member dynamically creates memory we will // store the object as an \p AutoPtr<FEBase>. This can be thought // of as a pointer that will clean up after itself. AutoPtr<FEBase> fe (FEBase::build(_biharmonic._dim, fe_type)); // Define data structures to contain the bound vectors contributions. DenseVector<Number> XLe, XUe; // These vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<unsigned int> dof_indices; MeshBase::const_element_iterator el = _biharmonic._mesh->active_local_elements_begin(); const MeshBase::const_element_iterator end_el = _biharmonic._mesh->active_local_elements_end(); for ( ; el != end_el; ++el) { // Extract the shape function to be evaluated at the nodes const std::vector<std::vector<Real> >& phi = fe->get_phi(); // Get the degree of freedom indices for the current element. // They are in 1-1 correspondence with shape functions phi // and define where in the global vector this element will. dof_map.dof_indices (*el, dof_indices); // Resize the local bounds vectors (zeroing them out in the process). XLe.resize(dof_indices.size()); XUe.resize(dof_indices.size()); // Extract the element node coordinates in the reference frame std::vector<Point> nodes; fe->get_refspace_nodes((*el)->type(), nodes); // Evaluate the shape functions at the nodes fe->reinit(*el, &nodes); // Construct the bounds based on the value of the i-th phi at the nodes. // Observe that this doesn't really work in general: we rely on the fact // that for Hermite elements each shape function is nonzero at most at a // single node. // More generally the bounds must be constructed by inspecting a "mass-like" // matrix (m_{ij}) of the shape functions (i) evaluated at their corresponding nodes (j). // The constraints imposed on the dofs (d_i) are then are -1 \leq \sum_i d_i m_{ij} \leq 1, // since \sum_i d_i m_{ij} is the value of the solution at the j-th node. // Auxiliary variables will need to be introduced to reduce this to a "box" constraint. // Additional complications will arise since m might be singular (as is the case for Hermite, // which, however, is easily handled by inspection). for (unsigned int i=0; i<phi.size(); ++i) { // FIXME: should be able to define INF and pass it to the solve Real infinity = 1.0e20; Real bound = infinity; for(unsigned int j = 0; j < nodes.size(); ++j) { if(phi[i][j]) { bound = 1.0/fabs(phi[i][j]); break; } } // The value of the solution at this node must be between 1.0 and -1.0. // Based on the value of phi(i)(i) the nodal coordinate must be between 1.0/phi(i)(i) and its negative. XLe(i) = -bound; XUe(i) = bound; } // The element bound vectors are now built for this element. // Insert them into the global vectors, potentially overwriting // the same dof contributions from other elements: no matter -- // the bounds are always -1.0 and 1.0. XL.insert(XLe, dof_indices); XU.insert(XUe, dof_indices); } }
void Biharmonic::JR::residual_and_jacobian(const NumericVector<Number> &u, NumericVector<Number> *R, SparseMatrix<Number> *J, NonlinearImplicitSystem&) { #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES if (!R && !J) return; // Declare a performance log. Give it a descriptive // string to identify what part of the code we are // logging, since there may be many PerfLogs in an // application. PerfLog perf_log ("Biharmonic Residual and Jacobian", false); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap& dof_map = get_dof_map(); // Get a constant reference to the Finite Element type // for the first (and only) variable in the system. FEType fe_type = dof_map.variable_type(0); // Build a Finite Element object of the specified type. Since the // \p FEBase::build() member dynamically creates memory we will // store the object as an \p AutoPtr<FEBase>. This can be thought // of as a pointer that will clean up after itself. AutoPtr<FEBase> fe (FEBase::build(_biharmonic._dim, fe_type)); // Quadrature rule for numerical integration. // With 2D triangles, the Clough quadrature rule puts a Gaussian // quadrature rule on each of the 3 subelements AutoPtr<QBase> qrule(fe_type.default_quadrature_rule(_biharmonic._dim)); // Tell the finite element object to use our quadrature rule. fe->attach_quadrature_rule (qrule.get()); // Here we define some references to element-specific data that // will be used to assemble the linear system. // We begin with the element Jacobian * quadrature weight at each // integration point. const std::vector<Real>& JxW = fe->get_JxW(); // The element shape functions evaluated at the quadrature points. const std::vector<std::vector<Real> >& phi = fe->get_phi(); // The element shape functions' derivatives evaluated at the quadrature points. const std::vector<std::vector<RealGradient> >& dphi = fe->get_dphi(); // The element shape functions' second derivatives evaluated at the quadrature points. const std::vector<std::vector<RealTensor> >& d2phi = fe->get_d2phi(); // For efficiency we will compute shape function laplacians n times, // not n^2 std::vector<Real> Laplacian_phi_qp; // Define data structures to contain the element matrix // and right-hand-side vector contribution. Following // basic finite element terminology we will denote these // "Je" and "Re". More detail is in example 3. DenseMatrix<Number> Je; DenseVector<Number> Re; // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<unsigned int> dof_indices; // Old solution const NumericVector<Number>& u_old = *old_local_solution; // Now we will loop over all the elements in the mesh. We will // compute the element matrix and right-hand-side contribution. See // example 3 for a discussion of the element iterators. MeshBase::const_element_iterator el = _biharmonic._mesh->active_local_elements_begin(); const MeshBase::const_element_iterator end_el = _biharmonic._mesh->active_local_elements_end(); for ( ; el != end_el; ++el) { // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem* elem = *el; // Get the degree of freedom indices for the // current element. These define where in the global // matrix and right-hand-side this element will // contribute to. dof_map.dof_indices (elem, dof_indices); // Compute the element-specific data for the current // element. This involves computing the location of the // quadrature points (q_point) and the shape function // values/derivatives (phi, dphi,d2phi) for the current element. fe->reinit (elem); // Zero the element matrix, the right-hand side and the Laplacian matrix // before summing them. if (J) Je.resize(dof_indices.size(), dof_indices.size()); if (R) Re.resize(dof_indices.size()); Laplacian_phi_qp.resize(dof_indices.size()); for (unsigned int qp=0; qp<qrule->n_points(); qp++) { // AUXILIARY QUANTITIES: // Residual and Jacobian share a few calculations: // at the very least, in the case of interfacial energy only with a constant mobility, // both calculations use Laplacian_phi_qp; more is shared the case of a concentration-dependent // mobility and bulk potentials. Number u_qp = 0.0, u_old_qp = 0.0, Laplacian_u_qp = 0.0, Laplacian_u_old_qp = 0.0; Gradient grad_u_qp(0.0,0.0,0.0), grad_u_old_qp(0.0,0.0,0.0); Number M_qp = 1.0, M_old_qp = 1.0, M_prime_qp = 0.0, M_prime_old_qp = 0.0; for (unsigned int i=0; i<phi.size(); i++) { Laplacian_phi_qp[i] = d2phi[i][qp](0,0); grad_u_qp(0) += u(dof_indices[i])*dphi[i][qp](0); grad_u_old_qp(0) += u_old(dof_indices[i])*dphi[i][qp](0); if (_biharmonic._dim > 1) { Laplacian_phi_qp[i] += d2phi[i][qp](1,1); grad_u_qp(1) += u(dof_indices[i])*dphi[i][qp](1); grad_u_old_qp(1) += u_old(dof_indices[i])*dphi[i][qp](1); } if (_biharmonic._dim > 2) { Laplacian_phi_qp[i] += d2phi[i][qp](2,2); grad_u_qp(2) += u(dof_indices[i])*dphi[i][qp](2); grad_u_old_qp(2) += u_old(dof_indices[i])*dphi[i][qp](2); } u_qp += phi[i][qp]*u(dof_indices[i]); u_old_qp += phi[i][qp]*u_old(dof_indices[i]); Laplacian_u_qp += Laplacian_phi_qp[i]*u(dof_indices[i]); Laplacian_u_old_qp += Laplacian_phi_qp[i]*u_old(dof_indices[i]); } // for i if (_biharmonic._degenerate) { M_qp = 1.0 - u_qp*u_qp; M_old_qp = 1.0 - u_old_qp*u_old_qp; M_prime_qp = -2.0*u_qp; M_prime_old_qp = -2.0*u_old_qp; } // ELEMENT RESIDUAL AND JACOBIAN for (unsigned int i=0; i<phi.size(); i++) { // RESIDUAL if (R) { Number ri = 0.0, ri_old = 0.0; ri -= Laplacian_phi_qp[i]*M_qp*_biharmonic._kappa*Laplacian_u_qp; ri_old -= Laplacian_phi_qp[i]*M_old_qp*_biharmonic._kappa*Laplacian_u_old_qp; if (_biharmonic._degenerate) { ri -= (dphi[i][qp]*grad_u_qp)*M_prime_qp*(_biharmonic._kappa*Laplacian_u_qp); ri_old -= (dphi[i][qp]*grad_u_old_qp)*M_prime_old_qp*(_biharmonic._kappa*Laplacian_u_old_qp); } if (_biharmonic._cahn_hillard) { if (_biharmonic._energy == DOUBLE_WELL || _biharmonic._energy == LOG_DOUBLE_WELL) { ri += Laplacian_phi_qp[i]*M_qp*_biharmonic._theta_c*(u_qp*u_qp - 1.0)*u_qp; ri_old += Laplacian_phi_qp[i]*M_old_qp*_biharmonic._theta_c*(u_old_qp*u_old_qp - 1.0)*u_old_qp; if (_biharmonic._degenerate) { ri += (dphi[i][qp]*grad_u_qp)*M_prime_qp*_biharmonic._theta_c*(u_qp*u_qp - 1.0)*u_qp; ri_old += (dphi[i][qp]*grad_u_old_qp)*M_prime_old_qp*_biharmonic._theta_c*(u_old_qp*u_old_qp - 1.0)*u_old_qp; } }// if(_biharmonic._energy == DOUBLE_WELL || _biharmonic._energy == LOG_DOUBLE_WELL) if (_biharmonic._energy == DOUBLE_OBSTACLE || _biharmonic._energy == LOG_DOUBLE_OBSTACLE) { ri -= Laplacian_phi_qp[i]*M_qp*_biharmonic._theta_c*u_qp; ri_old -= Laplacian_phi_qp[i]*M_old_qp*_biharmonic._theta_c*u_old_qp; if (_biharmonic._degenerate) { ri -= (dphi[i][qp]*grad_u_qp)*M_prime_qp*_biharmonic._theta_c*u_qp; ri_old -= (dphi[i][qp]*grad_u_old_qp)*M_prime_old_qp*_biharmonic._theta_c*u_old_qp; } } // if(_biharmonic._energy == DOUBLE_OBSTACLE || _biharmonic._energy == LOG_DOUBLE_OBSTACLE) if (_biharmonic._energy == LOG_DOUBLE_WELL || _biharmonic._energy == LOG_DOUBLE_OBSTACLE) { switch(_biharmonic._log_truncation) { case 2: break; case 3: break; default: break; }// switch(_biharmonic._log_truncation) }// if(_biharmonic._energy == LOG_DOUBLE_WELL || _biharmonic._energy == LOG_DOUBLE_OBSTACLE) }// if(_biharmonic._cahn_hillard) Re(i) += JxW[qp]*((u_qp-u_old_qp)*phi[i][qp]-_biharmonic._dt*0.5*((2.0-_biharmonic._cnWeight)*ri + _biharmonic._cnWeight*ri_old)); } // if (R) // JACOBIAN if (J) { Number M_prime_prime_qp = 0.0; if(_biharmonic._degenerate) M_prime_prime_qp = -2.0; for (unsigned int j=0; j<phi.size(); j++) { Number ri_j = 0.0; ri_j -= Laplacian_phi_qp[i]*M_qp*_biharmonic._kappa*Laplacian_phi_qp[j]; if (_biharmonic._degenerate) { ri_j -= Laplacian_phi_qp[i]*M_prime_qp*phi[j][qp]*_biharmonic._kappa*Laplacian_u_qp + (dphi[i][qp]*dphi[j][qp])*M_prime_qp*(_biharmonic._kappa*Laplacian_u_qp) + (dphi[i][qp]*grad_u_qp)*(M_prime_prime_qp*phi[j][qp])*(_biharmonic._kappa*Laplacian_u_qp) + (dphi[i][qp]*grad_u_qp)*(M_prime_qp)*(_biharmonic._kappa*Laplacian_phi_qp[j]); } if (_biharmonic._cahn_hillard) { if(_biharmonic._energy == DOUBLE_WELL || _biharmonic._energy == LOG_DOUBLE_WELL) { ri_j += Laplacian_phi_qp[i]*M_prime_qp*phi[j][qp]*_biharmonic._theta_c*(u_qp*u_qp - 1.0)*u_qp + Laplacian_phi_qp[i]*M_qp*_biharmonic._theta_c*(3.0*u_qp*u_qp - 1.0)*phi[j][qp] + (dphi[i][qp]*dphi[j][qp])*M_prime_qp*_biharmonic._theta_c*(u_qp*u_qp - 1.0)*u_qp + (dphi[i][qp]*grad_u_qp)*M_prime_prime_qp*_biharmonic._theta_c*(u_qp*u_qp - 1.0)*u_qp + (dphi[i][qp]*grad_u_qp)*M_prime_qp*_biharmonic._theta_c*(3.0*u_qp*u_qp - 1.0)*phi[j][qp]; }// if(_biharmonic._energy == DOUBLE_WELL || _biharmonic._energy == LOG_DOUBLE_WELL) if (_biharmonic._energy == DOUBLE_OBSTACLE || _biharmonic._energy == LOG_DOUBLE_OBSTACLE) { ri_j -= Laplacian_phi_qp[i]*M_prime_qp*phi[j][qp]*_biharmonic._theta_c*u_qp + Laplacian_phi_qp[i]*M_qp*_biharmonic._theta_c*phi[j][qp] + (dphi[i][qp]*dphi[j][qp])*M_prime_qp*_biharmonic._theta_c*u_qp + (dphi[i][qp]*grad_u_qp)*M_prime_prime_qp*_biharmonic._theta_c*u_qp + (dphi[i][qp]*grad_u_qp)*M_prime_qp*_biharmonic._theta_c*phi[j][qp]; } // if(_biharmonic._energy == DOUBLE_OBSTACLE || _biharmonic._energy == LOG_DOUBLE_OBSTACLE) if (_biharmonic._energy == LOG_DOUBLE_WELL || _biharmonic._energy == LOG_DOUBLE_OBSTACLE) { switch(_biharmonic._log_truncation) { case 2: break; case 3: break; default: break; }// switch(_biharmonic._log_truncation) }// if(_biharmonic._energy == LOG_DOUBLE_WELL || _biharmonic._energy == LOG_DOUBLE_OBSTACLE) }// if(_biharmonic._cahn_hillard) Je(i,j) += JxW[qp]*(phi[i][qp]*phi[j][qp] - 0.5*_biharmonic._dt*(2.0-_biharmonic._cnWeight)*ri_j); } // for j } // if (J) } // for i } // for qp // The element matrix and right-hand-side are now built // for this element. Add them to the global matrix and // right-hand-side vector. The \p SparseMatrix::add_matrix() // and \p NumericVector::add_vector() members do this for us. // Start logging the insertion of the local (element) // matrix and vector into the global matrix and vector if (R) { // If the mesh has hanging nodes (e.g., as a result of refinement), those need to be constrained. dof_map.constrain_element_vector(Re, dof_indices); R->add_vector(Re, dof_indices); } if (J) { // If the mesh has hanging nodes (e.g., as a result of refinement), those need to be constrained. dof_map.constrain_element_matrix(Je, dof_indices); J->add_matrix(Je, dof_indices); } } // for el #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES }