Esempio n. 1
0
/**
 * 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;
}
Esempio n. 5
0
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);
    } 
}
Esempio n. 6
0
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
}