226 * #include <deal.II/base/function_parser.h>
227 * #include <deal.II/base/index_set.h>
228 * #include <deal.II/base/parameter_handler.h>
229 * #include <deal.II/base/quadrature_lib.h>
230 * #include <deal.II/base/utilities.h>
232 * #include <deal.II/dofs/dof_handler.h>
233 * #include <deal.II/dofs/dof_tools.h>
235 * #include <deal.II/fe/fe_nedelec.h>
236 * #include <deal.II/fe/fe_series.h>
237 * #include <deal.II/fe/fe_values.h>
239 * #include <deal.II/grid/tria.h>
240 * #include <deal.II/grid/tria_iterator.h>
242 * #include <deal.II/lac/affine_constraints.h>
243 * #include <deal.II/lac/full_matrix.h>
244 * #include <deal.II/lac/petsc_precondition.h>
245 * #include <deal.II/lac/petsc_sparse_matrix.h>
246 * #include <deal.II/lac/petsc_vector.h>
247 * #include <deal.II/lac/slepc_solver.h>
249 * #include <deal.II/numerics/data_out.h>
250 * #include <deal.II/numerics/vector_tools.h>
254 * For parallelization (
using WorkStream and Intel TBB)
257 * #include <deal.II/base/multithread_info.h>
258 * #include <deal.II/base/work_stream.h>
260 * #include
"petscpc.h"
264 * For Error Estimation/Indication and Smoothness Indication
267 * #include <deal.II/fe/fe_tools.h>
269 * #include <deal.II/numerics/error_estimator.h>
270 * #include <deal.II/numerics/smoothness_estimator.h>
276 * #include <deal.II/grid/grid_refinement.h>
279 * #include <iostream>
282 *
namespace Operations
289 * curlcurl(const ::FEValues<2> &fe_values,
290 *
const unsigned int & i,
291 *
const unsigned int & j,
292 *
const unsigned int & q_point)
294 *
auto gradu1_x1x2 = fe_values.shape_grad_component(i, q_point, 0);
295 *
auto gradu2_x1x2 = fe_values.shape_grad_component(i, q_point, 1);
297 *
auto gradv1_x1x2 = fe_values.shape_grad_component(j, q_point, 0);
298 *
auto gradv2_x1x2 = fe_values.shape_grad_component(j, q_point, 1);
299 *
return (gradu2_x1x2[0] - gradu1_x1x2[1]) *
300 * (gradv2_x1x2[0] - gradv1_x1x2[1]);
308 * dot_term(const ::FEValues<dim> &fe_values,
309 *
const unsigned int & i,
310 *
const unsigned int & j,
311 *
const unsigned int & q_point)
313 *
double output = 0.0;
314 *
for (
unsigned int comp = 0; comp < dim; ++comp)
316 * output += fe_values.shape_value_component(i, q_point, comp) *
317 * fe_values.shape_value_component(j, q_point, comp);
327 *
namespace Structures
334 *
const unsigned int dim = 2;
336 *
const std::vector<Point<2>>
vertices = {{scaling * 0.0, scaling * 0.0},
337 * {scaling * 0.5, scaling * 0.0},
338 * {scaling * 0.0, scaling * 0.5},
339 * {scaling * 0.5, scaling * 0.5},
340 * {scaling * 0.0, scaling * 1.0},
341 * {scaling * 0.5, scaling * 1.0},
342 * {scaling * 1.0, scaling * 0.5},
343 * {scaling * 1.0, scaling * 1.0}};
345 *
const std::vector<std::array<int, GeometryInfo<dim>::vertices_per_cell>>
346 * cell_vertices = {{{0, 1, 2, 3}}, {{2, 3, 4, 5}}, {{3, 6, 5, 7}}};
347 *
const unsigned int n_cells = cell_vertices.size();
348 * std::vector<CellData<dim>> cells(n_cells,
CellData<dim>());
349 *
for (
unsigned int i = 0; i <
n_cells; ++i)
351 *
for (
unsigned int j = 0; j < cell_vertices[i].size(); ++j)
352 * cells[i].
vertices[j] = cell_vertices[i][j];
353 * cells[i].material_id = 0;
362 *
const double & scaling)
364 *
const unsigned int dim = 2;
366 *
const std::vector<Point<2>>
vertices = {{scaling * 0.0, scaling * 0.0},
367 * {scaling * 0.6, scaling * 0.0},
368 * {scaling * 0.0, scaling * 0.3},
369 * {scaling * 0.6, scaling * 0.3}};
371 *
const std::vector<std::array<int, GeometryInfo<dim>::vertices_per_cell>>
372 * cell_vertices = {{{0, 1, 2, 3}}};
373 *
const unsigned int n_cells = cell_vertices.size();
374 * std::vector<CellData<dim>> cells(n_cells,
CellData<dim>());
375 *
for (
unsigned int i = 0; i <
n_cells; ++i)
377 *
for (
unsigned int j = 0; j < cell_vertices[i].size(); ++j)
378 * cells[i].
vertices[j] = cell_vertices[i][j];
379 * cells[i].material_id = 0;
409 *
virtual unsigned int
410 * solve_problem() = 0;
412 * set_refinement_cycle(
const unsigned int cycle);
415 * output_solution() = 0;
420 *
unsigned int refinement_cycle = 0;
421 * std::unique_ptr<ParameterHandler> parameters;
422 *
unsigned int n_eigenpairs = 1;
423 *
double target = 0.0;
424 *
unsigned int eigenpair_selection_scheme;
425 *
unsigned int max_cycles = 0;
426 * ompi_communicator_t * mpi_communicator = PETSC_COMM_SELF;
435 * , parameters(std::make_unique<ParameterHandler>())
437 * parameters->declare_entry(
438 *
"Eigenpair selection scheme",
441 *
"The type of eigenpairs to find (0 - smallest, 1 - target)");
442 * parameters->declare_entry(
"Number of eigenvalues/eigenfunctions",
445 *
"The number of eigenvalues/eigenfunctions "
446 *
"to be computed.");
447 * parameters->declare_entry(
"Target eigenvalue",
450 *
"The target eigenvalue (if scheme == 1)");
452 * parameters->declare_entry(
"Cycles number",
455 *
"The number of cycles in refinement");
456 * parameters->parse_input(prm_file);
458 * eigenpair_selection_scheme =
459 * parameters->get_integer(
"Eigenpair selection scheme");
463 * The
project currently only supports selection by a target eigenvalue.
464 * Furthermore, only one eigenpair can be computed at a time.
467 * assert(eigenpair_selection_scheme == 1 &&
468 *
"Selection by a target is the only currently supported option!");
470 * parameters->get_integer(
"Number of eigenvalues/eigenfunctions");
472 * n_eigenpairs == 1 &&
473 *
"Only the computation of a single eigenpair is currently supported!");
475 * target = parameters->get_double(
"Target eigenvalue");
476 * max_cycles = parameters->get_integer(
"Cycles number");
477 *
if (eigenpair_selection_scheme == 1)
483 * Base<dim>::set_refinement_cycle(
const unsigned int cycle)
485 * refinement_cycle = cycle;
494 *
class EigenSolver :
public virtual Base<dim>
497 * EigenSolver(
const std::string & prm_file,
499 *
const unsigned int &minimum_degree,
500 *
const unsigned int &maximum_degree,
501 *
const unsigned int &starting_degree);
503 *
virtual unsigned int
504 * solve_problem()
override;
506 *
virtual unsigned int
509 *
template <
class SolverType>
511 * initialize_eigensolver(SolverType &eigensolver);
520 *
const std::unique_ptr<hp::FECollection<dim>> fe_collection;
521 * std::unique_ptr<hp::QCollection<dim>> quadrature_collection;
522 * std::unique_ptr<
hp::QCollection<dim - 1>> face_quadrature_collection;
524 *
const unsigned int max_degree, min_degree;
527 *
for the actual solution
530 * std::unique_ptr<std::vector<PETScWrappers::MPI::Vector>> eigenfunctions;
531 * std::unique_ptr<std::vector<double>>
eigenvalues;
541 * convert_solution();
553 * EigenSolver<dim>::EigenSolver(
const std::string & prm_file,
555 *
const unsigned int &minimum_degree,
556 *
const unsigned int &maximum_degree,
557 *
const unsigned int &starting_degree)
563 * , max_degree(maximum_degree)
564 * , min_degree(minimum_degree)
566 * std::make_unique<std::vector<PETScWrappers::MPI::Vector>>())
567 * ,
eigenvalues(std::make_unique<std::vector<double>>())
569 *
for (
unsigned int degree = min_degree; degree <= max_degree; ++degree)
574 * Generate quadrature collection with
sorted quadrature weights
579 * quadrature_collection->push_back(sorted_quadrature);
581 *
const QGauss<dim - 1> face_quadrature(degree + 1);
582 *
const QSorted<dim - 1> sorted_face_quadrature(face_quadrature);
583 * face_quadrature_collection->push_back(sorted_face_quadrature);
587 * adjust the discretization
590 *
if (starting_degree > min_degree && starting_degree <= max_degree)
592 *
const unsigned int start_diff = starting_degree - min_degree;
594 * cell1 = dof_handler.begin_active(),
595 * endc1 = dof_handler.end();
596 *
for (; cell1 < endc1; ++cell1)
598 * cell1->set_active_fe_index(start_diff);
609 * EigenSolver<dim>::get_lambda_h()
611 *
return &(*eigenvalues)[0];
620 * EigenSolver<dim>::get_solution()
630 * EigenSolver<dim>::convert_solution()
632 * solution.
reinit((*eigenfunctions)[0].size());
633 *
for (
unsigned int i = 0; i < solution.size(); ++i)
634 * solution[i] = (*eigenfunctions)[0][i];
644 *
template <
class SolverType>
646 * EigenSolver<dim>::initialize_eigensolver(SolverType &eigensolver)
650 * From the parameters
class, initialize the eigensolver...
653 *
switch (this->eigenpair_selection_scheme)
656 * eigensolver.set_which_eigenpairs(EPS_TARGET_MAGNITUDE);
659 * eigensolver.set_target_eigenvalue(this->target);
664 * eigensolver.set_which_eigenpairs(EPS_SMALLEST_MAGNITUDE);
668 * eigensolver.set_problem_type(EPS_GHEP);
671 * apply a Shift-Invert spectrum transformation
677 *
double shift_scalar = this->parameters->get_double(
"Target eigenvalue");
686 * this->mpi_communicator, additional_data);
688 * eigensolver.set_transformation(spectral_transformation);
689 * eigensolver.set_target_eigenvalue(this->target);
698 * EigenSolver<dim>::solve_problem()
708 * this->mpi_communicator);
710 * initialize_eigensolver(eigensolver);
717 * eigensolver.solve(stiffness_matrix,
721 * eigenfunctions->size());
722 *
for (
auto &entry : *eigenfunctions)
724 * constraints.distribute(entry);
726 * convert_solution();
728 *
return solver_control.last_step();
733 * EigenSolver<dim>::n_dofs() const
735 *
return dof_handler.n_dofs();
745 * EigenSolver<dim>::setup_system()
747 * dof_handler.distribute_dofs(*fe_collection);
748 * constraints.clear();
751 * constraints.close();
753 * eigenfunctions->resize(this->n_eigenpairs);
756 *
IndexSet eigenfunction_index_set = dof_handler.locally_owned_dofs();
758 *
for (
auto &entry : *eigenfunctions)
760 * entry.
reinit(eigenfunction_index_set, MPI_COMM_WORLD);
769 * EigenSolver<dim>::assemble_system()
772 * *quadrature_collection,
778 * Prep the system matrices
for the solution
781 * stiffness_matrix.reinit(dof_handler.n_dofs(),
782 * dof_handler.n_dofs(),
783 * dof_handler.max_couplings_between_dofs());
785 * dof_handler.n_dofs(),
786 * dof_handler.max_couplings_between_dofs());
789 * std::vector<types::global_dof_index> local_dof_indices;
791 *
for (
const auto &cell : dof_handler.active_cell_iterators())
793 * const unsigned
int dofs_per_cell = cell->get_fe().dofs_per_cell;
795 * cell_stiffness_matrix.reinit(dofs_per_cell, dofs_per_cell);
796 * cell_stiffness_matrix = 0;
798 * cell_mass_matrix.reinit(dofs_per_cell, dofs_per_cell);
799 * cell_mass_matrix = 0;
801 * hp_fe_values.reinit(cell);
805 *
for (
unsigned int q_point = 0; q_point < fe_values.n_quadrature_points;
808 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i)
810 *
for (
unsigned int j = 0; j < dofs_per_cell; ++j)
814 * Note that (in general) the Nedelec element is not
815 * primitive, namely that the shape
functions are vectorial
816 * with components in more than one direction
822 * cell_stiffness_matrix(i, j) +=
823 * Operations::curlcurl(fe_values, i, j, q_point) *
824 * fe_values.JxW(q_point);
826 * cell_mass_matrix(i, j) +=
827 * (Operations::dot_term(fe_values, i, j, q_point)) *
828 * fe_values.JxW(q_point);
831 * local_dof_indices.resize(dofs_per_cell);
832 * cell->get_dof_indices(local_dof_indices);
835 * constraints.distribute_local_to_global(cell_stiffness_matrix,
838 * constraints.distribute_local_to_global(cell_mass_matrix,
845 *
for (
unsigned int i = 0; i < dof_handler.n_dofs(); ++i)
846 *
if (constraints.is_constrained(i))
848 * stiffness_matrix.set(i, i, 10000.0);
853 * since we have just
set individual elements, we need the following
865 *
class PrimalSolver :
public EigenSolver<dim>
868 * PrimalSolver(
const std::string & prm_file,
870 *
const unsigned int &min_degree,
871 *
const unsigned int &max_degree,
872 *
const unsigned int &starting_degree);
877 *
virtual unsigned int
878 * n_dofs()
const override;
882 * PrimalSolver<dim>::PrimalSolver(
const std::string & prm_file,
884 *
const unsigned int &min_degree,
885 *
const unsigned int &max_degree,
886 *
const unsigned int &starting_degree)
888 * , EigenSolver<dim>(prm_file,
901 * PrimalSolver<dim>::output_solution()
906 *
for (
const auto &cell : this->dof_handler.active_cell_iterators())
907 * fe_degrees(cell->active_cell_index()) =
908 * (*this->fe_collection)[cell->active_fe_index()].degree;
909 * data_out.add_data_vector(fe_degrees,
"fe_degree");
910 * data_out.add_data_vector((*this->eigenfunctions)[0],
911 * std::string(
"eigenfunction_no_") +
914 * std::cout <<
"Eigenvalue: " << (*this->
eigenvalues)[0]
915 * <<
" NDoFs: " << this->dof_handler.n_dofs() << std::endl;
916 * std::ofstream eigenvalues_out(
917 *
"eigenvalues-" + std::to_string(this->refinement_cycle) +
".txt");
919 * eigenvalues_out << std::setprecision(20) << (*this->
eigenvalues)[0] <<
" "
920 * << this->dof_handler.n_dofs() << std::endl;
922 * eigenvalues_out.close();
925 * data_out.build_patches();
926 * std::ofstream output(
"eigenvectors-" +
927 * std::to_string(this->refinement_cycle) +
".vtu");
928 * data_out.write_vtu(output);
933 * PrimalSolver<dim>::n_dofs() const
935 *
return EigenSolver<dim>::n_dofs();
940 * Note, that at least
for the demonstrated problem (i.e., a Hermitian problem
941 * and eigenvalue QoI), the dual problem is identical to the primal problem;
942 * however, it is convenient to separate them in
this manner (
e.g.,
for
943 * considering functionals of the eigenfunction).
947 *
class DualSolver :
public EigenSolver<dim>
950 * DualSolver(
const std::string & prm_file,
952 *
const unsigned int &min_degree,
953 *
const unsigned int &max_degree,
954 *
const unsigned int &starting_degree);
958 * DualSolver<dim>::DualSolver(
const std::string & prm_file,
960 *
const unsigned int &min_degree,
961 *
const unsigned int &max_degree,
962 *
const unsigned int &starting_degree)
964 * , EigenSolver<dim>(prm_file,
976 *
namespace ErrorIndicators
978 *
using namespace Maxwell;
985 *
template <
int dim,
bool report_dual>
986 *
class DualWeightedResidual :
public PrimalSolver<dim>,
public DualSolver<dim>
990 * output_eigenvalue_data(std::ofstream &os);
992 * output_qoi_error_estimates(std::ofstream &os);
999 * DualWeightedResidual(
const std::string & prm_file,
1001 *
const unsigned int &min_primal_degree,
1002 *
const unsigned int &max_primal_degree,
1003 *
const unsigned int &starting_primal_degree);
1005 *
virtual unsigned int
1006 * solve_problem()
override;
1009 * output_solution()
override;
1011 *
virtual unsigned int
1012 * n_dofs()
const override;
1021 * get_primal_DoFHandler();
1024 * get_dual_DoFHandler();
1027 * get_FECollection();
1030 * get_primal_FECollection();
1032 * std::unique_ptr<std::vector<PETScWrappers::MPI::Vector>> &
1033 * get_eigenfunctions();
1035 * std::unique_ptr<std::vector<PETScWrappers::MPI::Vector>> &
1036 * get_primal_eigenfunctions();
1038 * std::unique_ptr<std::vector<double>> &
1039 * get_primal_eigenvalues();
1041 * std::unique_ptr<std::vector<double>> &
1042 * get_dual_eigenvalues();
1045 * synchronize_discretization();
1050 *
return PrimalSolver<dim>::fe_collection->max_degree();
1052 *
double qoi_error_estimate = 0;
1073 * std::unique_ptr<hp::FEValues<dim>> cell_hp_fe_values;
1074 * std::unique_ptr<hp::FEFaceValues<dim>> face_hp_fe_values;
1075 * std::unique_ptr<hp::FEFaceValues<dim>> face_hp_fe_values_neighbor;
1076 * std::unique_ptr<hp::FESubfaceValues<dim>> subface_hp_fe_values;
1078 * std::unique_ptr<hp::FEValues<dim>> cell_hp_fe_values_forward;
1079 * std::unique_ptr<hp::FEFaceValues<dim>> face_hp_fe_values_forward;
1080 * std::unique_ptr<hp::FEFaceValues<dim>> face_hp_fe_values_neighbor_forward;
1081 * std::unique_ptr<hp::FESubfaceValues<dim>> subface_hp_fe_values_forward;
1082 *
using FaceIntegrals =
1083 *
typename std::map<typename DoFHandler<dim>::face_iterator,
double>;
1086 * solve_primal_problem();
1089 * solve_dual_problem();
1100 * initialize_error_estimation_data();
1103 * estimate_on_one_cell(
1107 *
const double & lambda_h,
1109 * FaceIntegrals & face_integrals);
1112 * integrate_over_cell(
1116 *
const double & lambda_h,
1120 * integrate_over_regular_face(
1122 *
const unsigned int & face_no,
1125 * FaceIntegrals & face_integrals);
1128 * integrate_over_irregular_face(
1130 *
const unsigned int & face_no,
1133 * FaceIntegrals & face_integrals);
1140 *
template <
int dim,
bool report_dual>
1141 * DualWeightedResidual<dim, report_dual>::DualWeightedResidual(
1142 *
const std::string & prm_file,
1144 *
const unsigned int &min_primal_degree,
1145 *
const unsigned int &max_primal_degree,
1146 *
const unsigned int &starting_primal_degree)
1148 * , PrimalSolver<dim>(prm_file,
1150 * min_primal_degree,
1151 * max_primal_degree,
1152 * starting_primal_degree)
1153 * , DualSolver<dim>(prm_file,
1155 * min_primal_degree + 1,
1156 * max_primal_degree + 1,
1157 * starting_primal_degree + 1)
1159 * initialize_error_estimation_data();
1166 *
template <
int dim,
bool report_dual>
1168 * DualWeightedResidual<dim, report_dual>::get_DoFHandler()
1171 *
return &(PrimalSolver<dim>::dof_handler);
1173 *
return &(DualSolver<dim>::dof_handler);
1178 * See above function, but to specifically output the primal
DoFHandler...
1181 *
template <
int dim,
bool report_dual>
1183 * DualWeightedResidual<dim, report_dual>::get_primal_DoFHandler()
1185 *
return &(PrimalSolver<dim>::dof_handler);
1190 * See above function, but
for the FECollection
1193 *
template <
int dim,
bool report_dual>
1195 * DualWeightedResidual<dim, report_dual>::get_FECollection()
1198 *
return &*(PrimalSolver<dim>::fe_collection);
1200 *
return &*(DualSolver<dim>::fe_collection);
1205 * See above function, but
for the primal FECollection
1208 *
template <
int dim,
bool report_dual>
1210 * DualWeightedResidual<dim, report_dual>::get_primal_FECollection()
1212 *
return &*(PrimalSolver<dim>::fe_collection);
1215 *
template <
int dim,
bool report_dual>
1217 * DualWeightedResidual<dim, report_dual>::get_dual_DoFHandler()
1219 *
return &(DualSolver<dim>::dof_handler);
1223 *
template <
int dim,
bool report_dual>
1224 * std::unique_ptr<std::vector<PETScWrappers::MPI::Vector>> &
1225 * DualWeightedResidual<dim, report_dual>::get_eigenfunctions()
1228 *
return (PrimalSolver<dim>::eigenfunctions);
1230 *
return (DualSolver<dim>::eigenfunctions);
1234 *
template <
int dim,
bool report_dual>
1235 * std::unique_ptr<std::vector<PETScWrappers::MPI::Vector>> &
1236 * DualWeightedResidual<dim, report_dual>::get_primal_eigenfunctions()
1238 *
return (PrimalSolver<dim>::eigenfunctions);
1242 *
template <
int dim,
bool report_dual>
1243 * std::unique_ptr<std::vector<double>> &
1244 * DualWeightedResidual<dim, report_dual>::get_primal_eigenvalues()
1246 *
return PrimalSolver<dim>::eigenvalues;
1250 *
template <
int dim,
bool report_dual>
1251 * std::unique_ptr<std::vector<double>> &
1252 * DualWeightedResidual<dim, report_dual>::get_dual_eigenvalues()
1254 *
return DualSolver<dim>::eigenvalues;
1257 *
template <
int dim,
bool report_dual>
1259 * DualWeightedResidual<dim, report_dual>::output_solution()
1261 * PrimalSolver<dim>::output_solution();
1266 * Solves the primal problem
1269 *
template <
int dim,
bool report_dual>
1271 * DualWeightedResidual<dim, report_dual>::solve_primal_problem()
1273 *
return PrimalSolver<dim>::solve_problem();
1278 * Solves the dual problem
1281 *
template <
int dim,
bool report_dual>
1283 * DualWeightedResidual<dim, report_dual>::solve_dual_problem()
1285 *
return DualSolver<dim>::solve_problem();
1292 *
template <
int dim,
bool report_dual>
1294 * DualWeightedResidual<dim, report_dual>::solve_problem()
1296 * DualWeightedResidual<dim, report_dual>::solve_primal_problem();
1297 *
return DualWeightedResidual<dim, report_dual>::solve_dual_problem();
1303 *
template <
int dim,
bool report_dual>
1305 * DualWeightedResidual<dim, report_dual>::n_dofs() const
1307 *
return PrimalSolver<dim>::n_dofs();
1316 *
template <
int dim,
bool report_dual>
1318 * DualWeightedResidual<dim, report_dual>::synchronize_discretization()
1332 * In
this case, we have modified the polynomial orders
for the dual;
1333 * need to update the primal
1336 * dof1 = &(DualSolver<dim>::dof_handler);
1337 * dof2 = &(PrimalSolver<dim>::dof_handler);
1340 * endc1 = dof1->end();
1342 *
for (; cell1 < endc1; ++cell1, ++cell2)
1344 * cell2->set_active_fe_index(cell1->active_fe_index());
1352 *
template <
int dim,
bool report_dual>
1354 * DualWeightedResidual<dim, report_dual>::initialize_error_estimation_data()
1358 * initialize the cell fe_values...
1361 * cell_hp_fe_values = std::make_unique<hp::FEValues<dim>>(
1362 * *DualSolver<dim>::fe_collection,
1363 * *DualSolver<dim>::quadrature_collection,
1366 * face_hp_fe_values = std::make_unique<hp::FEFaceValues<dim>>(
1367 * *DualSolver<dim>::fe_collection,
1368 * *DualSolver<dim>::face_quadrature_collection,
1371 * face_hp_fe_values_neighbor = std::make_unique<hp::FEFaceValues<dim>>(
1372 * *DualSolver<dim>::fe_collection,
1373 * *DualSolver<dim>::face_quadrature_collection,
1376 * subface_hp_fe_values = std::make_unique<hp::FESubfaceValues<dim>>(
1377 * *DualSolver<dim>::fe_collection,
1378 * *DualSolver<dim>::face_quadrature_collection,
1387 *
template <
int dim,
bool report_dual>
1389 * DualWeightedResidual<dim, report_dual>::normalize_solutions(
1393 *
double sum_primal = 0.0, sum_dual = 0.0;
1394 *
for (
const auto &cell :
1395 * DualSolver<dim>::dof_handler.active_cell_iterators())
1397 * cell_hp_fe_values->
reinit(cell);
1401 * grab the fe_values
object
1407 * std::vector<Vector<double>> cell_primal_values(
1409 * cell_dual_values(fe_values.n_quadrature_points,
Vector<double>(dim));
1410 * fe_values.get_function_values(primal_solution, cell_primal_values);
1411 * fe_values.get_function_values(dual_weights, cell_dual_values);
1414 *
for (
unsigned int p = 0; p < fe_values.n_quadrature_points; ++p)
1417 * cell_primal_values[p] * cell_primal_values[p] * fe_values.JxW(p);
1419 * cell_dual_values[p] * cell_dual_values[p] * fe_values.JxW(p);
1423 * primal_solution /=
sqrt(sum_primal);
1424 * dual_weights /=
sqrt(sum_dual);
1431 *
template <
int dim,
bool report_dual>
1433 * DualWeightedResidual<dim, report_dual>::estimate_error(
1438 * The constraints could be grabbed directly, but
this is simple
1443 * primal_hanging_node_constraints);
1444 * primal_hanging_node_constraints.close();
1448 * dual_hanging_node_constraints);
1449 * dual_hanging_node_constraints.close();
1453 * First map the primal solution to the space of the dual solution
1454 * This allows us to use just one
set of
FEValues objects (rather than one
1455 * set
for the primal, one
for dual)
1461 *
Vector<double> primal_solution(DualSolver<dim>::dof_handler.n_dofs());
1463 * embed(PrimalSolver<dim>::dof_handler,
1464 * DualSolver<dim>::dof_handler,
1465 * dual_hanging_node_constraints,
1466 * *(PrimalSolver<dim>::get_solution()),
1469 *
Vector<double> &dual_solution = *(DualSolver<dim>::get_solution());
1471 * normalize_solutions(primal_solution, dual_solution);
1473 *
Vector<double> dual_weights(DualSolver<dim>::dof_handler.n_dofs()),
1474 * dual_weights_interm(PrimalSolver<dim>::dof_handler.n_dofs());
1478 * First
extract the dual solution to the space of the primal
1481 *
extract(DualSolver<dim>::dof_handler,
1482 * PrimalSolver<dim>::dof_handler,
1483 * primal_hanging_node_constraints,
1484 * *(DualSolver<dim>::get_solution()),
1485 * dual_weights_interm);
1489 * Now embed
this back to the space of the dual solution
1492 * embed(PrimalSolver<dim>::dof_handler,
1493 * DualSolver<dim>::dof_handler,
1494 * dual_hanging_node_constraints,
1495 * dual_weights_interm,
1501 * Subtract
this from the full dual solution
1504 * dual_weights -= *(DualSolver<dim>::get_solution());
1505 * dual_weights *= -1.0;
1507 * *(DualSolver<dim>::get_solution()) -= primal_solution;
1509 * FaceIntegrals face_integrals;
1510 *
for (
const auto &cell :
1511 * DualSolver<dim>::dof_handler.active_cell_iterators())
1512 * for (const auto &face : cell->face_iterators())
1513 * face_integrals[face] = -1e20;
1516 *
for (
const auto &cell :
1517 * DualSolver<dim>::dof_handler.active_cell_iterators())
1519 * estimate_on_one_cell(cell,
1522 * *(PrimalSolver<dim>::get_lambda_h()),
1526 *
unsigned int present_cell = 0;
1527 *
for (
const auto &cell :
1528 * DualSolver<dim>::dof_handler.active_cell_iterators())
1530 * for (const auto &face : cell->face_iterators())
1532 *
Assert(face_integrals.find(face) != face_integrals.
end(),
1533 * ExcInternalError());
1534 * error_indicators(present_cell) -= 0.5 * face_integrals[face];
1541 * Now, with the error indicators computed, let us produce the
1542 * estimate of the QoI error
1545 * this->qoi_error_estimate =
1546 * this->get_global_QoI_error(*(DualSolver<dim>::get_solution()),
1547 * error_indicators);
1548 * std::cout <<
"Estimated QoI error: " << std::setprecision(20)
1549 * << qoi_error_estimate << std::endl;
1556 *
template <
int dim,
bool report_dual>
1558 * DualWeightedResidual<dim, report_dual>::estimate_on_one_cell(
1562 *
const double & lambda_h,
1564 * FaceIntegrals & face_integrals)
1566 * integrate_over_cell(
1567 * cell, primal_solution, dual_weights, lambda_h, error_indicators);
1568 *
for (
unsigned int face_no :
GeometryInfo<dim>::face_indices())
1570 * if (cell->face(face_no)->at_boundary())
1572 * face_integrals[cell->face(face_no)] = 0.0;
1575 *
if ((cell->neighbor(face_no)->has_children() ==
false) &&
1576 * (cell->neighbor(face_no)->level() == cell->level()) &&
1577 * (cell->neighbor(face_no)->index() < cell->index()))
1579 *
if (cell->at_boundary(face_no) ==
false)
1580 *
if (cell->neighbor(face_no)->level() < cell->level())
1582 *
if (cell->face(face_no)->has_children() ==
false)
1583 * integrate_over_regular_face(
1584 * cell, face_no, primal_solution, dual_weights, face_integrals);
1586 * integrate_over_irregular_face(
1587 * cell, face_no, primal_solution, dual_weights, face_integrals);
1594 *
template <
int dim,
bool report_dual>
1596 * DualWeightedResidual<dim, report_dual>::integrate_over_cell(
1600 *
const double & lambda_h,
1603 * cell_hp_fe_values->reinit(cell);
1606 * Grab the fe_values
object
1610 * std::vector<std::vector<Tensor<2, dim, double>>> cell_hessians(
1612 * std::vector<Vector<double>> cell_primal_values(
1614 * cell_dual_values(fe_values.n_quadrature_points,
Vector<double>(dim));
1615 * fe_values.get_function_values(primal_solution, cell_primal_values);
1616 * fe_values.get_function_hessians(primal_solution, cell_hessians);
1617 * fe_values.get_function_values(dual_weights, cell_dual_values);
1622 *
for (
unsigned int p = 0; p < fe_values.n_quadrature_points; ++p)
1625 * ( (cell_hessians[p][1][1][0] -
1626 * cell_hessians[p][0][1][1]) *
1627 * (cell_dual_values[p](0)) +
1629 * (cell_hessians[p][0][0][1] - cell_hessians[p][1][0][0]) *
1630 * (cell_dual_values[p](1)) -
1631 * lambda_h * (cell_primal_values[p](0) * cell_dual_values[p](0) +
1632 * cell_primal_values[p](1) * cell_dual_values[p](1))) *
1636 * error_indicators(cell->active_cell_index()) +=
sum;
1642 *
template <
int dim,
bool report_dual>
1644 * DualWeightedResidual<dim, report_dual>::integrate_over_regular_face(
1646 *
const unsigned int & face_no,
1649 * FaceIntegrals & face_integrals)
1652 * ExcInternalError());
1653 *
const unsigned int neighbor_neighbor = cell->neighbor_of_neighbor(face_no);
1654 *
const auto neighbor = cell->neighbor(face_no);
1656 *
const unsigned int quadrature_index =
1657 *
std::max(cell->active_fe_index(), neighbor->active_fe_index());
1658 * face_hp_fe_values->reinit(cell, face_no, quadrature_index);
1661 * std::vector<std::vector<Tensor<1, dim, double>>> cell_primal_grads(
1662 * fe_face_values_cell.n_quadrature_points,
1664 * neighbor_primal_grads(fe_face_values_cell.n_quadrature_points,
1666 * fe_face_values_cell.get_function_gradients(primal_solution,
1667 * cell_primal_grads);
1669 * face_hp_fe_values_neighbor->reinit(neighbor,
1670 * neighbor_neighbor,
1671 * quadrature_index);
1675 * neighbor_primal_grads);
1676 *
const unsigned int n_q_points = fe_face_values_cell.n_quadrature_points;
1677 *
double face_integral = 0.0;
1678 * std::vector<Vector<double>> cell_dual_values(n_q_points,
1680 * fe_face_values_cell.get_function_values(dual_weights, cell_dual_values);
1681 *
for (
unsigned int p = 0; p < n_q_points; ++p)
1683 *
auto face_normal = fe_face_values_cell.normal_vector(p);
1686 * (cell_primal_grads[p][1][0] - cell_primal_grads[p][0][1] -
1687 * neighbor_primal_grads[p][1][0] + neighbor_primal_grads[p][0][1]) *
1688 * (cell_dual_values[p][0] * face_normal[1] -
1689 * cell_dual_values[p][1] * face_normal[0]) *
1690 * fe_face_values_cell.JxW(p);
1692 *
Assert(face_integrals.find(cell->face(face_no)) != face_integrals.end(),
1693 * ExcInternalError());
1694 *
Assert(face_integrals[cell->face(face_no)] == -1e20, ExcInternalError());
1695 * face_integrals[cell->face(face_no)] = face_integral;
1701 *
template <
int dim,
bool report_dual>
1703 * DualWeightedResidual<dim, report_dual>::integrate_over_irregular_face(
1705 *
const unsigned int & face_no,
1708 * FaceIntegrals & face_integrals)
1712 * cell->neighbor(face_no);
1715 *
Assert(neighbor->has_children(), ExcInternalError());
1717 *
const unsigned int neighbor_neighbor = cell->neighbor_of_neighbor(face_no);
1718 *
for (
unsigned int subface_no = 0; subface_no < face->n_children();
1722 * cell->neighbor_child_on_subface(face_no, subface_no);
1723 *
Assert(neighbor_child->face(neighbor_neighbor) ==
1724 * cell->face(face_no)->child(subface_no),
1725 * ExcInternalError());
1726 *
const unsigned int quadrature_index =
1727 *
std::max(cell->active_fe_index(), neighbor_child->active_fe_index());
1730 * initialize fe_subface values_cell
1733 * subface_hp_fe_values->reinit(cell,
1736 * quadrature_index);
1739 * std::vector<std::vector<Tensor<1, dim, double>>> cell_primal_grads(
1740 * subface_fe_values_cell.n_quadrature_points,
1742 * neighbor_primal_grads(subface_fe_values_cell.n_quadrature_points,
1744 * subface_fe_values_cell.get_function_gradients(primal_solution,
1745 * cell_primal_grads);
1748 * initialize fe_face_values_neighbor
1751 * face_hp_fe_values_neighbor->reinit(neighbor_child,
1752 * neighbor_neighbor,
1753 * quadrature_index);
1757 * neighbor_primal_grads);
1758 *
const unsigned int n_q_points =
1759 * subface_fe_values_cell.n_quadrature_points;
1760 * std::vector<Vector<double>> cell_dual_values(n_q_points,
1762 * face_fe_values_neighbor.get_function_values(dual_weights,
1763 * cell_dual_values);
1765 *
double face_integral = 0.0;
1767 *
for (
unsigned int p = 0; p < n_q_points; ++p)
1769 *
auto face_normal = face_fe_values_neighbor.normal_vector(p);
1771 * (cell_primal_grads[p][0][1] - cell_primal_grads[p][1][0] +
1772 * neighbor_primal_grads[p][1][0] -
1773 * neighbor_primal_grads[p][0][1]) *
1774 * (cell_dual_values[p][0] * face_normal[1] -
1775 * cell_dual_values[p][1] * face_normal[0]) *
1776 * face_fe_values_neighbor.JxW(p);
1778 * face_integrals[neighbor_child->face(neighbor_neighbor)] = face_integral;
1781 *
for (
unsigned int subface_no = 0; subface_no < face->n_children();
1784 *
Assert(face_integrals.find(face->child(subface_no)) !=
1785 * face_integrals.end(),
1786 * ExcInternalError());
1787 *
Assert(face_integrals[face->child(subface_no)] != -1e20,
1788 * ExcInternalError());
1789 *
sum += face_integrals[face->child(subface_no)];
1791 * face_integrals[face] =
sum;
1794 *
template <
int dim,
bool report_dual>
1796 * DualWeightedResidual<dim, report_dual>::get_global_QoI_error(
1800 *
auto dual_less_primal =
1804 *
double scaling_factor = 0.0;
1805 *
for (
const auto &cell :
1806 * DualSolver<dim>::dof_handler.active_cell_iterators())
1808 * cell_hp_fe_values->
reinit(cell);
1811 * grab the fe_values
object
1817 * std::vector<Vector<double>> cell_values(fe_values.n_quadrature_points,
1819 * fe_values.get_function_values(dual_less_primal, cell_values);
1821 *
for (
unsigned int p = 0; p < fe_values.n_quadrature_points; ++p)
1824 * (cell_values[p] * cell_values[p]) * fe_values.JxW(p);
1827 *
double global_QoI_error = 0.0;
1828 *
for (
const auto &indicator : error_indicators)
1830 * global_QoI_error += indicator;
1833 * global_QoI_error /= (1 - 0.5 * scaling_factor);
1834 *
return global_QoI_error;
1838 *
template <
int dim,
bool report_dual>
1840 * DualWeightedResidual<dim, report_dual>::embed(
1847 * assert(u2.size() == dof2.n_dofs() &&
"Incorrect input vector size!");
1852 * endc1 = dof1.end();
1855 *
for (; cell1 < endc1; ++cell1, ++cell2)
1862 * assert(fe1.degree < fe2.degree &&
"Incorrect usage of embed!");
1866 * Get the embedding_dofs
1875 * std::vector<unsigned int> embedding_dofs =
1876 * fe2.get_embedding_dofs(fe1.degree);
1877 *
const unsigned int dofs_per_cell2 = fe2.n_dofs_per_cell();
1883 * local_dof_values_1.reinit(fe1.dofs_per_cell);
1884 * cell1->get_dof_values(solution, local_dof_values_1);
1886 *
for (
unsigned int i = 0; i < local_dof_values_1.size(); ++i)
1887 * local_dof_values_2[embedding_dofs[i]] = local_dof_values_1[i];
1891 * Now
set this changes to the global vector
1894 * cell2->set_dof_values(local_dof_values_2, u2);
1900 * Applies the constraints of the target finite element space
1903 * constraints.distribute(u2);
1906 *
template <
int dim,
bool report_dual>
1908 * DualWeightedResidual<dim, report_dual>::extract(
1917 * Maps from fe1 to fe2
1920 * assert(u2.size() == dof2.n_dofs() &&
"Incorrect input vector size!");
1925 * endc1 = dof1.end();
1928 *
for (; cell1 < endc1; ++cell1, ++cell2)
1935 * assert(fe1.degree > fe2.degree &&
"Incorrect usage of extract!");
1939 * Get the embedding_dofs
1942 * std::vector<unsigned int> embedding_dofs =
1943 * fe1.get_embedding_dofs(fe2.degree);
1944 *
const unsigned int dofs_per_cell2 = fe2.n_dofs_per_cell();
1950 * local_dof_values_1.reinit(fe1.dofs_per_cell);
1951 * cell1->get_dof_values(solution, local_dof_values_1);
1953 *
for (
unsigned int i = 0; i < local_dof_values_2.size(); ++i)
1954 * local_dof_values_2[i] = local_dof_values_1[embedding_dofs[i]];
1958 * Now
set this changes to the global vector
1961 * cell2->set_dof_values(local_dof_values_2, u2);
1967 * Applies the constraints of the target finite element space
1970 * constraints.distribute(u2);
1972 *
template <
int dim,
bool report_dual>
1974 * DualWeightedResidual<dim, report_dual>::output_eigenvalue_data(
1975 * std::ofstream &os)
1977 * os << (*this->get_primal_eigenvalues())[0] <<
" "
1978 * << (this->get_primal_DoFHandler())->n_dofs() <<
" "
1979 * << (*this->get_dual_eigenvalues())[0] <<
" "
1980 * << (this->get_dual_DoFHandler())->n_dofs() << std::endl;
1982 *
template <
int dim,
bool report_dual>
1984 * DualWeightedResidual<dim, report_dual>::output_qoi_error_estimates(
1985 * std::ofstream &os)
1987 * os << qoi_error_estimate << std::endl;
1994 *
template <
int dim>
1995 *
class KellyErrorIndicator :
public PrimalSolver<dim>
2004 * output_eigenvalue_data(std::ofstream &os);
2006 * output_qoi_error_estimates(std::ofstream &);
2007 * KellyErrorIndicator(
const std::string & prm_file,
2009 *
const unsigned int &min_degree,
2010 *
const unsigned int &max_degree,
2011 *
const unsigned int &starting_degree);
2013 *
virtual unsigned int
2014 * solve_problem()
override;
2017 * output_solution()
override;
2020 * get_FECollection();
2023 * get_primal_FECollection();
2025 * std::unique_ptr<std::vector<PETScWrappers::MPI::Vector>> &
2026 * get_eigenfunctions();
2028 * std::unique_ptr<std::vector<PETScWrappers::MPI::Vector>> &
2029 * get_primal_eigenfunctions();
2031 * std::unique_ptr<std::vector<double>> &
2032 * get_primal_eigenvalues();
2036 * synchronize_discretization();
2042 * get_primal_DoFHandler();
2047 *
return PrimalSolver<dim>::fe_collection->max_degree();
2049 *
double qoi_error_estimate = 0;
2057 * prune_eigenpairs(
const double &TOL);
2060 * std::vector<const ReadVector<PetscScalar> *> eigenfunction_ptrs;
2062 * std::vector<const PETScWrappers::MPI::Vector *> eigenfunction_ptrs;
2064 * std::vector<const double *> eigenvalue_ptrs;
2066 * std::vector<std::shared_ptr<Vector<float>>> errors;
2069 *
template <
int dim>
2070 * KellyErrorIndicator<dim>::KellyErrorIndicator(
2071 *
const std::string & prm_file,
2073 *
const unsigned int &min_degree,
2074 *
const unsigned int &max_degree,
2075 *
const unsigned int &starting_degree)
2076 * : Base<dim>(prm_file, coarse_grid)
2077 * , PrimalSolver<dim>(prm_file,
2084 *
template <
int dim>
2086 * KellyErrorIndicator<dim>::solve_problem()
2088 *
return PrimalSolver<dim>::solve_problem();
2091 *
template <
int dim>
2093 * KellyErrorIndicator<dim>::get_FECollection()
2095 *
return &*(PrimalSolver<dim>::fe_collection);
2098 *
template <
int dim>
2100 * KellyErrorIndicator<dim>::get_primal_FECollection()
2102 *
return &*(PrimalSolver<dim>::fe_collection);
2105 *
template <
int dim>
2106 * std::unique_ptr<std::vector<PETScWrappers::MPI::Vector>> &
2107 * KellyErrorIndicator<dim>::get_eigenfunctions()
2109 *
return (PrimalSolver<dim>::eigenfunctions);
2112 *
template <
int dim>
2113 * std::unique_ptr<std::vector<double>> &
2114 * KellyErrorIndicator<dim>::get_primal_eigenvalues()
2116 *
return PrimalSolver<dim>::eigenvalues;
2119 *
template <
int dim>
2120 * std::unique_ptr<std::vector<PETScWrappers::MPI::Vector>> &
2121 * KellyErrorIndicator<dim>::get_primal_eigenfunctions()
2123 *
return (PrimalSolver<dim>::eigenfunctions);
2126 *
template <
int dim>
2128 * KellyErrorIndicator<dim>::get_DoFHandler()
2130 *
return &(PrimalSolver<dim>::dof_handler);
2133 *
template <
int dim>
2135 * KellyErrorIndicator<dim>::get_primal_DoFHandler()
2137 *
return &(PrimalSolver<dim>::dof_handler);
2140 *
template <
int dim>
2142 * KellyErrorIndicator<dim>::synchronize_discretization()
2146 * This function does
nothing for this error indicator
2152 *
template <
int dim>
2154 * KellyErrorIndicator<dim>::output_solution()
2156 * PrimalSolver<dim>::output_solution();
2159 *
template <
int dim>
2161 * KellyErrorIndicator<dim>::prune_eigenpairs(
const double &TOL)
2163 *
unsigned int count = 0;
2164 *
for (
size_t eigenpair_index = 0;
2165 * eigenpair_index < this->eigenfunctions->size();
2166 * ++eigenpair_index)
2168 *
if (count >= this->n_eigenpairs)
2170 *
if (
abs((*this->eigenvalues)[eigenpair_index]) < TOL)
2173 * eigenfunction_ptrs.push_back(&(*this->eigenfunctions)[eigenpair_index]);
2174 * eigenvalue_ptrs.push_back(&(*this->eigenvalues)[eigenpair_index]);
2178 *
template <
int dim>
2180 * KellyErrorIndicator<dim>::estimate_error(
Vector<double> &error_indicators)
2182 * std::cout <<
"Marking cells via Kelly indicator..." << std::endl;
2183 * prune_eigenpairs(1e-9);
2186 * deallocate the errors vector
2190 *
for (
size_t i = 0; i < eigenfunction_ptrs.size(); ++i)
2192 * errors.emplace_back(
2195 * std::vector<Vector<float> *> estimated_error_per_cell(
2196 * eigenfunction_ptrs.size());
2197 *
for (
size_t i = 0; i < eigenfunction_ptrs.size(); ++i)
2199 * estimated_error_per_cell[i] = errors[i].get();
2206 * *this->face_quadrature_collection,
2212 * *this->face_quadrature_collection,
2214 * eigenfunction_ptrs,
2215 * estimated_error_per_cell);
2218 *
for (
auto &error_vec : errors)
2220 * auto normalized_vec = *error_vec;
2221 * normalized_vec /= normalized_vec.l1_norm();
2223 *
for (
unsigned int i = 0; i < error_indicators.size(); ++i)
2224 * error_indicators(i) += double(normalized_vec(i));
2226 * std::cout <<
"...Done!" << std::endl;
2228 *
template <
int dim>
2230 * KellyErrorIndicator<dim>::output_eigenvalue_data(std::ofstream &os)
2232 * os << (*this->get_primal_eigenvalues())[0] <<
" "
2233 * << (this->get_primal_DoFHandler())->n_dofs() << std::endl;
2235 *
template <
int dim>
2237 * KellyErrorIndicator<dim>::output_qoi_error_estimates(std::ofstream &)
2247 *
namespace RegularityIndicators
2249 *
using namespace dealii;
2253 *
template <
int dim>
2254 *
class LegendreInfo
2258 *
class LegendreInfo<2>
2261 * std::unique_ptr<FESeries::Legendre<2>> legendre_u, legendre_v;
2269 * assert(fe_collection !=
nullptr && dof_handler !=
nullptr &&
2270 *
"A valid FECollection and DoFHandler must be accessible!");
2272 * legendre_u = std::make_unique<FESeries::Legendre<2>>(
2274 * legendre_v = std::make_unique<FESeries::Legendre<2>>(
2277 * legendre_u->precalculate_all_transformation_matrices();
2278 * legendre_v->precalculate_all_transformation_matrices();
2281 *
template <
class VectorType>
2283 * compute_coefficient_decay(
const VectorType & eigenfunction,
2284 * std::vector<double> &smoothness_indicators)
2288 * Compute the coefficients
for the u and v components of the solution
2293 * smoothness_v(smoothness_indicators.size());
2305 *
for (
unsigned int i = 0; i < smoothness_indicators.size(); ++i)
2307 * smoothness_indicators[i] =
std::min(smoothness_u[i], smoothness_v[i]);
2315 *
template <
int dim>
2316 *
class LegendreIndicator
2324 *
template <
class VectorType>
2326 * estimate_smoothness(
2327 *
const std::unique_ptr<std::vector<VectorType>> &eigenfunctions,
2328 *
const unsigned int & index_of_goal,
2329 * std::vector<double> & smoothness_indicators);
2335 *
template <
int dim>
2337 * LegendreIndicator<dim>::attach_FE_info_and_initialize(
2346 *
template <
int dim>
2347 *
template <
class VectorType>
2349 * LegendreIndicator<dim>::estimate_smoothness(
2350 *
const std::unique_ptr<std::vector<VectorType>> &eigenfunctions,
2351 *
const unsigned int & index_of_goal,
2352 * std::vector<double> & smoothness_indicators)
2354 * this->
legendre.compute_coefficient_decay((*eigenfunctions)[index_of_goal],
2355 * smoothness_indicators);
2363 *
namespace Refinement
2365 *
using namespace dealii;
2366 *
using namespace Maxwell;
2368 *
template <
int dim,
class ErrorIndicator,
class RegularityIndicator>
2369 *
class Refiner :
public ErrorIndicator,
public RegularityIndicator
2372 * Refiner(
const std::string & prm_file,
2374 *
const unsigned int &min_degree,
2375 *
const unsigned int &max_degree,
2376 *
const unsigned int &starting_degree);
2379 * execute_refinement(
const double &smoothness_threshold_fraction);
2382 * output_solution()
override;
2386 * std::vector<double> smoothness_indicators;
2387 * std::ofstream eigenvalues_out;
2388 * std::ofstream error_estimate_out;
2391 *
template <
int dim,
class ErrorIndicator,
class RegularityIndicator>
2392 * Refiner<dim, ErrorIndicator, RegularityIndicator>::Refiner(
2393 *
const std::string & prm_file,
2395 *
const unsigned int &min_degree,
2396 *
const unsigned int &max_degree,
2397 *
const unsigned int &starting_degree)
2398 * : Base<dim>(prm_file, coarse_grid)
2399 * , ErrorIndicator(prm_file,
2404 * , RegularityIndicator()
2406 *
if (ErrorIndicator::name() ==
"DWR")
2408 * error_estimate_out.open(
"error_estimate.txt");
2409 * error_estimate_out << std::setprecision(20);
2412 * eigenvalues_out.open(
"eigenvalues_" + ErrorIndicator::name() +
"_out.txt");
2413 * eigenvalues_out << std::setprecision(20);
2418 * For generating samples of the curl of the electric field
2421 *
template <
int dim>
2425 * CurlPostprocessor()
2432 * std::vector<
Vector<double>> &computed_quantities)
const override
2435 * computed_quantities.size());
2436 *
for (
unsigned int p = 0; p < input_data.solution_gradients.size(); ++p)
2438 * computed_quantities[p](0) = input_data.solution_gradients[p][1][0] -
2439 * input_data.solution_gradients[p][0][1];
2451 *
template <
int dim,
class ErrorIndicator,
class RegularityIndicator>
2453 * Refiner<dim, ErrorIndicator, RegularityIndicator>::output_solution()
2455 * CurlPostprocessor<dim> curl_u;
2458 *
auto & output_dof = *(ErrorIndicator::get_primal_DoFHandler());
2461 *
for (
const auto &cell : output_dof.active_cell_iterators())
2462 * fe_degrees(cell->active_cell_index()) =
2463 * (*ErrorIndicator::get_primal_FECollection())[cell->active_fe_index()]
2465 * data_out.add_data_vector(fe_degrees,
"fe_degree");
2467 * data_out.add_data_vector(estimated_error_per_cell,
"error");
2469 *
for (
const auto &cell : output_dof.active_cell_iterators())
2471 * auto i = cell->active_cell_index();
2472 *
if (!cell->refine_flag_set() && !cell->coarsen_flag_set())
2473 * smoothness_out(i) = -1;
2475 * smoothness_out(i) = smoothness_indicators[i];
2477 * data_out.add_data_vector(smoothness_out,
"smoothness");
2478 * data_out.add_data_vector((*ErrorIndicator::get_primal_eigenfunctions())[0],
2479 * std::string(
"eigenfunction_no_") +
2481 * data_out.add_data_vector((*ErrorIndicator::get_primal_eigenfunctions())[0],
2484 * ErrorIndicator::output_eigenvalue_data(eigenvalues_out);
2485 * ErrorIndicator::output_qoi_error_estimates(error_estimate_out);
2487 * std::cout <<
"Number of DoFs: " << (this->get_primal_DoFHandler())->n_dofs()
2491 * data_out.build_patches();
2492 * std::ofstream output(
"eigenvectors-" + ErrorIndicator::name() +
"-" +
2493 * std::to_string(this->refinement_cycle) + +
".vtu");
2494 * data_out.write_vtu(output);
2503 *
template <
int dim,
class ErrorIndicator,
class RegularityIndicator>
2505 * Refiner<dim, ErrorIndicator, RegularityIndicator>::execute_refinement(
2506 *
const double &smoothness_threshold_fraction)
2510 * First initialize the RegularityIndicator...
2511 * Depending on the limits
set,
this may take a
while
2514 * std::cout <<
"Initializing RegularityIndicator..." << std::endl;
2516 * <<
"(This may take a while if the max expansion order is set too high)"
2518 * RegularityIndicator::attach_FE_info_and_initialize(
2519 * ErrorIndicator::get_FECollection(), ErrorIndicator::get_DoFHandler());
2520 * std::cout <<
"Done!" << std::endl <<
"Starting Refinement..." << std::endl;
2522 *
for (
unsigned int cycle = 0; cycle <= this->max_cycles; ++cycle)
2524 * this->set_refinement_cycle(cycle);
2525 * std::cout <<
"Cycle: " << cycle << std::endl;
2526 * ErrorIndicator::solve_problem();
2527 * this->estimated_error_per_cell.reinit(
2530 * ErrorIndicator::estimate_error(estimated_error_per_cell);
2534 * Depending on the source of the error estimation/indication, these
2535 * values might be signed, so we address that with the following
2538 *
for (
double &error_indicator : estimated_error_per_cell)
2539 * error_indicator =
std::
abs(error_indicator);
2543 * *this->
triangulation, estimated_error_per_cell, 1. / 5., 0.000);
2547 * Now get regularity indicators
2548 * For those elements which must be refined,
swap to increasing @f$p@f$
2549 * depending on the regularity threshold...
2555 * smoothness_indicators =
2557 * std::numeric_limits<double>::max());
2558 *
if (ErrorIndicator::PrimalSolver::min_degree !=
2559 * ErrorIndicator::PrimalSolver::max_degree)
2560 * RegularityIndicator::estimate_smoothness(
2561 * ErrorIndicator::get_eigenfunctions(), 0, smoothness_indicators);
2567 * this->output_solution();
2568 *
const double threshold_smoothness = smoothness_threshold_fraction;
2569 *
unsigned int num_refined = 0, num_coarsened = 0;
2570 *
if (ErrorIndicator::PrimalSolver::min_degree !=
2571 * ErrorIndicator::PrimalSolver::max_degree)
2573 *
for (
const auto &cell :
2574 * ErrorIndicator::get_DoFHandler()->active_cell_iterators())
2576 * if (cell->refine_flag_set())
2578 *
if (cell->coarsen_flag_set())
2580 *
if (cell->refine_flag_set() &&
2581 * smoothness_indicators[cell->active_cell_index()] >
2582 * threshold_smoothness &&
2583 *
static_cast<unsigned int>(cell->active_fe_index() + 1) <
2584 * ErrorIndicator::get_FECollection()->size())
2586 * cell->clear_refine_flag();
2587 * cell->set_active_fe_index(cell->active_fe_index() + 1);
2589 *
else if (cell->coarsen_flag_set() &&
2590 * smoothness_indicators[cell->active_cell_index()] <
2591 * threshold_smoothness &&
2592 * cell->active_fe_index() != 0)
2594 * cell->clear_coarsen_flag();
2596 * cell->set_active_fe_index(cell->active_fe_index() - 1);
2600 * Here we also impose a limit on how small the cells can become
2603 *
else if (cell->refine_flag_set() && cell->diameter() < 5.0e-6)
2605 * cell->clear_refine_flag();
2606 *
if (
static_cast<unsigned int>(cell->active_fe_index() + 1) <
2607 * ErrorIndicator::get_FECollection()->size())
2608 * cell->set_active_fe_index(cell->active_fe_index() + 1);
2615 * Check what the smallest
diameter is
2618 *
double min_diameter = std::numeric_limits<double>::max();
2619 *
for (
const auto &cell :
2620 * ErrorIndicator::get_DoFHandler()->active_cell_iterators())
2621 * if (cell->
diameter() < min_diameter)
2624 * std::cout <<
"Min diameter: " << min_diameter << std::endl;
2626 * ErrorIndicator::synchronize_discretization();
2628 * (this->
triangulation)->execute_coarsening_and_refinement();
2634 * main(
int argc,
char **argv)
2638 *
using namespace dealii;
2639 *
using namespace Maxwell;
2640 *
using namespace Refinement;
2641 *
using namespace ErrorIndicators;
2642 *
using namespace RegularityIndicators;
2650 * ExcMessage(
"This program can only be run in serial, use ./maxwell-hp"));
2653 * Structures::create_L_waveguide(triangulation_DWR, 2.0);
2654 * Structures::create_L_waveguide(triangulation_Kelly, 2.0);
2656 * Refiner<2, KellyErrorIndicator<2>, LegendreIndicator<2>> problem_Kelly(
2658 * triangulation_Kelly,
2663 * Refiner<2, DualWeightedResidual<2, false>, LegendreIndicator<2>>
2664 * problem_DWR(
"maxwell-hp.prm",
2665 * triangulation_DWR,
2672 * The threshold
for the
hp-decision: too small -> not enough
2673 * @f$h@f$-refinement, too large -> not enough @f$p@f$-refinement
2676 *
double smoothness_threshold = 0.75;
2678 * std::cout <<
"Executing refinement for the Kelly strategy!" << std::endl;
2679 * problem_Kelly.execute_refinement(smoothness_threshold);
2680 * std::cout <<
"...Done with Kelly refinement strategy!" << std::endl;
2681 * std::cout <<
"Executing refinement for the DWR strategy!" << std::endl;
2682 * problem_DWR.execute_refinement(smoothness_threshold);
2683 * std::cout <<
"...Done with DWR refinement strategy!" << std::endl;
2686 *
catch (std::exception &exc)
2688 * std::cerr << std::endl
2690 * <<
"----------------------------------------------------"
2692 * std::cerr <<
"Exception on processing: " << std::endl
2693 * << exc.what() << std::endl
2694 * <<
"Aborting!" << std::endl
2695 * <<
"----------------------------------------------------"
2702 * std::cerr << std::endl
2704 * <<
"----------------------------------------------------"
2706 * std::cerr <<
"Unknown exception!" << std::endl
2707 * <<
"Aborting!" << std::endl
2708 * <<
"----------------------------------------------------"
2713 * std::cout << std::endl <<
" Job done." << std::endl;
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
void attach_dof_handler(const DoFHandler< dim, spacedim > &)
DataPostprocessorScalar(const std::string &name, const UpdateFlags update_flags)
virtual void evaluate_vector_field(const DataPostprocessorInputs::Vector< dim > &input_data, std::vector< Vector< double > > &computed_quantities) const
active_cell_iterator begin_active(const unsigned int level=0) const
const FEFaceValues< dim, spacedim > & get_present_fe_values() const
const FESubfaceValues< dim, spacedim > & get_present_fe_values() const
void get_function_gradients(const ReadVector< Number > &fe_function, std::vector< Tensor< 1, spacedim, Number > > &gradients) const
const FEValues< dim, spacedim > & get_present_fe_values() const
static void estimate(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const Quadrature< dim - 1 > &quadrature, const std::map< types::boundary_id, const Function< spacedim, Number > * > &neumann_bc, const ReadVector< Number > &solution, Vector< float > &error, const ComponentMask &component_mask={}, const Function< spacedim > *coefficients=nullptr, const unsigned int n_threads=numbers::invalid_unsigned_int, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id, const types::material_id material_id=numbers::invalid_material_id, const Strategy strategy=cell_diameter_over_24)
unsigned int n_active_cells() const
void refine_global(const unsigned int times=1)
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata) override
#define DEAL_II_VERSION_GTE(major, minor, subminor)
__global__ void set(Number *val, const Number s, const size_type N)
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrow(cond, exc)
typename ActiveSelector::cell_iterator cell_iterator
typename ActiveSelector::face_iterator face_iterator
typename ActiveSelector::active_cell_iterator active_cell_iterator
void make_hanging_node_constraints(const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< number > &constraints)
void make_zero_boundary_constraints(const DoFHandler< dim, spacedim > &dof, const types::boundary_id boundary_id, AffineConstraints< number > &zero_boundary_constraints, const ComponentMask &component_mask={})
@ update_hessians
Second derivatives of shape functions.
@ update_values
Shape function values.
@ update_normal_vectors
Normal vectors.
@ update_JxW_values
Transformed quadrature weights.
@ update_gradients
Shape function gradients.
@ update_quadrature_points
Transformed quadrature points.
void refine_and_coarsen_fixed_number(Triangulation< dim, spacedim > &triangulation, const Vector< Number > &criteria, const double top_fraction_of_cells, const double bottom_fraction_of_cells, const unsigned int max_n_cells=std::numeric_limits< unsigned int >::max())
@ valid
Iterator points to a valid object.
void mass_matrix(FullMatrix< double > &M, const FEValuesBase< dim > &fe, const double factor=1.)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
FESeries::Legendre< dim, spacedim > default_fe_series(const hp::FECollection< dim, spacedim > &fe_collection, const unsigned int component=numbers::invalid_unsigned_int)
void coefficient_decay(FESeries::Legendre< dim, spacedim > &fe_legendre, const DoFHandler< dim, spacedim > &dof_handler, const VectorType &solution, Vector< float > &smoothness_indicators, const VectorTools::NormType regression_strategy=VectorTools::Linfty_norm, const double smallest_abs_coefficient=1e-10, const bool only_flagged_cells=false)
constexpr ReturnType< rank, T >::value_type & extract(T &t, const ArrayType &indices)
VectorType::value_type * end(VectorType &V)
T sum(const T &t, const MPI_Comm mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
int(& functions)(const void *v1, const void *v2)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
double legendre(unsigned int l, double x)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
void swap(SmartPointer< T, P > &t1, SmartPointer< T, Q > &t2)
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)