1 #include "mesh_error_estimate.h" 3 #include <Epetra_RowMatrixTransposer.h> 4 #include <deal.II/distributed/shared_tria.h> 5 #include <deal.II/distributed/solution_transfer.h> 6 #include <deal.II/distributed/tria.h> 7 #include <deal.II/dofs/dof_tools.h> 8 #include <deal.II/fe/fe_q.h> 9 #include <deal.II/fe/fe_values.h> 10 #include <deal.II/grid/tria.h> 11 #include <deal.II/lac/la_parallel_vector.h> 12 #include <deal.II/numerics/data_out.h> 13 #include <deal.II/numerics/vector_tools.h> 19 #include "dg/dg_base.hpp" 20 #include "functional/functional.h" 21 #include "linear_solver/linear_solver.h" 22 #include "parameters/all_parameters.h" 23 #include "physics/physics.h" 24 #include "post_processor/physics_post_processor.h" 28 template <
int dim,
typename real,
typename MeshType>
33 template <
int dim,
typename real,
typename MeshType>
38 template <
int dim,
typename real,
typename MeshType>
41 std::vector<dealii::types::global_dof_index> dofs_indices;
42 dealii::Vector<real> cellwise_errors (this->
dg->high_order_grid->triangulation->n_active_cells());
43 this->
dg->assemble_residual();
45 for (
const auto &cell : this->
dg->dof_handler.active_cell_iterators())
47 if(!cell->is_locally_owned())
continue;
49 const int i_fele = cell->active_fe_index();
50 const dealii::FESystem<dim,dim> &fe_ref = this->
dg->fe_collection[i_fele];
51 const unsigned int n_dofs_cell = fe_ref.n_dofs_per_cell();
52 dofs_indices.resize(n_dofs_cell);
53 cell->get_dof_indices (dofs_indices);
54 real max_residual = 0;
55 for (
unsigned int idof = 0; idof < n_dofs_cell; ++idof)
57 const unsigned int index = dofs_indices[idof];
58 const real res = std::abs(this->
dg->right_hand_side[index]);
59 if (res > max_residual)
62 cellwise_errors[cell->active_cell_index()] = max_residual;
65 return cellwise_errors;
69 template <
int dim,
int nstate,
typename real,
typename MeshType>
72 , solution_coarse(this->
dg->solution)
74 , mpi_communicator(MPI_COMM_WORLD)
75 , pcout(
std::cout, dealii::Utilities::MPI::this_mpi_process(mpi_communicator)==0)
77 Assert(this->
dg->triangulation->get_mesh_smoothing() ==
typename dealii::Triangulation<dim>::MeshSmoothing(dealii::Triangulation<dim>::none),
78 dealii::ExcMessage(
"Mesh smoothing might h-refine cells while computing the dual weighted residual."));
80 coarse_fe_index.reinit(this->
dg->triangulation->n_active_cells());
86 for (
const auto &cell : this->
dg->dof_handler.active_cell_iterators())
88 if(cell->is_locally_owned())
90 coarse_fe_index[cell->active_cell_index()] = cell->active_fe_index();
95 template <
int dim,
int nstate,
typename real,
typename MeshType>
99 real error_sum = cellwise_errors.l1_norm();
103 template <
int dim,
int nstate,
typename real,
typename MeshType>
106 dealii::Vector<real> cellwise_errors(this->
dg->triangulation->n_active_cells());
109 pcout<<
"Computing fine grid adjoint..."<<std::endl;
111 pcout<<
"Computing dual weighted residual..."<<std::endl;
115 pcout<<
"Done computing the goal oriented error indicator."<<std::endl;
116 return cellwise_errors;
120 template <
int dim,
int nstate,
typename real,
typename MeshType>
125 solution_refinement_state = SolutionRefinementStateEnum::coarse;
128 coarse_fe_index.reinit(this->
dg->triangulation->n_active_cells());
131 for (
const auto &cell : this->
dg->dof_handler.active_cell_iterators())
133 if(cell->is_locally_owned())
135 coarse_fe_index[cell->active_cell_index()] = cell->active_fe_index();
142 adjoint_fine = dealii::LinearAlgebra::distributed::Vector<real>();
143 adjoint_coarse = dealii::LinearAlgebra::distributed::Vector<real>();
148 template <
int dim,
int nstate,
typename real,
typename MeshType>
152 if(solution_refinement_state == required_refinement_state)
157 else if(solution_refinement_state == SolutionRefinementStateEnum::coarse && required_refinement_state == SolutionRefinementStateEnum::fine)
162 else if(solution_refinement_state == SolutionRefinementStateEnum::fine && required_refinement_state == SolutionRefinementStateEnum::coarse)
168 pcout<<
"Invalid state. Aborting.."<<std::endl;
173 template <
int dim,
int nstate,
typename real,
typename MeshType>
176 if (this->
dg->get_max_fe_degree() >= this->
dg->max_degree)
178 pcout<<
"Polynomial degree of DG will exceed the maximum allowable after refinement. Update max_degree in dg"<<std::endl;
182 [[maybe_unused]]
unsigned int no_of_cells_before_changing_p = this->
dg->triangulation->n_active_cells();
184 dealii::IndexSet locally_owned_dofs, locally_relevant_dofs;
185 locally_owned_dofs = this->
dg->dof_handler.locally_owned_dofs();
186 dealii::DoFTools::extract_locally_relevant_dofs(this->
dg->dof_handler, locally_relevant_dofs);
191 using VectorType =
typename dealii::LinearAlgebra::distributed::Vector<double>;
192 using DoFHandlerType =
typename dealii::DoFHandler<dim>;
195 SolutionTransfer solution_transfer(this->
dg->dof_handler);
196 solution_transfer.prepare_for_coarsening_and_refinement(
solution_coarse);
198 this->
dg->high_order_grid->prepare_for_coarsening_and_refinement();
200 for (
const auto &cell : this->
dg->dof_handler.active_cell_iterators())
202 if (cell->is_locally_owned())
204 cell->set_future_fe_index(cell->active_fe_index()+1);
208 this->
dg->triangulation->execute_coarsening_and_refinement();
209 this->
dg->high_order_grid->execute_coarsening_and_refinement();
211 this->
dg->allocate_system();
212 this->
dg->solution.zero_out_ghosts();
214 if constexpr (std::is_same_v<
typename dealii::SolutionTransfer<dim,VectorType,DoFHandlerType>,
215 decltype(solution_transfer)>) {
218 solution_transfer.interpolate(this->
dg->solution);
221 this->
dg->solution.update_ghost_values();
223 [[maybe_unused]]
unsigned int no_of_cells_after_changing_p = this->
dg->triangulation->n_active_cells();
225 AssertDimension(no_of_cells_before_changing_p, no_of_cells_after_changing_p);
227 solution_refinement_state = SolutionRefinementStateEnum::fine;
230 template <
int dim,
int nstate,
typename real,
typename MeshType>
233 [[maybe_unused]]
unsigned int no_of_cells_before_changing_p = this->
dg->triangulation->n_active_cells();
234 this->
dg->high_order_grid->prepare_for_coarsening_and_refinement();
236 for (
const auto &cell : this->
dg->dof_handler.active_cell_iterators())
238 if (cell->is_locally_owned())
240 cell->set_future_fe_index(coarse_fe_index[cell->active_cell_index()]);
244 this->
dg->triangulation->execute_coarsening_and_refinement();
245 this->
dg->high_order_grid->execute_coarsening_and_refinement();
247 this->
dg->allocate_system();
248 this->
dg->solution.zero_out_ghosts();
252 [[maybe_unused]]
unsigned int no_of_cells_after_changing_p = this->
dg->triangulation->n_active_cells();
254 AssertDimension(no_of_cells_before_changing_p, no_of_cells_after_changing_p);
256 solution_refinement_state = SolutionRefinementStateEnum::coarse;
259 template <
int dim,
int nstate,
typename real,
typename MeshType>
269 template <
int dim,
int nstate,
typename real,
typename MeshType>
279 template <
int dim,
int nstate,
typename real,
typename MeshType>
281 ::compute_adjoint(dealii::LinearAlgebra::distributed::Vector<real> &derivative_functional_wrt_solution,
282 dealii::LinearAlgebra::distributed::Vector<real> &adjoint_variable)
284 derivative_functional_wrt_solution.reinit(this->
dg->solution);
285 adjoint_variable.reinit(this->
dg->solution);
287 const bool compute_derivative_functional_wrt_solution =
true, compute_derivative_functional_wrt_grid_dofs =
false;
288 const real functional_value =
functional->evaluate_functional(compute_derivative_functional_wrt_solution, compute_derivative_functional_wrt_grid_dofs);
289 (void) functional_value;
290 derivative_functional_wrt_solution =
functional->dIdw;
291 derivative_functional_wrt_solution.update_ghost_values();
294 this->
dg->assemble_residual(
true);
296 AssertDimension(derivative_functional_wrt_solution.size(), adjoint_variable.size());
297 AssertDimension(this->
dg->system_matrix_transpose.n(), adjoint_variable.size());
299 solve_linear(this->
dg->system_matrix_transpose, derivative_functional_wrt_solution, adjoint_variable, this->dg->all_parameters->linear_solver_param);
300 adjoint_variable *= -1.0;
302 adjoint_variable.compress(dealii::VectorOperation::add);
303 adjoint_variable.update_ghost_values();
305 return adjoint_variable;
308 template <
int dim,
int nstate,
typename real,
typename MeshType>
316 const unsigned int max_dofs_per_cell = this->
dg->dof_handler.get_fe_collection().max_dofs_per_cell();
317 std::vector<dealii::types::global_dof_index> current_dofs_indices(max_dofs_per_cell);
320 for (
const auto &cell : this->
dg->dof_handler.active_cell_iterators())
322 if(!cell->is_locally_owned())
continue;
324 const unsigned int fe_index_curr_cell = cell->active_fe_index();
325 const dealii::FESystem<dim,dim> ¤t_fe_ref = this->
dg->fe_collection[fe_index_curr_cell];
326 const unsigned int n_dofs_curr_cell = current_fe_ref.n_dofs_per_cell();
328 current_dofs_indices.resize(n_dofs_curr_cell);
329 cell->get_dof_indices(current_dofs_indices);
332 for(
unsigned int idof = 0; idof < n_dofs_curr_cell; ++idof)
334 dwr_cell += this->
dg->right_hand_side[current_dofs_indices[idof]]*
adjoint_fine[current_dofs_indices[idof]];
343 template <
int dim,
int nstate,
typename real,
typename MeshType>
346 dealii::DataOut<dim, dealii::DoFHandler<dim>> data_out;
347 data_out.attach_dof_handler(this->
dg->dof_handler);
350 data_out.add_data_vector(this->
dg->solution, *post_processor);
352 dealii::Vector<float> subdomain(this->
dg->triangulation->n_active_cells());
353 for (
unsigned int i = 0; i < subdomain.size(); ++i)
355 subdomain(i) = this->
dg->triangulation->locally_owned_subdomain();
357 data_out.add_data_vector(subdomain,
"subdomain", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_cell_data);
360 std::vector<unsigned int> active_fe_indices;
361 this->
dg->dof_handler.get_active_fe_indices(active_fe_indices);
362 dealii::Vector<double> active_fe_indices_dealiivector(active_fe_indices.begin(), active_fe_indices.end());
363 dealii::Vector<double> cell_poly_degree = active_fe_indices_dealiivector;
365 data_out.add_data_vector(active_fe_indices_dealiivector,
"PolynomialDegree", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_cell_data);
367 std::vector<std::string> residual_names;
368 for(
int s=0;s<nstate;++s)
370 std::string varname =
"residual" + dealii::Utilities::int_to_string(s,1);
371 residual_names.push_back(varname);
374 data_out.add_data_vector(this->
dg->right_hand_side, residual_names, dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_dof_data);
377 std::vector<std::string> derivative_functional_wrt_solution_names;
378 for(
int s=0;s<nstate;++s)
380 std::string varname =
"derivative_functional_wrt_solution" + dealii::Utilities::int_to_string(s,1);
381 derivative_functional_wrt_solution_names.push_back(varname);
384 std::vector<std::string> adjoint_names;
385 for(
int s=0;s<nstate;++s)
387 std::string varname =
"psi" + dealii::Utilities::int_to_string(s,1);
388 adjoint_names.push_back(varname);
392 if(solution_refinement_state == SolutionRefinementStateEnum::fine) {
393 data_out.add_data_vector(
derivative_functional_wrt_solution_fine, derivative_functional_wrt_solution_names, dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_dof_data);
394 data_out.add_data_vector(
adjoint_fine, adjoint_names, dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_dof_data);
396 data_out.add_data_vector(
dual_weighted_residual_fine,
"DWR", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_cell_data);
397 }
else if(solution_refinement_state == SolutionRefinementStateEnum::coarse) {
399 data_out.add_data_vector(
adjoint_coarse, adjoint_names, dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_dof_data);
402 const int iproc = dealii::Utilities::MPI::this_mpi_process(
mpi_communicator);
404 data_out.build_patches();
407 std::string filename =
"adjoint-" ;
408 if(solution_refinement_state == SolutionRefinementStateEnum::fine)
409 filename += dealii::Utilities::int_to_string(cycle, 4) +
".";
410 filename += dealii::Utilities::int_to_string(iproc, 4);
412 std::ofstream output(filename);
413 data_out.write_vtu(output);
417 std::vector<std::string> filenames;
418 for (
unsigned int iproc = 0; iproc < dealii::Utilities::MPI::n_mpi_processes(
mpi_communicator); ++iproc)
420 std::string fn =
"adjoint-";
421 if(solution_refinement_state == SolutionRefinementStateEnum::fine)
423 else if(solution_refinement_state == SolutionRefinementStateEnum::coarse)
425 fn += dealii::Utilities::int_to_string(dim, 1) +
"D-";
426 fn += dealii::Utilities::int_to_string(cycle, 4) +
".";
427 fn += dealii::Utilities::int_to_string(iproc, 4);
429 filenames.push_back(fn);
431 std::string master_fn =
"adjoint-";
432 if(solution_refinement_state == SolutionRefinementStateEnum::fine)
433 master_fn +=
"fine-";
434 else if(solution_refinement_state == SolutionRefinementStateEnum::coarse)
435 master_fn +=
"coarse-";
436 master_fn += dealii::Utilities::int_to_string(dim, 1) +
"D-";
437 master_fn += dealii::Utilities::int_to_string(cycle, 4) +
".pvtu";
438 std::ofstream master_output(master_fn);
439 data_out.write_pvtu_record(master_output, filenames);
Abstract class to estimate error for mesh adaptation.
void reinit()
Reinitializes member variables of DualWeightedResidualError.
std::pair< unsigned int, double > solve_linear(const dealii::TrilinosWrappers::SparseMatrix &system_matrix, dealii::LinearAlgebra::distributed::Vector< double > &right_hand_side, dealii::LinearAlgebra::distributed::Vector< double > &solution, const Parameters::LinearSolverParam ¶m)
dealii::LinearAlgebra::distributed::Vector< real > coarse_grid_adjoint()
Computes the coarse grid adjoint.
Files for the baseline physics.
MeshErrorEstimateBase(std::shared_ptr< DGBase< dim, real, MeshType > > dg_input)
Constructor.
std::shared_ptr< Functional< dim, nstate, real, MeshType > > functional
Functional class pointer.
MPI_Comm mpi_communicator
MPI communicator.
void convert_dgsolution_to_coarse_or_fine(SolutionRefinementStateEnum refinement_state)
Converts DG solution to the specified state.
dealii::Vector< real > compute_cellwise_errors() override
Computes maximum residual error in each cell.
DualWeightedResidualError(std::shared_ptr< DGBase< dim, real, MeshType > > dg_input)
Constructor.
dealii::LinearAlgebra::distributed::Vector< real > derivative_functional_wrt_solution_coarse
functional derivative (on the coarse grid)
dealii::ConditionalOStream pcout
Parallel std::cout that only outputs on mpi_rank==0.
dealii::LinearAlgebra::distributed::Vector< real > adjoint_coarse
coarse grid adjoint ( )
dealii::LinearAlgebra::distributed::Vector< real > fine_grid_adjoint()
Computes the fine grid adjoint.
SolutionRefinementStateEnum
For storing the current refinement state of the solution.
dealii::Vector< real > dual_weighted_residual()
Computes the Dual Weighted Residual (DWR)
dealii::LinearAlgebra::distributed::Vector< real > compute_adjoint(dealii::LinearAlgebra::distributed::Vector< real > &derivative_functional_wrt_solution, dealii::LinearAlgebra::distributed::Vector< real > &adjoint_variable)
Solves the adjoint equation.
dealii::Vector< real > compute_cellwise_errors() override
Computes dual weighted residual error in each cell, by integrating over all quadrature points...
dealii::LinearAlgebra::distributed::Vector< real > solution_coarse
original solution
static std::unique_ptr< dealii::DataPostprocessor< dim > > create_Postprocessor(const Parameters::AllParameters *const parameters_input)
Create the post-processor with the correct template parameters.
Class to compute residual based error.
static std::shared_ptr< Functional< dim, nstate, real, MeshType > > create_Functional(PHiLiP::Parameters::AllParameters const *const param, std::shared_ptr< PHiLiP::DGBase< dim, real, MeshType > > dg)
Create standard functional object from constant parameter file.
void fine_to_coarse()
Return the problem to the original solution and polynomial distribution.
std::shared_ptr< DGBase< dim, real, MeshType > > dg
Pointer to DGBase.
DualWeightedResidualError class.
DGBase is independent of the number of state variables.
real total_dual_weighted_residual_error()
Computes the sum of dual weighted residual error over all the cells in the domain.
ResidualErrorEstimate(std::shared_ptr< DGBase< dim, real, MeshType >> dg_input)
Constructor.
dealii::LinearAlgebra::distributed::Vector< real > derivative_functional_wrt_solution_fine
functional derivative (on the fine grid)
dealii::LinearAlgebra::distributed::Vector< real > adjoint_fine
fine grid adjoint ( )
dealii::Vector< real > dual_weighted_residual_fine
Dual weighted residual (.
void output_results_vtk(const unsigned int cycle)
Outputs the current solution and adjoint values.
void coarse_to_fine()
Projects the problem to a p-enriched space.