int main (int argc, char** argv) { libMesh::init (argc, argv); { std::cout << "Running " << argv[0]; for (int i=1; i<argc; i++) std::cout << " " << argv[i]; std::cout << std::endl << std::endl; config.load(); config.print(); PerfLog perf("Main Program"); perf.start_event("program init"); Mesh mesh (config.dim); MeshData mesh_data(mesh); //mesh_data.activate(); mesh_data.enable_compatibility_mode(); mesh.read("tmp/in.xda",&mesh_data); mesh.find_neighbors(); //mesh_data.read("data.xta"); //mesh.print_info(); EquationSystems equation_systems (mesh,&mesh_data); LinearImplicitSystem & eigen_system = equation_systems.add_system<LinearImplicitSystem> ("Poisson"); //equation_systems.add_system<EigenSystem> ("Poisson"); equation_systems.get_system("Poisson").add_variable("u", FIRST); equation_systems.get_system("Poisson").attach_assemble_function (assemble_poisson); unsigned int nev = config.eigs; equation_systems.parameters.set<unsigned int>("eigenpairs") = nev; equation_systems.parameters.set<unsigned int>("basis vectors") = nev*3; // eigen_system.eigen_solver-> set_eigensolver_type(ARNOLDI); //eigen_system.eigen_solver-> set_eigensolver_type(SUBSPACE); //eigen_system.eigen_solver-> set_eigensolver_type(POWER); // eigen_system.eigen_solver-> set_eigensolver_type(LANCZOS); // eigen_system.set_eigenproblem_type(GHEP); // eigen_system.eigen_solver->set_position_of_spectrum(SMALLEST_MAGNITUDE); //eigen_system.eigen_solver->set_position_of_spectrum(LARGEST_MAGNITUDE); equation_systems.parameters.set<Real>("linear solver tolerance") = pow(TOLERANCE, 5./3.); equation_systems.parameters.set<unsigned int> ("linear solver maximum iterations") = 1000; equation_systems.init(); //equation_systems.print_info(); perf.stop_event("program init"); if (config.assemble) { assemble_poisson(equation_systems, "Poisson"); } if (!config.printlog) perf.clear(); } return libMesh::close(); }
// The main program int main(int argc, char** argv) { // Initialize libMesh LibMeshInit init(argc, argv); // Parameters GetPot infile("fem_system_params.in"); const Real global_tolerance = infile("global_tolerance", 0.); const unsigned int nelem_target = infile("n_elements", 400); const bool transient = infile("transient", true); const Real deltat = infile("deltat", 0.005); unsigned int n_timesteps = infile("n_timesteps", 1); //const unsigned int coarsegridsize = infile("coarsegridsize", 1); const unsigned int coarserefinements = infile("coarserefinements", 0); const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10); //const unsigned int dim = 2; #ifdef LIBMESH_HAVE_EXODUS_API const unsigned int write_interval = infile("write_interval", 5); #endif // Create a mesh, with dimension to be overridden later, distributed // across the default MPI communicator. Mesh mesh(init.comm()); GetPot infileForMesh("convdiff_mprime.in"); std::string find_mesh_here = infileForMesh("mesh","psiLF_mesh.xda"); mesh.read(find_mesh_here); std::cout << "Read in mesh from: " << find_mesh_here << "\n\n"; // And an object to refine it MeshRefinement mesh_refinement(mesh); mesh_refinement.coarsen_by_parents() = true; mesh_refinement.absolute_global_tolerance() = global_tolerance; mesh_refinement.nelem_target() = nelem_target; mesh_refinement.refine_fraction() = 0.3; mesh_refinement.coarsen_fraction() = 0.3; mesh_refinement.coarsen_threshold() = 0.1; //mesh_refinement.uniformly_refine(coarserefinements); // Print information about the mesh to the screen. mesh.print_info(); // Create an equation systems object. EquationSystems equation_systems (mesh); // Name system ConvDiff_MprimeSys & system = equation_systems.add_system<ConvDiff_MprimeSys>("Diff_ConvDiff_MprimeSys"); // Steady-state problem system.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system)); // Sanity check that we are indeed solving a steady problem libmesh_assert_equal_to (n_timesteps, 1); // Read in all the equation systems data from the LF solve (system, solutions, rhs, etc) std::string find_psiLF_here = infileForMesh("psiLF_file","psiLF.xda"); std::cout << "Looking for psiLF at: " << find_psiLF_here << "\n\n"; equation_systems.read(find_psiLF_here, READ, EquationSystems::READ_HEADER | EquationSystems::READ_DATA | EquationSystems::READ_ADDITIONAL_DATA); // Check that the norm of the solution read in is what we expect it to be Real readin_L2 = system.calculate_norm(*system.solution, 0, L2); std::cout << "Read in solution norm: "<< readin_L2 << std::endl << std::endl; //DEBUG //equation_systems.write("right_back_out.xda", WRITE, EquationSystems::WRITE_DATA | // EquationSystems::WRITE_ADDITIONAL_DATA); #ifdef LIBMESH_HAVE_GMV //GMVIO(equation_systems.get_mesh()).write_equation_systems(std::string("right_back_out.gmv"), equation_systems); #endif // Initialize the system //equation_systems.init (); //already initialized by read-in // And the nonlinear solver options NewtonSolver *solver = new NewtonSolver(system); system.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver); solver->quiet = infile("solver_quiet", true); solver->verbose = !solver->quiet; solver->max_nonlinear_iterations = infile("max_nonlinear_iterations", 15); solver->relative_step_tolerance = infile("relative_step_tolerance", 1.e-3); solver->relative_residual_tolerance = infile("relative_residual_tolerance", 0.0); solver->absolute_residual_tolerance = infile("absolute_residual_tolerance", 0.0); // And the linear solver options solver->max_linear_iterations = infile("max_linear_iterations", 50000); solver->initial_linear_tolerance = infile("initial_linear_tolerance", 1.e-3); // Print information about the system to the screen. equation_systems.print_info(); // Now we begin the timestep loop to compute the time-accurate // solution of the equations...not that this is transient, but eh, why not... for (unsigned int t_step=0; t_step != n_timesteps; ++t_step) { // A pretty update message std::cout << "\n\nSolving time step " << t_step << ", time = " << system.time << std::endl; // Adaptively solve the timestep unsigned int a_step = 0; for (; a_step != max_adaptivesteps; ++a_step) { // VESTIGIAL for now ('vestigial' eh ? ;) ) std::cout << "\n\n I should be skipped what are you doing here lalalalalalala *!**!*!*!*!*!* \n\n"; system.solve(); system.postprocess(); ErrorVector error; AutoPtr<ErrorEstimator> error_estimator; // To solve to a tolerance in this problem we // need a better estimator than Kelly if (global_tolerance != 0.) { // We can't adapt to both a tolerance and a mesh // size at once libmesh_assert_equal_to (nelem_target, 0); UniformRefinementEstimator *u = new UniformRefinementEstimator; // The lid-driven cavity problem isn't in H1, so // lets estimate L2 error u->error_norm = L2; error_estimator.reset(u); } else { // If we aren't adapting to a tolerance we need a // target mesh size libmesh_assert_greater (nelem_target, 0); // Kelly is a lousy estimator to use for a problem // not in H1 - if we were doing more than a few // timesteps we'd need to turn off or limit the // maximum level of our adaptivity eventually error_estimator.reset(new KellyErrorEstimator); } // Calculate error std::vector<Real> weights(9,1.0); // based on u, v, p, c, their adjoints, and source parameter // Keep the same default norm type. std::vector<FEMNormType> norms(1, error_estimator->error_norm.type(0)); error_estimator->error_norm = SystemNorm(norms, weights); error_estimator->estimate_error(system, error); // Print out status at each adaptive step. Real global_error = error.l2_norm(); std::cout << "Adaptive step " << a_step << ": " << std::endl; if (global_tolerance != 0.) std::cout << "Global_error = " << global_error << std::endl; if (global_tolerance != 0.) std::cout << "Worst element error = " << error.maximum() << ", mean = " << error.mean() << std::endl; if (global_tolerance != 0.) { // If we've reached our desired tolerance, we // don't need any more adaptive steps if (global_error < global_tolerance) break; mesh_refinement.flag_elements_by_error_tolerance(error); } else { // If flag_elements_by_nelem_target returns true, this // should be our last adaptive step. if (mesh_refinement.flag_elements_by_nelem_target(error)) { mesh_refinement.refine_and_coarsen_elements(); equation_systems.reinit(); a_step = max_adaptivesteps; break; } } // Carry out the adaptive mesh refinement/coarsening mesh_refinement.refine_and_coarsen_elements(); equation_systems.reinit(); std::cout << "Refined mesh to " << mesh.n_active_elem() << " active elements and " << equation_systems.n_active_dofs() << " active dofs." << std::endl; } // End loop over adaptive steps // Do one last solve if necessary if (a_step == max_adaptivesteps) { QoISet qois; std::vector<unsigned int> qoi_indices; qoi_indices.push_back(0); qois.add_indices(qoi_indices); qois.set_weight(0, 1.0); system.assemble_qoi_sides = true; //QoI doesn't involve sides std::cout << "\n~*~*~*~*~*~*~*~*~ adjoint solve start ~*~*~*~*~*~*~*~*~\n" << std::endl; std::pair<unsigned int, Real> adjsolve = system.adjoint_solve(); std::cout << "number of iterations to solve adjoint: " << adjsolve.first << std::endl; std::cout << "final residual of adjoint solve: " << adjsolve.second << std::endl; std::cout << "\n~*~*~*~*~*~*~*~*~ adjoint solve end ~*~*~*~*~*~*~*~*~" << std::endl; NumericVector<Number> &dual_solution = system.get_adjoint_solution(0); NumericVector<Number> &primal_solution = *system.solution; primal_solution.swap(dual_solution); ExodusII_IO(mesh).write_timestep("super_adjoint.exo", equation_systems, 1, /* This number indicates how many time steps are being written to the file */ system.time); primal_solution.swap(dual_solution); system.assemble(); //overwrite residual read in from psiLF solve // The total error estimate system.postprocess(); //to compute M_HF(psiLF) and M_LF(psiLF) terms Real QoI_error_estimate = (-0.5*(system.rhs)->dot(dual_solution)) + system.get_MHF_psiLF() - system.get_MLF_psiLF(); std::cout << "\n\n 0.5*M'_HF(psiLF)(superadj): " << std::setprecision(17) << 0.5*(system.rhs)->dot(dual_solution) << "\n"; std::cout << " M_HF(psiLF): " << std::setprecision(17) << system.get_MHF_psiLF() << "\n"; std::cout << " M_LF(psiLF): " << std::setprecision(17) << system.get_MLF_psiLF() << "\n"; std::cout << "\n\n Residual L2 norm: " << system.calculate_norm(*system.rhs, L2) << "\n"; std::cout << " Residual discrete L2 norm: " << system.calculate_norm(*system.rhs, DISCRETE_L2) << "\n"; std::cout << " Super-adjoint L2 norm: " << system.calculate_norm(dual_solution, L2) << "\n"; std::cout << " Super-adjoint discrete L2 norm: " << system.calculate_norm(dual_solution, DISCRETE_L2) << "\n"; std::cout << "\n\n QoI error estimate: " << std::setprecision(17) << QoI_error_estimate << "\n\n"; //DEBUG std::cout << "\n------------ herp derp ------------" << std::endl; //libMesh::out.precision(16); //dual_solution.print(); //system.get_adjoint_rhs().print(); AutoPtr<NumericVector<Number> > adjresid = system.solution->clone(); (system.matrix)->vector_mult(*adjresid,system.get_adjoint_solution(0)); SparseMatrix<Number>& adjmat = *system.matrix; (system.matrix)->get_transpose(adjmat); adjmat.vector_mult(*adjresid,system.get_adjoint_solution(0)); //std::cout << "******************** matrix-superadj product (libmesh) ************************" << std::endl; //adjresid->print(); adjresid->add(-1.0, system.get_adjoint_rhs(0)); //std::cout << "******************** superadjoint system residual (libmesh) ***********************" << std::endl; //adjresid->print(); std::cout << "\n\nadjoint system residual (discrete L2): " << system.calculate_norm(*adjresid,DISCRETE_L2) << std::endl; std::cout << "adjoint system residual (L2, all): " << system.calculate_norm(*adjresid,L2) << std::endl; std::cout << "adjoint system residual (L2, 0): " << system.calculate_norm(*adjresid,0,L2) << std::endl; std::cout << "adjoint system residual (L2, 1): " << system.calculate_norm(*adjresid,1,L2) << std::endl; std::cout << "adjoint system residual (L2, 2): " << system.calculate_norm(*adjresid,2,L2) << std::endl; std::cout << "adjoint system residual (L2, 3): " << system.calculate_norm(*adjresid,3,L2) << std::endl; std::cout << "adjoint system residual (L2, 4): " << system.calculate_norm(*adjresid,4,L2) << std::endl; std::cout << "adjoint system residual (L2, 5): " << system.calculate_norm(*adjresid,5,L2) << std::endl; /* AutoPtr<NumericVector<Number> > sadj_matlab = system.solution->clone(); AutoPtr<NumericVector<Number> > adjresid_matlab = system.solution->clone(); if(FILE *fp=fopen("superadj_matlab.txt","r")){ Real value; int counter = 0; int flag = 1; while(flag != -1){ flag = fscanf(fp,"%lf",&value); if(flag != -1){ sadj_matlab->set(counter, value); counter += 1; } } fclose(fp); } (system.matrix)->vector_mult(*adjresid_matlab,*sadj_matlab); //std::cout << "******************** matrix-superadj product (matlab) ***********************" << std::endl; //adjresid_matlab->print(); adjresid_matlab->add(-1.0, system.get_adjoint_rhs(0)); //std::cout << "******************** superadjoint system residual (matlab) ***********************" << std::endl; //adjresid_matlab->print(); std::cout << "\n\nmatlab import adjoint system residual (discrete L2): " << system.calculate_norm(*adjresid_matlab,DISCRETE_L2) << "\n" << std::endl; */ /* AutoPtr<NumericVector<Number> > sadj_fwd_hack = system.solution->clone(); AutoPtr<NumericVector<Number> > adjresid_fwd_hack = system.solution->clone(); if(FILE *fp=fopen("superadj_forward_hack.txt","r")){ Real value; int counter = 0; int flag = 1; while(flag != -1){ flag = fscanf(fp,"%lf",&value); if(flag != -1){ sadj_fwd_hack->set(counter, value); counter += 1; } } fclose(fp); } (system.matrix)->vector_mult(*adjresid_fwd_hack,*sadj_fwd_hack); //std::cout << "******************** matrix-superadj product (fwd_hack) ***********************" << std::endl; //adjresid_fwd_hack->print(); adjresid_fwd_hack->add(-1.0, system.get_adjoint_rhs(0)); //std::cout << "******************** superadjoint system residual (fwd_hack) ***********************" << std::endl; //adjresid_fwd_hack->print(); std::cout << "\n\nfwd_hack import adjoint system residual (discrete L2): " << system.calculate_norm(*adjresid_fwd_hack,DISCRETE_L2) << "\n" << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 0): " << system.calculate_norm(*adjresid_fwd_hack,0,L2) << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 1): " << system.calculate_norm(*adjresid_fwd_hack,1,L2) << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 2): " << system.calculate_norm(*adjresid_fwd_hack,2,L2) << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 3): " << system.calculate_norm(*adjresid_fwd_hack,3,L2) << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 4): " << system.calculate_norm(*adjresid_fwd_hack,4,L2) << std::endl; std::cout << "fwd_hack adjoint system residual (L2, 5): " << system.calculate_norm(*adjresid_fwd_hack,5,L2) << std::endl; */ //std::cout << "************************ system.matrix ***********************" << std::endl; //system.matrix->print(); std::cout << "\n------------ herp derp ------------" << std::endl; // The cell wise breakdown ErrorVector cell_wise_error; cell_wise_error.resize((system.rhs)->size()); for(unsigned int i = 0; i < (system.rhs)->size() ; i++) { if(i < system.get_mesh().n_elem()) cell_wise_error[i] = fabs(-0.5*((system.rhs)->el(i) * dual_solution(i)) + system.get_MHF_psiLF(i) - system.get_MLF_psiLF(i)); else cell_wise_error[i] = fabs(-0.5*((system.rhs)->el(i) * dual_solution(i))); /*csv from 'save data' from gmv output gives a few values at each node point (value for every element that shares that node), yet paraview display only seems to show one of them -> the value in an element is given at each of the nodes that it has, hence the repetition; what is displayed in paraview is each element's value; even though MHF_psiLF and MLF_psiLF are stored by element this seems to give elemental contributions that agree with if we had taken the superadj-residual dot product by integrating over elements*/ /*at higher mesh resolutions and lower k, weird-looking artifacts start to appear and it no longer agrees with output from manual integration of superadj-residual...*/ } // Plot it std::ostringstream error_gmv; error_gmv << "error.gmv"; cell_wise_error.plot_error(error_gmv.str(), equation_systems.get_mesh()); //alternate element-wise breakdown, outputed as values matched to element centroids; for matlab plotz primal_solution.swap(dual_solution); system.postprocess(1); primal_solution.swap(dual_solution); system.postprocess(2); std::cout << "\n\n -0.5*M'_HF(psiLF)(superadj): " << std::setprecision(17) << system.get_half_adj_weighted_resid() << "\n"; primal_solution.swap(dual_solution); std::string write_error_here = infileForMesh("error_est_output_file", "error_est_breakdown.dat"); std::ofstream output(write_error_here); for(unsigned int i = 0 ; i < system.get_mesh().n_elem(); i++) { Point elem_cent = system.get_mesh().elem(i)->centroid(); if(output.is_open()) { output << elem_cent(0) << " " << elem_cent(1) << " " << fabs(system.get_half_adj_weighted_resid(i) + system.get_MHF_psiLF(i) - system.get_MLF_psiLF(i)) << "\n"; } } output.close(); } // End if at max adaptive steps #ifdef LIBMESH_HAVE_EXODUS_API // Write out this timestep if we're requested to if ((t_step+1)%write_interval == 0) { std::ostringstream file_name; /* // We write the file in the ExodusII format. file_name << "out_" << std::setw(3) << std::setfill('0') << std::right << t_step+1 << ".e"; //this should write out the primal which should be the same as what's read in... ExodusII_IO(mesh).write_timestep(file_name.str(), equation_systems, 1, //number of time steps written to file system.time); */ } #endif // #ifdef LIBMESH_HAVE_EXODUS_API } // All done. return 0; } //end main
// The main program. int main (int argc, char** argv) { // Skip adaptive examples on a non-adaptive libMesh build #ifndef LIBMESH_ENABLE_AMR libmesh_example_assert(false, "--enable-amr"); #else // Skip this 2D example if libMesh was compiled as 1D-only. libmesh_example_assert(2 <= LIBMESH_DIM, "2D support"); // Initialize libMesh. LibMeshInit init (argc, argv); std::cout << "Started " << argv[0] << std::endl; // Make sure the general input file exists, and parse it { std::ifstream i("general.in"); if (!i) { std::cerr << '[' << init.comm().rank() << "] Can't find general.in; exiting early." << std::endl; libmesh_error(); } } GetPot infile("general.in"); // Read in parameters from the input file FEMParameters param; param.read(infile); // Create a mesh with the given dimension, distributed // across the default MPI communicator. Mesh mesh(init.comm(), param.dimension); // And an object to refine it AutoPtr<MeshRefinement> mesh_refinement(new MeshRefinement(mesh)); // And an EquationSystems to run on it EquationSystems equation_systems (mesh); std::cout << "Building mesh" << std::endl; // Build a unit square ElemType elemtype; if (param.elementtype == "tri" || param.elementtype == "unstructured") elemtype = TRI3; else elemtype = QUAD4; MeshTools::Generation::build_square (mesh, param.coarsegridx, param.coarsegridy, param.domain_xmin, param.domain_xmin + param.domain_edge_width, param.domain_ymin, param.domain_ymin + param.domain_edge_length, elemtype); std::cout << "Building system" << std::endl; HeatSystem &system = equation_systems.add_system<HeatSystem> ("HeatSystem"); set_system_parameters(system, param); std::cout << "Initializing systems" << std::endl; // Initialize the system equation_systems.init (); // Refine the grid again if requested for (unsigned int i=0; i != param.extrarefinements; ++i) { mesh_refinement->uniformly_refine(1); equation_systems.reinit(); } std::cout<<"Setting primal initial conditions"<<std::endl; read_initial_parameters(); system.project_solution(initial_value, initial_grad, equation_systems.parameters); // Output the H1 norm of the initial conditions libMesh::out << "|U(" <<system.time<< ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl<<std::endl; // Add an adjoint vector, this will be computed after the forward // time stepping is complete // // Tell the library not to save adjoint solutions during the forward // solve // // Tell the library not to project this vector, and hence, memory // solution history to not save it. // // Make this vector ghosted so we can localize it to each element // later. const std::string & adjoint_solution_name = "adjoint_solution0"; system.add_vector("adjoint_solution0", false, GHOSTED); // Close up any resources initial.C needed finish_initialization(); // Plot the initial conditions write_output(equation_systems, 0, "primal"); // Print information about the mesh and system to the screen. mesh.print_info(); equation_systems.print_info(); // In optimized mode we catch any solver errors, so that we can // write the proper footers before closing. In debug mode we just // let the exception throw so that gdb can grab it. #ifdef NDEBUG try { #endif // Now we begin the timestep loop to compute the time-accurate // solution of the equations. for (unsigned int t_step=param.initial_timestep; t_step != param.initial_timestep + param.n_timesteps; ++t_step) { // A pretty update message std::cout << " Solving time step " << t_step << ", time = " << system.time << std::endl; // Solve the forward problem at time t, to obtain the solution at time t + dt system.solve(); // Output the H1 norm of the computed solution libMesh::out << "|U(" <<system.time + system.deltat<< ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl; // Advance to the next timestep in a transient problem std::cout<<"Advancing timestep"<<std::endl<<std::endl; system.time_solver->advance_timestep(); // Write out this timestep write_output(equation_systems, t_step+1, "primal"); } // End timestep loop ///////////////// Now for the Adjoint Solution ////////////////////////////////////// // Now we will solve the backwards in time adjoint problem std::cout << std::endl << "Solving the adjoint problem" << std::endl; // We need to tell the library that it needs to project the adjoint, so // MemorySolutionHistory knows it has to save it // Tell the library to project the adjoint vector, and hence, memory solution history to // save it system.set_vector_preservation(adjoint_solution_name, true); std::cout << "Setting adjoint initial conditions Z("<<system.time<<")"<<std::endl; // Need to call adjoint_advance_timestep once for the initial condition setup std::cout<<"Retrieving solutions at time t="<<system.time<<std::endl; system.time_solver->adjoint_advance_timestep(); // Output the H1 norm of the retrieved solutions (u^i and u^i+1) libMesh::out << "|U(" <<system.time + system.deltat<< ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl; libMesh::out << "|U(" <<system.time<< ")|= " << system.calculate_norm(system.get_vector("_old_nonlinear_solution"), 0, H1) << std::endl; // The first thing we have to do is to apply the adjoint initial // condition. The user should supply these. Here they are specified // in the functions adjoint_initial_value and adjoint_initial_gradient system.project_vector(adjoint_initial_value, adjoint_initial_grad, equation_systems.parameters, system.get_adjoint_solution(0)); // Since we have specified an adjoint solution for the current time (T), set the adjoint_already_solved boolean to true, so we dont solve unneccesarily in the adjoint sensitivity method system.set_adjoint_already_solved(true); libMesh::out << "|Z(" <<system.time<< ")|= " << system.calculate_norm(system.get_adjoint_solution(), 0, H1) << std::endl<<std::endl; write_output(equation_systems, param.n_timesteps, "dual"); // Now that the adjoint initial condition is set, we will start the // backwards in time adjoint integration // For loop stepping backwards in time for (unsigned int t_step=param.initial_timestep; t_step != param.initial_timestep + param.n_timesteps; ++t_step) { //A pretty update message std::cout << " Solving adjoint time step " << t_step << ", time = " << system.time << std::endl; // The adjoint_advance_timestep // function calls the retrieve function of the memory_solution_history // class via the memory_solution_history object we declared earlier. // The retrieve function sets the system primal vectors to their values // at the current timestep std::cout<<"Retrieving solutions at time t="<<system.time<<std::endl; system.time_solver->adjoint_advance_timestep(); // Output the H1 norm of the retrieved solution libMesh::out << "|U(" <<system.time + system.deltat << ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl; libMesh::out << "|U(" <<system.time<< ")|= " << system.calculate_norm(system.get_vector("_old_nonlinear_solution"), 0, H1) << std::endl; system.set_adjoint_already_solved(false); system.adjoint_solve(); // Now that we have solved the adjoint, set the adjoint_already_solved boolean to true, so we dont solve unneccesarily in the error estimator system.set_adjoint_already_solved(true); libMesh::out << "|Z(" <<system.time<< ")|= "<< system.calculate_norm(system.get_adjoint_solution(), 0, H1) << std::endl << std::endl; // Get a pointer to the primal solution vector NumericVector<Number> &primal_solution = *system.solution; // Get a pointer to the solution vector of the adjoint problem for QoI 0 NumericVector<Number> &dual_solution_0 = system.get_adjoint_solution(0); // Swap the primal and dual solutions so we can write out the adjoint solution primal_solution.swap(dual_solution_0); write_output(equation_systems, param.n_timesteps - (t_step + 1), "dual"); // Swap back primal_solution.swap(dual_solution_0); } // End adjoint timestep loop // Now that we have computed both the primal and adjoint solutions, we compute the sensitivties to the parameter p // dQ/dp = partialQ/partialp - partialR/partialp // partialQ/partialp = (Q(p+dp) - Q(p-dp))/(2*dp), this is not supported by the library yet // partialR/partialp = (R(u,z;p+dp) - R(u,z;p-dp))/(2*dp), where // R(u,z;p+dp) = int_{0}^{T} f(z;p+dp) - <partialu/partialt, z>(p+dp) - <g(u),z>(p+dp) // To do this we need to step forward in time, and compute the perturbed R at each time step and accumulate it // Then once all time steps are over, we can compute (R(u,z;p+dp) - R(u,z;p-dp))/(2*dp) // Now we begin the timestep loop to compute the time-accurate // adjoint sensitivities for (unsigned int t_step=param.initial_timestep; t_step != param.initial_timestep + param.n_timesteps; ++t_step) { // A pretty update message std::cout << "Retrieving " << t_step << ", time = " << system.time << std::endl; // Retrieve the primal and adjoint solutions at the current timestep system.time_solver->retrieve_timestep(); libMesh::out << "|U(" <<system.time + system.deltat << ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl; libMesh::out << "|U(" <<system.time<< ")|= " << system.calculate_norm(system.get_vector("_old_nonlinear_solution"), 0, H1) << std::endl; libMesh::out << "|Z(" <<system.time<< ")|= "<< system.calculate_norm(system.get_adjoint_solution(0), 0, H1) << std::endl << std::endl; // Call the postprocess function which we have overloaded to compute // accumulate the perturbed residuals (dynamic_cast<HeatSystem&>(system)).perturb_accumulate_residuals(dynamic_cast<HeatSystem&>(system).get_parameter_vector()); // Move the system time forward (retrieve_timestep does not do this) system.time += system.deltat; } // A pretty update message std::cout << "Retrieving " << " final time = " << system.time << std::endl; // Retrieve the primal and adjoint solutions at the current timestep system.time_solver->retrieve_timestep(); libMesh::out << "|U(" <<system.time + system.deltat << ")|= " << system.calculate_norm(*system.solution, 0, H1) << std::endl; libMesh::out << "|U(" <<system.time<< ")|= " << system.calculate_norm(system.get_vector("_old_nonlinear_solution"), 0, H1) << std::endl; libMesh::out << "|Z(" <<system.time<< ")|= "<< system.calculate_norm(system.get_adjoint_solution(0), 0, H1) << std::endl<<std::endl; // Call the postprocess function which we have overloaded to compute // accumulate the perturbed residuals (dynamic_cast<HeatSystem&>(system)).perturb_accumulate_residuals(dynamic_cast<HeatSystem&>(system).get_parameter_vector()); // Now that we computed the accumulated, perturbed residuals, we can compute the // approximate sensitivity Number sensitivity_0_0 = (dynamic_cast<HeatSystem&>(system)).compute_final_sensitivity(); // Print it out std::cout<<"Sensitivity of QoI 0 w.r.t parameter 0 is: " << sensitivity_0_0 << std::endl; #ifdef NDEBUG } catch (...) { std::cerr << '[' << mesh.processor_id() << "] Caught exception; exiting early." << std::endl; } #endif std::cerr << '[' << mesh.processor_id() << "] Completing output." << std::endl; // All done. return 0; #endif // LIBMESH_ENABLE_AMR }
int main(int argc, char** argv){ //initialize libMesh LibMeshInit init(argc, argv); //parameters GetPot infile("fem_system_params.in"); unsigned int n_timesteps = infile("n_timesteps", 1); //Real init_dR = infile("init_dR",1.e-3); const int nx = infile("nx",100); const int ny = infile("ny",100); const int nz = infile("nz",100); GetPot infileForMesh("contamTrans.in"); bool doContinuation = infileForMesh("do_continuation",false); bool doArcLengthContinuation = infileForMesh("do_arclength_continuation",false); // Create a mesh, with dimension to be overridden later, distributed // across the default MPI communicator. Mesh mesh(init.comm()); //create mesh unsigned int dim; if(nz == 0){ //to check if oscillations happen in 2D as well... dim = 2; MeshTools::Generation::build_square(mesh, nx, ny, 0., 2300., 0., 1650., QUAD9); }else{ dim = 3; MeshTools::Generation::build_cube(mesh, nx, ny, nz, 0., 2300., 0., 1650., 0., 100., HEX27); } // Print information about the mesh to the screen. mesh.print_info(); //DEBUG // Create an equation systems object. EquationSystems equation_systems (mesh); //name system ContamTransSysInv & system = equation_systems.add_system<ContamTransSysInv>("ContamTransInv"); //system.min_continuation_parameter = 0.; //system.max_continuation_parameter = std::fabs(infileForMesh("reaction_rate",1.e-3)); //steady-state problem system.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system)); libmesh_assert_equal_to (n_timesteps, 1); // Initialize the system equation_systems.init (); //initial conditions read_initial_parameters(); system.project_solution(initial_value, initial_grad, equation_systems.parameters); finish_initialization(); // And the nonlinear solver options NewtonSolver *solver = new NewtonSolver(system); system.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver); solver->quiet = infile("solver_quiet", true); solver->verbose = !solver->quiet; solver->max_nonlinear_iterations = infile("max_nonlinear_iterations", 15); solver->relative_step_tolerance = infile("relative_step_tolerance", 1.e-3); solver->relative_residual_tolerance = infile("relative_residual_tolerance", 0.0); solver->absolute_residual_tolerance = infile("absolute_residual_tolerance", 0.0); // And the linear solver options solver->max_linear_iterations = infile("max_linear_iterations", 10000); solver->initial_linear_tolerance = infile("initial_linear_tolerance",1.e-13); solver->minimum_linear_tolerance = infile("minimum_linear_tolerance",1.e-13); solver->linear_tolerance_multiplier = infile("linear_tolerance_multiplier",1.e-3); // Print information about the system to the screen. equation_systems.print_info(); //DEBUG Real target_R = infileForMesh("reaction_rate",1.e-3); if(!doContinuation){ system.set_R(target_R); system.solve(); }else if(doArcLengthContinuation){ std::cout << "\n\nAAAAAAAAAAAAAHHHHHHHHH this arc-length continuation doesn't work yet...\n\n" << std::endl; /* system.quiet = infile("solver_quiet", true); system.set_max_arclength_stepsize(infile("max_ds",1.e2)); //two prior solutions system.set_R(0.); system.solve(); //first solution system.save_current_solution(); std::cout << "\n First solve finished..." << std::endl; system.set_R(init_dR); system.solve(); //second solution std::cout << "\n Second solve finished..." << std::endl; //continuation steps //system.set_R(target_R); system.continuation_solve(); //doesn't seem to move away first step...what is this even supposed to do? std::cout << "\n Continuation solve done..." << std::endl; Real Rcurr = system.get_R(); int iter = 0; while(system.get_R() < 0.99*target_R && iter < infile("max_arcsteps",10)){ system.advance_arcstep(); system.solve(); std::cout << "\nR: " << system.get_R() << std::endl; std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; iter += 1; } */ }else{ //natural continuation std::vector<double> Rsteps; if(FILE *fp=fopen("continuation_steps.txt","r")){ Real value; int flag = 1; while(flag != -1){ flag = fscanf(fp,"%lf",&value); if(flag != -1){ Rsteps.push_back(value); } } fclose(fp); }else{ std::cout << "\n\n Need to define continuation steps in continuation_steps.txt\n\n" << std::endl; } for(int i = 0; i < Rsteps.size(); i++){ double R = Rsteps[i]; system.set_R(R); std::cout << "\n\nStarting iteration with R = " << R << "\n\n" << std::endl; system.solve(); } } //end continuation type switch system.postprocess(); Number QoI_computed = system.get_QoI_value("computed", 0); std::cout<< "Computed QoI is " << std::setprecision(17) << QoI_computed << std::endl; // All done. return 0; } //end main
int main(int argc, char** argv){ //initialize libMesh LibMeshInit init(argc, argv); //parameters GetPot infile("fem_system_params.in"); const Real global_tolerance = infile("global_tolerance", 0.); const unsigned int nelem_target = infile("n_elements", 400); const bool transient = infile("transient", true); const Real deltat = infile("deltat", 0.005); unsigned int n_timesteps = infile("n_timesteps", 1); //const unsigned int coarsegridsize = infile("coarsegridsize", 1); const unsigned int coarserefinements = infile("coarserefinements", 0); const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10); //const unsigned int dim = 2; #ifdef LIBMESH_HAVE_EXODUS_API const unsigned int write_interval = infile("write_interval", 5); #endif // Create a mesh, with dimension to be overridden later, distributed // across the default MPI communicator. Mesh mesh(init.comm()); Mesh mesh2(init.comm()); GetPot infileForMesh("convdiff_mprime.in"); std::string find_mesh_here = infileForMesh("divided_mesh","meep.exo"); mesh.read(find_mesh_here); mesh2.read(find_mesh_here); //mesh.read("psiHF_mesh_1Dfused.xda"); // And an object to refine it /*MeshRefinement mesh_refinement(mesh); mesh_refinement.coarsen_by_parents() = true; mesh_refinement.absolute_global_tolerance() = global_tolerance; mesh_refinement.nelem_target() = nelem_target; mesh_refinement.refine_fraction() = 0.3; mesh_refinement.coarsen_fraction() = 0.3; mesh_refinement.coarsen_threshold() = 0.1; mesh_refinement.uniformly_refine(coarserefinements);*/ // Print information about the mesh to the screen. mesh.print_info(); // Create an equation systems object. EquationSystems equation_systems (mesh); EquationSystems equation_systems_mix(mesh2); //name system ConvDiff_PrimarySys & system_primary = equation_systems.add_system<ConvDiff_PrimarySys>("ConvDiff_PrimarySys"); ConvDiff_AuxSys & system_aux = equation_systems.add_system<ConvDiff_AuxSys>("ConvDiff_AuxSys"); ConvDiff_MprimeSys & system_mix = equation_systems_mix.add_system<ConvDiff_MprimeSys>("ConvDiff_MprimeSys"); //steady-state problem system_primary.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system_primary)); system_aux.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system_aux)); system_mix.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system_mix)); libmesh_assert_equal_to (n_timesteps, 1); /*equation_systems.read("psiLF.xda", READ, EquationSystems::READ_HEADER | EquationSystems::READ_DATA | EquationSystems::READ_ADDITIONAL_DATA); equation_systems.print_info();*/ // Initialize the system equation_systems.init (); // Set the time stepping options system_primary.deltat = deltat; system_aux.deltat = deltat;//this is ignored for SteadySolver...right? // And the nonlinear solver options NewtonSolver *solver_primary = new NewtonSolver(system_primary); system_primary.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver_primary); solver_primary->quiet = infile("solver_quiet", true); solver_primary->verbose = !solver_primary->quiet; solver_primary->max_nonlinear_iterations = infile("max_nonlinear_iterations", 15); solver_primary->relative_step_tolerance = infile("relative_step_tolerance", 1.e-3); solver_primary->relative_residual_tolerance = infile("relative_residual_tolerance", 0.0); solver_primary->absolute_residual_tolerance = infile("absolute_residual_tolerance", 0.0); NewtonSolver *solver_aux = new NewtonSolver(system_aux); system_aux.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver_aux); solver_aux->quiet = infile("solver_quiet", true); solver_aux->verbose = !solver_aux->quiet; solver_aux->max_nonlinear_iterations = infile("max_nonlinear_iterations", 15); solver_aux->relative_step_tolerance = infile("relative_step_tolerance", 1.e-3); solver_aux->relative_residual_tolerance = infile("relative_residual_tolerance", 0.0); solver_aux->absolute_residual_tolerance = infile("absolute_residual_tolerance", 0.0); // And the linear solver options solver_primary->max_linear_iterations = infile("max_linear_iterations", 50000); solver_primary->initial_linear_tolerance = infile("initial_linear_tolerance", 1.e-3); solver_aux->max_linear_iterations = infile("max_linear_iterations", 50000); solver_aux->initial_linear_tolerance = infile("initial_linear_tolerance", 1.e-3); // Print information about the system to the screen. equation_systems.print_info(); // Now we begin the timestep loop to compute the time-accurate // solution of the equations...not that this is transient, but eh, why not... for (unsigned int t_step=0; t_step != n_timesteps; ++t_step){ // A pretty update message std::cout << "\n\nSolving time step " << t_step << ", time = " << system_primary.time << std::endl; // Adaptively solve the timestep unsigned int a_step = 0; /*for (; a_step != max_adaptivesteps; ++a_step) { system.solve(); system.postprocess(); ErrorVector error; AutoPtr<ErrorEstimator> error_estimator; // To solve to a tolerance in this problem we // need a better estimator than Kelly if (global_tolerance != 0.) { // We can't adapt to both a tolerance and a mesh // size at once libmesh_assert_equal_to (nelem_target, 0); UniformRefinementEstimator *u = new UniformRefinementEstimator; // The lid-driven cavity problem isn't in H1, so // lets estimate L2 error u->error_norm = L2; error_estimator.reset(u); } else { // If we aren't adapting to a tolerance we need a // target mesh size libmesh_assert_greater (nelem_target, 0); // Kelly is a lousy estimator to use for a problem // not in H1 - if we were doing more than a few // timesteps we'd need to turn off or limit the // maximum level of our adaptivity eventually error_estimator.reset(new KellyErrorEstimator); } // Calculate error std::vector<Real> weights(9,1.0); // based on u, v, p, c, their adjoints, and source parameter // Keep the same default norm type. std::vector<FEMNormType> norms(1, error_estimator->error_norm.type(0)); error_estimator->error_norm = SystemNorm(norms, weights); error_estimator->estimate_error(system, error); // Print out status at each adaptive step. Real global_error = error.l2_norm(); std::cout << "Adaptive step " << a_step << ": " << std::endl; if (global_tolerance != 0.) std::cout << "Global_error = " << global_error << std::endl; if (global_tolerance != 0.) std::cout << "Worst element error = " << error.maximum() << ", mean = " << error.mean() << std::endl; if (global_tolerance != 0.) { // If we've reached our desired tolerance, we // don't need any more adaptive steps if (global_error < global_tolerance) break; mesh_refinement.flag_elements_by_error_tolerance(error); } else { // If flag_elements_by_nelem_target returns true, this // should be our last adaptive step. if (mesh_refinement.flag_elements_by_nelem_target(error)) { mesh_refinement.refine_and_coarsen_elements(); equation_systems.reinit(); a_step = max_adaptivesteps; break; } } // Carry out the adaptive mesh refinement/coarsening mesh_refinement.refine_and_coarsen_elements(); equation_systems.reinit(); std::cout << "Refined mesh to " << mesh.n_active_elem() << " active elements and " << equation_systems.n_active_dofs() << " active dofs." << std::endl; }*/ // Do one last solve if necessary if (a_step == max_adaptivesteps) { system_primary.solve(); std::cout << "\n\n Residual L2 norm (primary): " << system_primary.calculate_norm(*system_primary.rhs, L2) << "\n"; system_aux.solve(); std::cout << "\n\n Residual L2 norm (auxiliary): " << system_aux.calculate_norm(*system_aux.rhs, L2) << "\n"; equation_systems_mix.init(); DirectSolutionTransfer sol_transfer(init.comm()); sol_transfer.transfer(system_primary.variable(system_primary.variable_number("c")), system_mix.variable(system_mix.variable_number("c"))); sol_transfer.transfer(system_primary.variable(system_primary.variable_number("zc")), system_mix.variable(system_mix.variable_number("zc"))); sol_transfer.transfer(system_primary.variable(system_primary.variable_number("fc")), system_mix.variable(system_mix.variable_number("fc"))); sol_transfer.transfer(system_aux.variable(system_aux.variable_number("aux_c")), system_mix.variable(system_mix.variable_number("aux_c"))); sol_transfer.transfer(system_aux.variable(system_aux.variable_number("aux_zc")), system_mix.variable(system_mix.variable_number("aux_zc"))); sol_transfer.transfer(system_aux.variable(system_aux.variable_number("aux_fc")), system_mix.variable(system_mix.variable_number("aux_fc"))); std::cout << "c: " << system_mix.calculate_norm(*system_mix.solution, 0, L2) << " " << system_primary.calculate_norm(*system_primary.solution, 0, L2) << std::endl; std::cout << "zc: " << system_mix.calculate_norm(*system_mix.solution, 1, L2) << " " << system_primary.calculate_norm(*system_primary.solution, 1, L2) << std::endl; std::cout << "fc: " << system_mix.calculate_norm(*system_mix.solution, 2, L2) << " " << system_primary.calculate_norm(*system_primary.solution, 2, L2) << std::endl; std::cout << "aux_c: " << system_mix.calculate_norm(*system_mix.solution, 3, L2) << " " << system_aux.calculate_norm(*system_aux.solution, 0, L2) << std::endl; std::cout << "aux_zc: " << system_mix.calculate_norm(*system_mix.solution, 4, L2) << " " << system_aux.calculate_norm(*system_aux.solution, 1, L2) << std::endl; std::cout << "aux_fc: " << system_mix.calculate_norm(*system_mix.solution, 5, L2) << " " << system_aux.calculate_norm(*system_aux.solution, 2, L2) << std::endl; std::cout << "Overall: " << system_mix.calculate_norm(*system_mix.solution, L2) << std::endl; system_mix.postprocess(); //DEBUG std::cout << " M_HF(psiLF): " << std::setprecision(17) << system_mix.get_MHF_psiLF() << "\n"; std::cout << " I(psiLF): " << std::setprecision(17) << system_mix.get_MLF_psiLF() << "\n"; } // Advance to the next timestep in a transient problem system_primary.time_solver->advance_timestep(); #ifdef LIBMESH_HAVE_EXODUS_API // Write out this timestep if we're requested to if ((t_step+1)%write_interval == 0) { //std::ostringstream file_name; // We write the file in the ExodusII format. //file_name << "out_" // << std::setw(3) // << std::setfill('0') // << std::right // << t_step+1 // << ".e"; //ExodusII_IO(mesh).write_timestep(file_name.str(), ExodusII_IO(mesh).write_timestep("psiLF.exo", equation_systems_mix, 1, /* This number indicates how many time steps are being written to the file */ system_primary.time); mesh.write("psiLF_mesh.xda"); equation_systems_mix.write("psiLF.xda", WRITE, EquationSystems::WRITE_DATA | EquationSystems::WRITE_ADDITIONAL_DATA); } #endif // #ifdef LIBMESH_HAVE_EXODUS_API } // All done. return 0; } //end main
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; }
int main(int argc, char** argv){ //initialize libMesh LibMeshInit init(argc, argv); //parameters GetPot infile("fem_system_params.in"); const bool transient = infile("transient", true); const Real deltat = infile("deltat", 0.005); unsigned int n_timesteps = infile("n_timesteps", 20); const int nx = infile("nx",100); const int ny = infile("ny",100); const int nz = infile("nz",100); //const unsigned int dim = 3; const unsigned int max_r_steps = infile("max_r_steps", 3); const unsigned int max_r_level = infile("max_r_level", 3); const Real refine_percentage = infile("refine_percentage", 0.1); const Real coarsen_percentage = infile("coarsen_percentage", 0.0); const std::string indicator_type = infile("indicator_type", "kelly"); const bool write_error = infile("write_error",false); const bool flag_by_elem_frac = infile("flag_by_elem_frac",true); #ifdef LIBMESH_HAVE_EXODUS_API const unsigned int write_interval = infile("write_interval", 5); #endif // Create a mesh, with dimension to be overridden later, distributed // across the default MPI communicator. Mesh mesh(init.comm()); //create mesh unsigned int dim; if(nz == 0){ //to check if oscillations happen in 2D as well... dim = 2; MeshTools::Generation::build_square(mesh, nx, ny, 497150.0, 501750.0, 537350.0, 540650.0, QUAD9); }else{ dim = 3; MeshTools::Generation::build_cube(mesh, nx, ny, nz, 497150.0, 501750.0, 537350.0, 540650.0, 0.0, 100.0, HEX27); } // Print information about the mesh to the screen. mesh.print_info(); // Create an equation systems object. EquationSystems equation_systems (mesh); //name system ContamTransSysInv & system = equation_systems.add_system<ContamTransSysInv>("ContamTransInv"); //solve as steady or transient if(transient){ //system.time_solver = AutoPtr<TimeSolver>(new EulerSolver(system)); //backward Euler system.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system)); std::cout << "\n\nAaahhh transience not yet available!\n" << std::endl; n_timesteps = 1; } else{ system.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system)); libmesh_assert_equal_to (n_timesteps, 1); //this doesn't seem to work? } // Initialize the system equation_systems.init (); //initial conditions read_initial_parameters(); system.project_solution(initial_value, initial_grad, equation_systems.parameters); finish_initialization(); // Set the time stepping options... system.deltat = deltat; //...and the nonlinear solver options... NewtonSolver *solver = new NewtonSolver(system); system.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver); solver->quiet = infile("solver_quiet", true); solver->verbose = !solver->quiet; solver->max_nonlinear_iterations = infile("max_nonlinear_iterations", 15); solver->relative_step_tolerance = infile("relative_step_tolerance", 1.e-3); solver->relative_residual_tolerance = infile("relative_residual_tolerance", 0.0); solver->absolute_residual_tolerance = infile("absolute_residual_tolerance", 0.0); // And the linear solver options solver->max_linear_iterations = infile("max_linear_iterations", 10000); solver->initial_linear_tolerance = infile("initial_linear_tolerance",1.e-13); solver->minimum_linear_tolerance = infile("minimum_linear_tolerance",1.e-13); solver->linear_tolerance_multiplier = infile("linear_tolerance_multiplier",1.e-3); // Mesh Refinement object - to test effect of constant refined mesh (not refined at every timestep) MeshRefinement mesh_refinement(mesh); mesh_refinement.refine_fraction() = refine_percentage; mesh_refinement.coarsen_fraction() = coarsen_percentage; mesh_refinement.max_h_level() = max_r_level; // Print information about the system to the screen. equation_systems.print_info(); ExodusII_IO exodusIO = ExodusII_IO(mesh); //for writing multiple timesteps to one file for (unsigned int r_step=0; r_step<max_r_steps; r_step++) { std::cout << "\nBeginning Solve " << r_step+1 << std::endl; for (unsigned int t_step=0; t_step != n_timesteps; ++t_step) { std::cout << "\n\nSolving time step " << t_step << ", time = " << system.time << std::endl; system.solve(); system.postprocess(); // Advance to the next timestep in a transient problem system.time_solver->advance_timestep(); } //end stepping through time loop std::cout << "\n Refining the mesh..." << std::endl; // The \p ErrorVector is a particular \p StatisticsVector // for computing error information on a finite element mesh. ErrorVector error; if (indicator_type == "patch") { // The patch recovery estimator should give a // good estimate of the solution interpolation // error. PatchRecoveryErrorEstimator error_estimator; error_estimator.set_patch_reuse(false); //anisotropy trips up reuse error_estimator.estimate_error (system, error); } else if (indicator_type == "kelly") { // The Kelly error estimator is based on // an error bound for the Poisson problem // on linear elements, but is useful for // driving adaptive refinement in many problems KellyErrorEstimator error_estimator; error_estimator.estimate_error (system, error); } // Write out the error distribution if(write_error){ std::ostringstream ss; ss << r_step; #ifdef LIBMESH_HAVE_EXODUS_API std::string error_output = "error_"+ss.str()+".e"; #else std::string error_output = "error_"+ss.str()+".gmv"; #endif error.plot_error( error_output, mesh ); } // This takes the error in \p error and decides which elements // will be coarsened or refined. if(flag_by_elem_frac) mesh_refinement.flag_elements_by_elem_fraction(error); else mesh_refinement.flag_elements_by_error_fraction (error); // This call actually refines and coarsens the flagged // elements. mesh_refinement.refine_and_coarsen_elements(); // This call reinitializes the \p EquationSystems object for // the newly refined mesh. One of the steps in the // reinitialization is projecting the \p solution, // \p old_solution, etc... vectors from the old mesh to // the current one. equation_systems.reinit (); std::cout << "System has: " << equation_systems.n_active_dofs() << " degrees of freedom." << std::endl; } //end refinement loop //use that final refinement for (unsigned int t_step=0; t_step != n_timesteps; ++t_step) { std::cout << "\n\nSolving time step " << t_step << ", time = " << system.time << std::endl; system.solve(); system.postprocess(); Number QoI_computed = system.get_QoI_value("computed", 0); std::cout<< "Computed QoI is " << std::setprecision(17) << QoI_computed << std::endl; // Advance to the next timestep in a transient problem system.time_solver->advance_timestep(); } //end stepping through time loop #ifdef LIBMESH_HAVE_EXODUS_API for (unsigned int t_step=0; t_step != n_timesteps; ++t_step) { // Write out this timestep if we're requested to if ((t_step+1)%write_interval == 0) { std::ostringstream ex_file_name; std::ostringstream tplot_file_name; // We write the file in the ExodusII format. //ex_file_name << "out_" // << std::setw(3) // << std::setfill('0') // << std::right // << t_step+1 // << ".e"; tplot_file_name << "out_" << std::setw(3) << std::setfill('0') << std::right << t_step+1 << ".plt"; //ExodusII_IO(mesh).write_timestep(ex_file_name.str(), // equation_systems, // 1, /* This number indicates how many time steps // are being written to the file */ // system.time); exodusIO.write_timestep("output.exo", equation_systems, t_step+1, system.time); //outputs all timesteps in one file TecplotIO(mesh).write_equation_systems(tplot_file_name.str(), equation_systems); } } #endif // #ifdef LIBMESH_HAVE_EXODUS_API // All done. return 0; } //end main
// The main program int main(int argc, char** argv) { //for record-keeping std::cout << "Running: " << argv[0]; for (int i=1; i<argc; i++) std::cout << " " << argv[i]; std::cout << std::endl << std::endl; clock_t begin = std::clock(); // Initialize libMesh LibMeshInit init(argc, argv); // Parameters GetPot solverInfile("fem_system_params.in"); const bool transient = solverInfile("transient", false); unsigned int n_timesteps = solverInfile("n_timesteps", 1); const int nx = solverInfile("nx",100); const int ny = solverInfile("ny",100); const int nz = solverInfile("nz",100); GetPot infile("contamTrans.in"); //std::string find_mesh_here = infile("initial_mesh","mesh.exo"); bool doContinuation = infile("do_continuation",false); bool splitSuperAdj = infile("split_super_adjoint",true); //solve as single adjoint or two forwards int maxIter = infile("max_model_refinements",0); //maximum number of model refinements double refStep = infile("refinement_step",0.1); //additional proportion of domain refined per step //this refers to additional basis functions...number of elements will be more... double qoiErrorTol = infile("relative_error_tolerance",0.01); //stopping criterion //bool doDivvyMatlab = infile("do_divvy_in_Matlab",false); //output files to determine next refinement in Matlab bool avoid_sides = infile("avoid_sides",false); //DEBUG, whether to avoid sides while refining if(refStep*maxIter > 1) maxIter = round(ceil(1./refStep)); Mesh mesh(init.comm()); Mesh mesh2(init.comm()); //create mesh unsigned int dim; if(nz == 0){ //to check if oscillations happen in 2D as well... dim = 2; MeshTools::Generation::build_square(mesh, nx, ny, 0., 2300., 0., 1650., QUAD9); MeshTools::Generation::build_square(mesh2, nx, ny, 0., 2300., 0., 1650., QUAD9); }else{ dim = 3; MeshTools::Generation::build_cube(mesh, nx, ny, nz, 0., 2300., 0., 1650., 0., 100., HEX27); MeshTools::Generation::build_cube(mesh2, nx, ny, nz, 0., 2300., 0., 1650., 0., 100., HEX27); } mesh.print_info(); //DEBUG // Create an equation systems object. EquationSystems equation_systems (mesh); EquationSystems equation_systems_mix(mesh2); //name system ConvDiff_PrimarySys & system_primary = equation_systems.add_system<ConvDiff_PrimarySys>("ConvDiff_PrimarySys"); //for primary variables ConvDiff_AuxSys & system_aux = equation_systems.add_system<ConvDiff_AuxSys>("ConvDiff_AuxSys"); //for auxiliary variables ConvDiff_MprimeSys & system_mix = equation_systems_mix.add_system<ConvDiff_MprimeSys>("Diff_ConvDiff_MprimeSys"); //for superadj ConvDiff_PrimarySadjSys & system_sadj_primary = equation_systems.add_system<ConvDiff_PrimarySadjSys>("ConvDiff_PrimarySadjSys"); //for split superadj ConvDiff_AuxSadjSys & system_sadj_aux = equation_systems.add_system<ConvDiff_AuxSadjSys>("ConvDiff_AuxSadjSys"); //for split superadj //steady-state problem system_primary.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system_primary)); system_aux.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system_aux)); system_mix.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system_mix)); system_sadj_primary.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system_sadj_primary)); system_sadj_aux.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system_sadj_aux)); libmesh_assert_equal_to (n_timesteps, 1); // Initialize the system equation_systems.init (); equation_systems_mix.init(); //initial guess for primary state read_initial_parameters(); system_primary.project_solution(initial_value, initial_grad, equation_systems.parameters); finish_initialization(); //nonlinear solver options NewtonSolver *solver_sadj_primary = new NewtonSolver(system_sadj_primary); system_sadj_primary.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver_sadj_primary); solver_sadj_primary->quiet = solverInfile("solver_quiet", true); solver_sadj_primary->verbose = !solver_sadj_primary->quiet; solver_sadj_primary->max_nonlinear_iterations = solverInfile("max_nonlinear_iterations", 15); solver_sadj_primary->relative_step_tolerance = solverInfile("relative_step_tolerance", 1.e-3); solver_sadj_primary->relative_residual_tolerance = solverInfile("relative_residual_tolerance", 0.0); solver_sadj_primary->absolute_residual_tolerance = solverInfile("absolute_residual_tolerance", 0.0); NewtonSolver *solver_sadj_aux = new NewtonSolver(system_sadj_aux); system_sadj_aux.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver_sadj_aux); solver_sadj_aux->quiet = solverInfile("solver_quiet", true); solver_sadj_aux->verbose = !solver_sadj_aux->quiet; solver_sadj_aux->max_nonlinear_iterations = solverInfile("max_nonlinear_iterations", 15); solver_sadj_aux->relative_step_tolerance = solverInfile("relative_step_tolerance", 1.e-3); solver_sadj_aux->relative_residual_tolerance = solverInfile("relative_residual_tolerance", 0.0); solver_sadj_aux->absolute_residual_tolerance = solverInfile("absolute_residual_tolerance", 0.0); NewtonSolver *solver_primary = new NewtonSolver(system_primary); system_primary.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver_primary); solver_primary->quiet = solverInfile("solver_quiet", true); solver_primary->verbose = !solver_primary->quiet; solver_primary->max_nonlinear_iterations = solverInfile("max_nonlinear_iterations", 15); solver_primary->relative_step_tolerance = solverInfile("relative_step_tolerance", 1.e-3); solver_primary->relative_residual_tolerance = solverInfile("relative_residual_tolerance", 0.0); solver_primary->absolute_residual_tolerance = solverInfile("absolute_residual_tolerance", 0.0); NewtonSolver *solver_aux = new NewtonSolver(system_aux); system_aux.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver_aux); solver_aux->quiet = solverInfile("solver_quiet", true); solver_aux->verbose = !solver_aux->quiet; solver_aux->max_nonlinear_iterations = solverInfile("max_nonlinear_iterations", 15); solver_aux->relative_step_tolerance = solverInfile("relative_step_tolerance", 1.e-3); solver_aux->relative_residual_tolerance = solverInfile("relative_residual_tolerance", 0.0); solver_aux->absolute_residual_tolerance = solverInfile("absolute_residual_tolerance", 0.0); solver_primary->require_residual_reduction = solverInfile("require_residual_reduction",true); solver_sadj_primary->require_residual_reduction = solverInfile("require_residual_reduction",true); solver_aux->require_residual_reduction = solverInfile("require_residual_reduction",true); solver_sadj_aux->require_residual_reduction = solverInfile("require_residual_reduction",true); //linear solver options solver_primary->max_linear_iterations = solverInfile("max_linear_iterations",10000); solver_primary->initial_linear_tolerance = solverInfile("initial_linear_tolerance",1.e-13); solver_primary->minimum_linear_tolerance = solverInfile("minimum_linear_tolerance",1.e-13); solver_primary->linear_tolerance_multiplier = solverInfile("linear_tolerance_multiplier",1.e-3); solver_aux->max_linear_iterations = solverInfile("max_linear_iterations",10000); solver_aux->initial_linear_tolerance = solverInfile("initial_linear_tolerance",1.e-13); solver_aux->minimum_linear_tolerance = solverInfile("minimum_linear_tolerance",1.e-13); solver_aux->linear_tolerance_multiplier = solverInfile("linear_tolerance_multiplier",1.e-3); solver_sadj_primary->max_linear_iterations = solverInfile("max_linear_iterations",10000); solver_sadj_primary->initial_linear_tolerance = solverInfile("initial_linear_tolerance",1.e-13); solver_sadj_primary->minimum_linear_tolerance = solverInfile("minimum_linear_tolerance",1.e-13); solver_sadj_primary->linear_tolerance_multiplier = solverInfile("linear_tolerance_multiplier",1.e-3); solver_sadj_aux->max_linear_iterations = solverInfile("max_linear_iterations",10000); solver_sadj_aux->initial_linear_tolerance = solverInfile("initial_linear_tolerance",1.e-13); solver_sadj_aux->minimum_linear_tolerance = solverInfile("minimum_linear_tolerance",1.e-13); solver_sadj_aux->linear_tolerance_multiplier = solverInfile("linear_tolerance_multiplier",1.e-3); /*if(doDivvyMatlab){ //DOF maps and such to help visualize std::ofstream output_global_dof("global_dof_map.dat"); for(unsigned int i = 0 ; i < system_mix.get_mesh().n_elem(); i++){ std::vector< dof_id_type > di; system_mix.get_dof_map().dof_indices(system_mix.get_mesh().elem(i), di); if(output_global_dof.is_open()){ output_global_dof << i << " "; for(unsigned int j = 0; j < di.size(); j++) output_global_dof << di[j] << " "; output_global_dof << "\n"; } } output_global_dof.close(); std::ofstream output_elem_cent("elem_centroids.dat"); for(unsigned int i = 0 ; i < system_mix.get_mesh().n_elem(); i++){ Point elem_cent = system_mix.get_mesh().elem(i)->centroid(); if(output_elem_cent.is_open()){ output_elem_cent << elem_cent(0) << " " << elem_cent(1) << "\n"; } } output_elem_cent.close(); }*/ //inverse dof map (elements in support of each node, assuming every 6 dofs belong to same node) std::vector<std::set<dof_id_type> > node_to_elem; node_to_elem.resize(round(system_mix.n_dofs()/6.)); for(unsigned int i = 0 ; i < system_mix.get_mesh().n_elem(); i++){ std::vector< dof_id_type > di; system_mix.get_dof_map().dof_indices(system_mix.get_mesh().elem(i), di); for(unsigned int j = 0; j < di.size(); j++) node_to_elem[round(floor(di[j]/6.))].insert(i); } int refIter = 0; double relError = 2.*qoiErrorTol; while(refIter <= maxIter && relError > qoiErrorTol){ if(!doContinuation){ //clear out previous solutions system_primary.solution->zero(); system_aux.solution->zero(); system_sadj_primary.solution->zero(); system_sadj_aux.solution->zero(); } system_mix.solution->zero(); clock_t begin_inv = std::clock(); system_primary.solve(); system_primary.clearQoI(); clock_t end_inv = std::clock(); clock_t begin_err_est = std::clock(); std::cout << "\n End primary solve, begin auxiliary solve..." << std::endl; system_aux.solve(); std::cout << "\n End auxiliary solve..." << std::endl; clock_t end_aux = std::clock(); system_primary.postprocess(); system_aux.postprocess(); system_sadj_primary.set_c_vals(system_primary.get_c_vals()); system_sadj_aux.set_auxc_vals(system_aux.get_auxc_vals()); equation_systems_mix.reinit(); //combine primary and auxiliary variables into psi DirectSolutionTransfer sol_transfer(init.comm()); sol_transfer.transfer(system_aux.variable(system_aux.variable_number("aux_c")), system_mix.variable(system_mix.variable_number("aux_c"))); sol_transfer.transfer(system_aux.variable(system_aux.variable_number("aux_zc")), system_mix.variable(system_mix.variable_number("aux_zc"))); sol_transfer.transfer(system_aux.variable(system_aux.variable_number("aux_fc")), system_mix.variable(system_mix.variable_number("aux_fc"))); AutoPtr<NumericVector<Number> > just_aux = system_mix.solution->clone(); sol_transfer.transfer(system_primary.variable(system_primary.variable_number("c")), system_mix.variable(system_mix.variable_number("c"))); sol_transfer.transfer(system_primary.variable(system_primary.variable_number("zc")), system_mix.variable(system_mix.variable_number("zc"))); sol_transfer.transfer(system_primary.variable(system_primary.variable_number("fc")), system_mix.variable(system_mix.variable_number("fc"))); if(!splitSuperAdj){ //solve super-adjoint as single adjoint system_mix.assemble_qoi_sides = true; //QoI doesn't involve sides std::cout << "\n~*~*~*~*~*~*~*~*~ adjoint solve start ~*~*~*~*~*~*~*~*~\n" << std::endl; std::pair<unsigned int, Real> adjsolve = system_mix.adjoint_solve(); std::cout << "number of iterations to solve adjoint: " << adjsolve.first << std::endl; std::cout << "final residual of adjoint solve: " << adjsolve.second << std::endl; std::cout << "\n~*~*~*~*~*~*~*~*~ adjoint solve end ~*~*~*~*~*~*~*~*~" << std::endl; NumericVector<Number> &dual_sol = system_mix.get_adjoint_solution(0); //DEBUG system_mix.assemble(); //calculate residual to correspond to solution //std::cout << "\n sadj norm: " << system_mix.calculate_norm(dual_sol, L2) << std::endl; //DEBUG //std::cout << system_mix.calculate_norm(dual_sol, 0, L2) << std::endl; //DEBUG //std::cout << system_mix.calculate_norm(dual_sol, 1, L2) << std::endl; //DEBUG //std::cout << system_mix.calculate_norm(dual_sol, 2, L2) << std::endl; //DEBUG //std::cout << system_mix.calculate_norm(dual_sol, 3, L2) << std::endl; //DEBUG //std::cout << system_mix.calculate_norm(dual_sol, 4, L2) << std::endl; //DEBUG //std::cout << system_mix.calculate_norm(dual_sol, 5, L2) << std::endl; //DEBUG }else{ //solve super-adjoint as system_mix.assemble(); //calculate residual to correspond to solution std::cout << "\n Begin primary super-adjoint solve...\n" << std::endl; system_sadj_primary.solve(); std::cout << "\n End primary super-adjoint solve, begin auxiliary super-adjoint solve...\n" << std::endl; system_sadj_aux.solve(); std::cout << "\n End auxiliary super-adjoint solve...\n" << std::endl; const std::string & adjoint_solution0_name = "adjoint_solution0"; system_mix.add_vector(adjoint_solution0_name, false, GHOSTED); system_mix.set_vector_as_adjoint(adjoint_solution0_name,0); NumericVector<Number> &eep = system_mix.add_adjoint_rhs(0); system_mix.set_adjoint_already_solved(true); NumericVector<Number> &dual_sol = system_mix.get_adjoint_solution(0); NumericVector<Number> &primal_sol = *system_mix.solution; dual_sol.swap(primal_sol); sol_transfer.transfer(system_sadj_aux.variable(system_sadj_aux.variable_number("sadj_aux_c")), system_mix.variable(system_mix.variable_number("aux_c"))); sol_transfer.transfer(system_sadj_aux.variable(system_sadj_aux.variable_number("sadj_aux_zc")), system_mix.variable(system_mix.variable_number("aux_zc"))); sol_transfer.transfer(system_sadj_aux.variable(system_sadj_aux.variable_number("sadj_aux_fc")), system_mix.variable(system_mix.variable_number("aux_fc"))); sol_transfer.transfer(system_sadj_primary.variable(system_sadj_primary.variable_number("sadj_c")), system_mix.variable(system_mix.variable_number("c"))); sol_transfer.transfer(system_sadj_primary.variable(system_sadj_primary.variable_number("sadj_zc")), system_mix.variable(system_mix.variable_number("zc"))); sol_transfer.transfer(system_sadj_primary.variable(system_sadj_primary.variable_number("sadj_fc")), system_mix.variable(system_mix.variable_number("fc"))); //std::cout << "\n sadj norm: " << system_mix.calculate_norm(primal_sol, L2) << std::endl; //DEBUG dual_sol.swap(primal_sol); //std::cout << "\n sadj norm: " << system_mix.calculate_norm(primal_sol, L2) << std::endl; //DEBUG //std::cout << system_sadj_primary.calculate_norm(*system_sadj_primary.solution, 0, L2) << std::endl; //DEBUG //std::cout << system_sadj_primary.calculate_norm(*system_sadj_primary.solution, 1, L2) << std::endl; //DEBUG //std::cout << system_sadj_primary.calculate_norm(*system_sadj_primary.solution, 2, L2) << std::endl; //DEBUG //std::cout << system_sadj_aux.calculate_norm(*system_sadj_aux.solution, 0, L2) << std::endl; //DEBUG //std::cout << system_sadj_aux.calculate_norm(*system_sadj_aux.solution, 1, L2) << std::endl; //DEBUG //std::cout << system_sadj_aux.calculate_norm(*system_sadj_aux.solution, 2, L2) << std::endl; //DEBUG } NumericVector<Number> &dual_solution = system_mix.get_adjoint_solution(0); /* NumericVector<Number> &primal_solution = *system_mix.solution; //DEBUG primal_solution.swap(dual_solution); //DEBUG ExodusII_IO(mesh).write_timestep("super_adjoint.exo", equation_systems, 1, / his number indicates how many time steps are being written to the file system_mix.time); //DEBUG primal_solution.swap(dual_solution); //DEBUG */ //adjoint-weighted residual AutoPtr<NumericVector<Number> > adjresid = system_mix.solution->zero_clone(); adjresid->pointwise_mult(*system_mix.rhs,dual_solution); adjresid->scale(-0.5); std::cout << "\n -0.5*M'_HF(psiLF)(superadj): " << adjresid->sum() << std::endl; //DEBUG //LprimeHF(psiLF) AutoPtr<NumericVector<Number> > LprimeHF_psiLF = system_mix.solution->zero_clone(); LprimeHF_psiLF->pointwise_mult(*system_mix.rhs,*just_aux); std::cout << " L'_HF(psiLF): " << LprimeHF_psiLF->sum() << std::endl; //DEBUG //QoI and error estimate std::cout << "QoI: " << std::setprecision(17) << system_primary.getQoI() << std::endl; std::cout << "QoI Error estimate: " << std::setprecision(17) << adjresid->sum()+LprimeHF_psiLF->sum() << std::endl; relError = fabs((adjresid->sum()+LprimeHF_psiLF->sum())/system_primary.getQoI()); //print out information std::cout << "Estimated absolute relative qoi error: " << relError << std::endl << std::endl; std::cout << "Estimated HF QoI: " << std::setprecision(17) << system_primary.getQoI()+adjresid->sum()+LprimeHF_psiLF->sum() << std::endl; clock_t end = clock(); std::cout << "Time so far: " << double(end-begin)/CLOCKS_PER_SEC << " seconds..." << std::endl; std::cout << "Time for inverse problem: " << double(end_inv-begin_inv)/CLOCKS_PER_SEC << " seconds..." << std::endl; std::cout << "Time for extra error estimate bits: " << double(end-begin_err_est)/CLOCKS_PER_SEC << " seconds..." << std::endl; std::cout << " Time to get auxiliary problems: " << double(end_aux-begin_err_est)/CLOCKS_PER_SEC << " seconds..." << std::endl; std::cout << " Time to get superadjoint: " << double(end-end_aux)/CLOCKS_PER_SEC << " seconds...\n" << std::endl; //proportion of domain refined at this iteration MeshBase::element_iterator elem_it = mesh.elements_begin(); const MeshBase::element_iterator elem_end = mesh.elements_end(); double numMarked = 0.; for (; elem_it != elem_end; ++elem_it){ Elem* elem = *elem_it; numMarked += elem->subdomain_id(); } std::cout << "Refinement fraction: " << numMarked/system_mix.get_mesh().n_elem() << std::endl << std::endl; //output at each iteration std::stringstream ss; ss << refIter; std::string str = ss.str(); std::string write_error_basis_blame = (infile("error_est_output_file_basis_blame", "error_est_breakdown_basis_blame")) + str + ".dat"; std::ofstream output2(write_error_basis_blame); for(unsigned int i = 0 ; i < adjresid->size(); i++){ if(output2.is_open()) output2 << (*adjresid)(i) + (*LprimeHF_psiLF)(i) << "\n"; } output2.close(); if(refIter < maxIter && relError > qoiErrorTol){ //if further refinement needed //collapse error contributions into nodes std::vector<std::pair<Number,dof_id_type> > node_errs(round(system_mix.n_dofs()/6.)); for(unsigned int node_num = 0; node_num < node_errs.size(); node_num++){ node_errs[node_num] = std::pair<Number,dof_id_type> (fabs((*adjresid)(6*node_num) + (*LprimeHF_psiLF)(6*node_num) + (*adjresid)(6*node_num+1) + (*LprimeHF_psiLF)(6*node_num+1) + (*adjresid)(6*node_num+2) + (*LprimeHF_psiLF)(6*node_num+2) + (*adjresid)(6*node_num+3) + (*LprimeHF_psiLF)(6*node_num+3) + (*adjresid)(6*node_num+4) + (*LprimeHF_psiLF)(6*node_num+4) + (*adjresid)(6*node_num+5) + (*LprimeHF_psiLF)(6*node_num+5)), node_num); } //find nodes contributing the most //double refPcnt = std::min((refIter+1)*refStep,1.); double refPcnt = std::min(refStep,1.); //additional refinement (compared to previous iteration) int cutoffLoc = round(node_errs.size()*refPcnt); std::sort(node_errs.begin(), node_errs.end()); std::reverse(node_errs.begin(), node_errs.end()); //find elements in support of worst offenders std::vector<dof_id_type> markMe; markMe.reserve(cutoffLoc*8); for(int i = 0; i < cutoffLoc; i++){ markMe.insert(markMe.end(), node_to_elem[node_errs[i].second].begin(), node_to_elem[node_errs[i].second].end()); } //mark those elements for refinement. for(int i = 0; i < markMe.size(); i++){ if(!avoid_sides || (avoid_sides && !mesh.elem(markMe[i])->on_boundary())) mesh.elem(markMe[i])->subdomain_id() = 1; //assuming HF regions marked with 1 } //to test whether assignment matches matlab's /*std::string stash_assign = "divvy_c_poke.txt"; std::ofstream output_dbg(stash_assign.c_str()); MeshBase::element_iterator elem_it = mesh.elements_begin(); const MeshBase::element_iterator elem_end = mesh.elements_end(); for (; elem_it != elem_end; ++elem_it){ Elem* elem = *elem_it; if(output_dbg.is_open()){ output_dbg << elem->id() << " " << elem->subdomain_id() << "\n"; } } output_dbg.close();*/ #ifdef LIBMESH_HAVE_EXODUS_API std::stringstream ss2; ss2 << refIter + 1; std::string str = ss2.str(); std::string write_divvy = "divvy" + str + ".exo"; ExodusII_IO (mesh).write_equation_systems(write_divvy,equation_systems); //DEBUG #endif // #ifdef LIBMESH_HAVE_EXODUS_API } refIter += 1; } std::string stash_assign = "divvy_final.txt"; std::ofstream output_dbg(stash_assign.c_str()); MeshBase::element_iterator elem_it = mesh.elements_begin(); const MeshBase::element_iterator elem_end = mesh.elements_end(); double numMarked = 0.; for (; elem_it != elem_end; ++elem_it){ Elem* elem = *elem_it; numMarked += elem->subdomain_id(); if(output_dbg.is_open()){ output_dbg << elem->id() << " " << elem->subdomain_id() << "\n"; } } output_dbg.close(); std::cout << "\nRefinement concluded..." << std::endl; std::cout << "Final refinement fraction: " << numMarked/system_mix.get_mesh().n_elem() << std::endl; std::cout << "Final estimated relative error: " << relError << std::endl; return 0; //done } //end main