12 #ifndef StaticScalarSolver_H__
13 #define StaticScalarSolver_H__
15 #include <deal.II/base/exceptions.h>
16 #include <deal.II/base/function.h>
17 #include <deal.II/base/thread_management.h>
18 #include <deal.II/base/timer.h>
19 #include <deal.II/base/types.h>
20 #include <deal.II/base/work_stream.h>
22 #include <deal.II/grid/tria.h>
24 #include <deal.II/dofs/dof_handler.h>
25 #include <deal.II/dofs/dof_tools.h>
27 #include <deal.II/fe/fe_q.h>
28 #include <deal.II/fe/fe_values.h>
29 #include <deal.II/fe/mapping_q.h>
31 #include <deal.II/lac/affine_constraints.h>
32 #include <deal.II/lac/dynamic_sparsity_pattern.h>
33 #include <deal.II/lac/precondition.h>
34 #include <deal.II/lac/solver_cg.h>
35 #include <deal.II/lac/solver_control.h>
36 #include <deal.II/lac/sparse_matrix.h>
37 #include <deal.II/lac/vector.h>
39 #include <deal.II/numerics/data_out.h>
40 #include <deal.II/numerics/vector_tools.h>
41 #include <deal.II/numerics/vector_tools_common.h>
42 #include <deal.II/numerics/vector_tools_project.h>
50 #include "constants.hpp"
51 #include "static_scalar_input.hpp"
53 #define TMR(__name) TimerOutput::Scope timer_section(timer, __name)
55 using namespace dealii;
57 namespace StaticScalarSolver {
235 template<
int dim,
int stage = 1>
274 unsigned int mapping_degree,
275 unsigned int type_of_pde_rhs,
276 std::string fname =
"data",
277 const Function<dim>* exact_solution =
nullptr,
278 bool axisymmetric =
false,
279 bool vector_potential =
false,
280 bool print_time_tables =
false,
281 bool project_exact_solution =
false,
282 bool write_higher_order_cells =
false)
284 , mapping_degree(mapping_degree)
285 , type_of_pde_rhs(type_of_pde_rhs)
287 , exact_solution(exact_solution)
288 , axisymmetric(axisymmetric)
289 , vector_potential(vector_potential)
290 , print_time_tables(print_time_tables)
291 , project_exact_solution(project_exact_solution)
292 , write_higher_order_cells(write_higher_order_cells)
294 Assert(((dim == 2) || (dim == 3)), ExcInternalError());
295 Assert(p < 6, ExcInternalError());
296 Assert(type_of_pde_rhs < 4, ExcInternalError());
301 ExcMessage(
"The setting axisymmetric=true is only allowed if dim=2."));
306 "The settings axisymmetric=true and type_of_pde_rhs>1 (corresponds to \
307 the modes for computing the current vector potential) are not compatible. \
308 An out-of-plane scalar current vector potential implies that the free-current \
309 density is an in-plane vector. Strictly speaking, it is impossible to setup a \
310 curl-curl equation on an axisymmetric problem domain if the free-current density \
311 is an in-plane vector. Charge conservation will fail."));
314 if (vector_potential) {
317 "The setting vector_potential=true can only be used if dim=2."));
318 Assert(((type_of_pde_rhs == 2) || (type_of_pde_rhs == 3)),
319 ExcMessage(
"The setting vector_potential=true can only be used if \
320 type_of_pde_rhs=2 or type_of_pde_rhs=3."));
323 if ((type_of_pde_rhs == 0) || (type_of_pde_rhs == 1)) {
324 Assert(!vector_potential,
326 "The settings type_of_pde_rhs=0 and type_of_pde_rhs=1 can only \
327 be used if vector_potential=false."));
330 if ((type_of_pde_rhs == 2) || (type_of_pde_rhs == 3)) {
333 "The settings type_of_pde_rhs=2 and type_of_pde_rhs=3 can only \
334 be used if dim=2."));
335 Assert(vector_potential,
337 "The settings type_of_pde_rhs=2 and type_of_pde_rhs=3 can only \
338 be used if vector_potential=true"));
483 system_matrix.clear();
484 system_rhs.reinit(0);
490 const Triangulation<dim>&
get_tria()
const {
return triangulation; }
507 return static_cast<unsigned int>(triangulation.n_active_cells());
515 return static_cast<unsigned int>(triangulation.n_vertices());
523 return static_cast<unsigned int>(triangulation.n_used_vertices());
531 return static_cast<unsigned int>(triangulation.n_lines());
539 return static_cast<unsigned int>(dof_handler.n_dofs());
577 TimerOutput::OutputFrequency tf =
578 (print_time_tables) ? TimerOutput::summary : TimerOutput::never;
580 TimerOutput timer(std::cout, tf, TimerOutput::cpu_and_wall_times_grouped);
587 TMR(
"Fill Dirichlet stack");
588 fill_dirichlet_stack();
603 if (exact_solution) {
604 if (project_exact_solution) {
605 TMR(
"Project exact solution");
606 project_exact_solution_fcn();
610 TMR(
"Compute error norms");
611 compute_error_norms();
621 virtual ~
Solver() =
default;
696 const unsigned int mapping_degree;
697 const unsigned int type_of_pde_rhs;
698 const std::string fname;
699 const Function<dim>* exact_solution;
700 const bool axisymmetric;
701 const bool vector_potential;
702 const bool print_time_tables;
703 const bool project_exact_solution;
704 const bool write_higher_order_cells;
706 Vector<float> L2_per_cell;
707 Vector<float> Linfty_per_cell;
708 Vector<float> H1_per_cell;
716 struct AssemblyScratchData
718 AssemblyScratchData(
const FiniteElement<dim>& fe,
719 unsigned int type_of_pde_rhs,
721 bool vector_potential,
722 unsigned int mapping_degree);
724 AssemblyScratchData(
const AssemblyScratchData& scratch_data);
733 MappingQ<dim> mapping;
735 FEValues<dim> fe_values;
736 FEFaceValues<dim> fe_face_values;
738 const unsigned int dofs_per_cell;
739 const unsigned int n_q_points;
740 const unsigned int n_q_points_face;
742 std::vector<double> the_coefficient_list;
743 std::vector<double> pde_rhs_list;
744 std::vector<Tensor<1, dim>> pde_rhs_cvp_list;
745 std::vector<Tensor<1, dim>> pde_rhs_cvp_list_face;
746 std::vector<double> gamma_list;
747 std::vector<double> robin_rhs_list;
748 std::vector<double> free_surface_charge_list;
750 const unsigned int type_of_pde_rhs;
751 const bool axisymmetric;
752 const bool vector_potential;
761 bool do_Jf_on_boundary;
762 double robin_rhs_or_kappa;
765 struct AssemblyCopyData
767 FullMatrix<double> cell_matrix;
768 Vector<double> cell_rhs;
769 std::vector<types::global_dof_index> local_dof_indices;
772 void system_matrix_local(
773 const typename DoFHandler<dim>::active_cell_iterator& cell,
774 AssemblyScratchData& scratch_data,
775 AssemblyCopyData& copy_data);
777 void copy_local_to_global(
const AssemblyCopyData& copy_data);
783 template<
int dim,
int stage>
787 dof_handler.reinit(triangulation);
788 dof_handler.distribute_dofs(fe);
791 DoFTools::make_hanging_node_constraints(dof_handler, constraints);
793 #pragma GCC diagnostic push
794 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
795 for (
auto item : dirichlet_stack) {
796 Assert(item.first % 2 == 1, ExcInternalError());
798 #pragma GCC diagnostic pop
800 VectorTools::interpolate_boundary_values(
801 MappingQ<dim>(mapping_degree), dof_handler, dirichlet_stack, constraints);
805 DynamicSparsityPattern dsp(dof_handler.n_dofs(), dof_handler.n_dofs());
806 DoFTools::make_sparsity_pattern(dof_handler, dsp, constraints,
false);
808 sparsity_pattern.copy_from(dsp);
809 system_matrix.reinit(sparsity_pattern);
810 solution.reinit(dof_handler.n_dofs());
811 system_rhs.reinit(dof_handler.n_dofs());
813 if (project_exact_solution)
814 projected_exact_solution.reinit(dof_handler.n_dofs());
816 if (exact_solution) {
817 L2_per_cell.reinit(triangulation.n_active_cells());
818 H1_per_cell.reinit(triangulation.n_active_cells());
819 Linfty_per_cell.reinit(triangulation.n_active_cells());
823 template<
int dim,
int stage>
828 dof_handler.begin_active(),
831 &Solver::system_matrix_local,
832 &Solver::copy_local_to_global,
834 fe, type_of_pde_rhs, axisymmetric, vector_potential, mapping_degree),
838 template<
int dim,
int stage>
840 const FiniteElement<dim>& fe,
841 unsigned int type_of_pde_rhs,
843 bool vector_potential,
844 unsigned int mapping_degree)
845 : mapping(mapping_degree)
849 QGauss<dim>(qt.sim()),
850 update_gradients | update_values | update_quadrature_points |
852 , fe_face_values(mapping,
854 QGauss<dim - 1>(qt.sim()),
855 update_values | update_normal_vectors |
856 update_quadrature_points | update_JxW_values)
857 , dofs_per_cell(fe_values.dofs_per_cell)
858 , n_q_points(fe_values.get_quadrature().size())
859 , n_q_points_face(fe_face_values.get_quadrature().size())
860 , the_coefficient_list(n_q_points)
861 , pde_rhs_list(n_q_points)
862 , pde_rhs_cvp_list(n_q_points, Tensor<1, dim>())
863 , pde_rhs_cvp_list_face(n_q_points_face, Tensor<1, dim>())
864 , gamma_list(n_q_points_face)
865 , robin_rhs_list(n_q_points_face)
866 , free_surface_charge_list(n_q_points_face)
867 , type_of_pde_rhs(type_of_pde_rhs)
868 , axisymmetric(axisymmetric)
869 , vector_potential(vector_potential)
874 template<
int dim,
int stage>
875 Solver<dim, stage>::AssemblyScratchData::AssemblyScratchData(
876 const AssemblyScratchData& scratch_data)
877 : mapping(scratch_data.mapping.get_degree())
878 , qt(scratch_data.qt)
880 scratch_data.fe_values.get_fe(),
881 scratch_data.fe_values.get_quadrature(),
882 update_gradients | update_values | update_quadrature_points |
884 , fe_face_values(mapping,
885 scratch_data.fe_face_values.get_fe(),
886 scratch_data.fe_face_values.get_quadrature(),
887 update_values | update_normal_vectors |
888 update_quadrature_points | update_JxW_values)
889 , dofs_per_cell(fe_values.dofs_per_cell)
890 , n_q_points(fe_values.get_quadrature().size())
891 , n_q_points_face(fe_face_values.get_quadrature().size())
892 , the_coefficient_list(n_q_points)
893 , pde_rhs_list(n_q_points)
894 , pde_rhs_cvp_list(n_q_points, Tensor<1, dim>())
895 , pde_rhs_cvp_list_face(n_q_points_face, Tensor<1, dim>())
896 , gamma_list(n_q_points_face)
897 , robin_rhs_list(n_q_points_face)
898 , free_surface_charge_list(n_q_points_face)
899 , type_of_pde_rhs(scratch_data.type_of_pde_rhs)
900 , axisymmetric(scratch_data.axisymmetric)
901 , vector_potential(scratch_data.vector_potential)
906 template<
int dim,
int stage>
908 Solver<dim, stage>::system_matrix_local(
909 const typename DoFHandler<dim>::active_cell_iterator& cell,
910 AssemblyScratchData& scratch_data,
911 AssemblyCopyData& copy_data)
922 copy_data.cell_matrix.reinit(scratch_data.dofs_per_cell,
923 scratch_data.dofs_per_cell);
925 copy_data.cell_rhs.reinit(scratch_data.dofs_per_cell);
927 copy_data.local_dof_indices.resize(scratch_data.dofs_per_cell);
929 scratch_data.fe_values.reinit(cell);
931 if ((scratch_data.type_of_pde_rhs == 2) ||
932 (scratch_data.type_of_pde_rhs == 3)) {
935 for (
unsigned int q_index = 0; q_index < scratch_data.n_q_points; ++q_index)
936 scratch_data.the_coefficient_list[q_index] = 1.0;
938 scratch_data.the_coefficient.value_list(
939 scratch_data.fe_values.get_quadrature_points(),
942 scratch_data.the_coefficient_list);
945 if (scratch_data.type_of_pde_rhs == 1)
946 scratch_data.pde_rhs.value_list(
947 scratch_data.fe_values.get_quadrature_points(),
950 scratch_data.pde_rhs_list);
952 if ((scratch_data.type_of_pde_rhs == 2) ||
953 (scratch_data.type_of_pde_rhs == 3))
954 scratch_data.pde_rhs_cvp.value_list(
955 scratch_data.fe_values.get_quadrature_points(),
958 scratch_data.pde_rhs_cvp_list);
960 for (
unsigned int q_index = 0; q_index < scratch_data.n_q_points; ++q_index) {
961 if ((scratch_data.axisymmetric) && (!scratch_data.vector_potential)) {
962 scratch_data.axi_mult =
963 scratch_data.fe_values.quadrature_point(q_index)[0];
966 for (
unsigned int i = 0; i < scratch_data.dofs_per_cell; ++i) {
967 for (
unsigned int j = 0; j < scratch_data.dofs_per_cell; ++j) {
969 copy_data.cell_matrix(i, j) +=
970 scratch_data.axi_mult *
971 scratch_data.the_coefficient_list[q_index] *
972 scratch_data.fe_values.shape_grad(i, q_index) *
973 scratch_data.fe_values.shape_grad(j, q_index) *
974 scratch_data.fe_values.JxW(q_index);
977 switch (scratch_data.type_of_pde_rhs) {
980 copy_data.cell_rhs(i) = 0.0;
984 copy_data.cell_rhs(i) +=
985 scratch_data.axi_mult * scratch_data.pde_rhs_list[q_index] *
986 scratch_data.fe_values.shape_value(i, q_index) *
987 scratch_data.fe_values.JxW(q_index);
992 copy_data.cell_rhs(i) +=
993 (scratch_data.pde_rhs_cvp_list[q_index][0] *
994 scratch_data.fe_values.shape_grad(i, q_index)[1] -
995 scratch_data.pde_rhs_cvp_list[q_index][1] *
996 scratch_data.fe_values.shape_grad(i, q_index)[0]) *
997 scratch_data.fe_values.JxW(q_index);
1002 "The parameter type_of_pde_rhs equals " +
1003 std::to_string(scratch_data.type_of_pde_rhs) +
1004 ". Only the following values are allowed: 0, 1, and 2."));
1010 for (
unsigned int f = 0; f < GeometryInfo<dim>::faces_per_cell; ++f) {
1011 scratch_data.do_robin = (cell->face(f)->at_boundary() &&
1012 (cell->face(f)->boundary_id() % 2 == 0) &&
1013 (cell->face(f)->boundary_id() != 0));
1015 scratch_data.do_kappa =
1016 ((cell->user_index() > 0) && (cell->face(f)->user_index() > 0) &&
1017 (scratch_data.type_of_pde_rhs < 2));
1019 scratch_data.do_Jf_on_boundary =
1020 (cell->face(f)->at_boundary() && (scratch_data.type_of_pde_rhs == 3));
1023 !(scratch_data.do_robin && scratch_data.do_kappa),
1025 "Robin boundary condition is applied on a boundary. The surface free-current \
1026 charge, kappa_f, exists only on interfaces. No interface is a boundary. \
1027 Therefore, do_robin and do_kappa are mutually exclusive."));
1030 !(scratch_data.do_kappa && scratch_data.do_Jf_on_boundary),
1032 "When computing the current vector potential, type_of_pde = 2, J_f is \
1033 integrated over the boundary. The surface free-current charge, kappa_f \
1034 exists only on interfaces. No interface is a boundary. Therefore, \
1035 do_Jf_on_boundary and do_kappa are mutually exclusive."));
1037 if (scratch_data.do_robin || scratch_data.do_kappa ||
1038 scratch_data.do_Jf_on_boundary) {
1039 scratch_data.fe_face_values.reinit(cell, f);
1041 if (scratch_data.do_robin) {
1042 scratch_data.gamma.value_list(
1043 scratch_data.fe_face_values.get_quadrature_points(),
1044 scratch_data.fe_face_values.get_normal_vectors(),
1045 cell->face(f)->boundary_id(),
1046 cell->material_id(),
1048 cell->face(f)->user_index(),
1049 scratch_data.gamma_list);
1051 scratch_data.robin_rhs.value_list(
1052 scratch_data.fe_face_values.get_quadrature_points(),
1053 scratch_data.fe_face_values.get_normal_vectors(),
1054 cell->face(f)->boundary_id(),
1055 cell->material_id(),
1057 cell->face(f)->user_index(),
1058 scratch_data.robin_rhs_list);
1061 if (scratch_data.do_kappa)
1062 scratch_data.free_surface_charge.value_list(
1063 scratch_data.fe_face_values.get_quadrature_points(),
1064 scratch_data.fe_face_values.get_normal_vectors(),
1065 cell->material_id(),
1067 cell->face(f)->user_index(),
1068 scratch_data.free_surface_charge_list);
1070 if (scratch_data.do_Jf_on_boundary)
1071 scratch_data.pde_rhs_cvp.value_list(
1072 scratch_data.fe_face_values.get_quadrature_points(),
1073 cell->material_id(),
1075 scratch_data.pde_rhs_cvp_list_face);
1077 for (
unsigned int q_index_face = 0;
1078 q_index_face < scratch_data.n_q_points_face;
1080 if ((scratch_data.axisymmetric) && (!scratch_data.vector_potential))
1081 scratch_data.axi_mult =
1082 scratch_data.fe_face_values.quadrature_point(q_index_face)[0];
1084 for (
unsigned int i = 0; i < scratch_data.dofs_per_cell; ++i) {
1085 if (scratch_data.do_robin) {
1086 for (
unsigned int j = 0; j < scratch_data.dofs_per_cell; ++j) {
1088 copy_data.cell_matrix(i, j) +=
1089 scratch_data.axi_mult *
1090 scratch_data.gamma_list[q_index_face] *
1091 scratch_data.fe_face_values.shape_value(i,
1093 scratch_data.fe_face_values.shape_value(j,
1095 scratch_data.fe_face_values.JxW(q_index_face);
1099 if (scratch_data.do_robin || scratch_data.do_kappa) {
1100 scratch_data.robin_rhs_or_kappa = 0.0;
1103 if (scratch_data.do_robin)
1104 scratch_data.robin_rhs_or_kappa =
1105 scratch_data.robin_rhs_list[q_index_face];
1108 if (scratch_data.do_kappa)
1109 scratch_data.robin_rhs_or_kappa =
1110 scratch_data.free_surface_charge_list[q_index_face];
1116 copy_data.cell_rhs(i) +=
1117 scratch_data.axi_mult *
1118 scratch_data.robin_rhs_or_kappa *
1119 scratch_data.fe_face_values.shape_value(i, q_index_face) *
1120 scratch_data.fe_face_values.JxW(q_index_face);
1123 if (scratch_data.do_Jf_on_boundary) {
1125 copy_data.cell_rhs(i) -=
1126 scratch_data.fe_face_values.shape_value(i, q_index_face) *
1127 (scratch_data.pde_rhs_cvp_list_face[q_index_face][0] *
1128 scratch_data.fe_face_values.normal_vector(q_index_face)[1] -
1129 scratch_data.pde_rhs_cvp_list_face[q_index_face][1] *
1130 scratch_data.fe_face_values.normal_vector(
1133 scratch_data.fe_face_values.JxW(
1144 cell->get_dof_indices(copy_data.local_dof_indices);
1147 template<
int dim,
int stage>
1149 Solver<dim, stage>::copy_local_to_global(
const AssemblyCopyData& copy_data)
1151 constraints.distribute_local_to_global(copy_data.cell_matrix,
1153 copy_data.local_dof_indices,
1158 template<
int dim,
int stage>
1160 compute_L2_error_norm(
const DoFHandler<dim>& dof_handler,
1161 const Triangulation<dim>& triangulation,
1162 const Vector<double>& solution,
1163 const Function<dim>* exact_solution,
1164 Vector<float>& L2_per_cell,
1166 unsigned int mapping_degree)
1168 Weight<dim, stage> weight;
1169 const Function<dim, double>* mask = &weight;
1172 QGauss<dim> quadrature(qt.enorm());
1174 VectorTools::integrate_difference(MappingQ<dim>(mapping_degree),
1180 VectorTools::L2_norm,
1183 L2_norm = VectorTools::compute_global_error(
1184 triangulation, L2_per_cell, VectorTools::L2_norm);
1187 template<
int dim,
int stage>
1189 compute_H1_error_norm(
const DoFHandler<dim>& dof_handler,
1190 const Triangulation<dim>& triangulation,
1191 const Vector<double>& solution,
1192 const Function<dim>* exact_solution,
1193 Vector<float>& H1_per_cell,
1195 unsigned int mapping_degree)
1197 Weight<dim, stage> weight;
1198 const Function<dim, double>* mask = &weight;
1201 QGauss<dim> quadrature(qt.enorm());
1203 VectorTools::integrate_difference(MappingQ<dim>(mapping_degree),
1209 VectorTools::H1_seminorm,
1212 H1_norm = VectorTools::compute_global_error(
1213 triangulation, H1_per_cell, VectorTools::H1_seminorm);
1216 template<
int dim,
int stage>
1218 compute_Linfty_error_norm(
const DoFHandler<dim>& dof_handler,
1219 const Triangulation<dim>& triangulation,
1220 const Vector<double>& solution,
1221 const Function<dim>* exact_solution,
1222 Vector<float>& Linfty_per_cell,
1223 double& Linfty_norm,
1224 unsigned int mapping_degree)
1226 Weight<dim, stage> weight;
1227 const Function<dim, double>* mask = &weight;
1230 QGauss<dim> quadrature(qt.enorm());
1232 VectorTools::integrate_difference(MappingQ<dim>(mapping_degree),
1238 VectorTools::Linfty_norm,
1241 Linfty_norm = VectorTools::compute_global_error(
1242 triangulation, Linfty_per_cell, VectorTools::Linfty_norm);
1245 template<
int dim,
int stage>
1249 if (exact_solution) {
1250 Threads::Task<void> task_l2 =
1251 Threads::new_task(&compute_L2_error_norm<dim, stage>,
1260 Threads::Task<void> task_h1 =
1261 Threads::new_task(&compute_H1_error_norm<dim, stage>,
1270 Threads::Task<void> task_linfty =
1271 Threads::new_task(&compute_Linfty_error_norm<dim, stage>,
1282 template<
int dim,
int stage>
1288 AffineConstraints<double> constraints_empty;
1289 constraints_empty.close();
1291 VectorTools::project(MappingQ<dim>(mapping_degree),
1294 QGauss<dim>(qt.
sim()),
1296 projected_exact_solution);
1299 template<
int dim,
int stage>
1303 DataOut<dim> data_out;
1305 data_out.attach_dof_handler(dof_handler);
1306 data_out.add_data_vector(solution,
"ScalarField");
1308 if (exact_solution) {
1309 data_out.add_data_vector(L2_per_cell,
"L2norm");
1310 data_out.add_data_vector(Linfty_per_cell,
"LinftyNorm");
1311 data_out.add_data_vector(H1_per_cell,
"H1seminorm");
1313 if (project_exact_solution)
1314 data_out.add_data_vector(projected_exact_solution,
"ScalarFieldExact");
1319 if (write_higher_order_cells) {
1320 DataOutBase::VtkFlags flags;
1321 flags.write_higher_order_cells =
true;
1322 data_out.set_flags(flags);
1324 const MappingQ<dim> mapping(mapping_degree);
1326 data_out.build_patches(mapping,
1328 DataOut<dim>::CurvedCellRegion::curved_inner_cells);
1330 ofs.open(fname +
".vtu");
1331 data_out.write_vtu(ofs);
1335 data_out.build_patches();
1337 ofs.open(fname +
".vtk");
1338 data_out.write_vtk(ofs);
1344 template<
int dim,
int stage>
1348 std::ofstream ofs_matrix(fname +
"_matrix.csv");
1349 std::ofstream ofs_rhs(fname +
"_rhs.csv");
1351 for (
unsigned int i = 0; i < system_matrix.m(); ++i) {
1352 ofs_rhs << system_rhs(i);
1353 if (i < (system_matrix.m() - 1))
1356 for (
unsigned int j = 0; j < system_matrix.n(); ++j) {
1357 ofs_matrix << std::scientific << std::setprecision(16)
1358 << system_matrix.el(i, j);
1360 if (j < (system_matrix.m() - 1))
1363 if (i < (system_matrix.m() - 1))
The tables that contain the amount of quadrature points used in the scalar problems.
unsigned int sim() const
Returns the amount of quadrature points used when assembling system if linear equations.
Solves static scalar boundary value problem.
std::map< types::boundary_id, const Function< dim > * > dirichlet_stack
A map that contains pairs of boundary IDs and the corresponding Dirichlet boundary conditions.
double H1_norm
The error semi-norm.
double Linfty_norm
The error norm.
void save() const
Saves simulation results into a vtk or vtu file.
void assemble()
Assembles the system matrix and the right-hand side vector.
Triangulation< dim > triangulation
The mesh.
const Triangulation< dim > & get_tria() const
Returns a reference to triangulation.
const Vector< double > & get_solution() const
Returns a reference to the solution.
DoFHandler< dim > dof_handler
The degrees-of-freedom handler.
SparsityPattern sparsity_pattern
The sparsity pattern of the system matrix.
double get_L2_norm() const
Returns error norm.
double L2_norm
The error norm.
void clear()
Releases computer memory associated with the system matrix and right-hand side.
const DoFHandler< dim > & get_dof_handler() const
Returns a reference to dof handler.
void project_exact_solution_fcn()
Projects exact solution.
double get_H1_norm() const
Returns error norm.
Vector< double > system_rhs
The system right-hand side vector.
unsigned int get_n_dofs() const
Returns the total amount of the degrees of freedom.
Vector< double > solution
The solution vector, i.e., degrees of freedom yielded by the simulation.
double get_Linfty_norm() const
Returns error norm.
Vector< double > projected_exact_solution
The projected exact solution vector.
AffineConstraints< double > constraints
The constraints associated with the Dirichlet boundary conditions.
unsigned int get_n_cells() const
Returns the number of active cells in the mesh.
SparseMatrix< double > system_matrix
The system matrix.
void compute_error_norms()
Computes error norms.
unsigned int get_type_of_pde_rhs() const
Returns the value of type_of_pde_rhs.
virtual void solve()=0
Solves the system of linear equations.
unsigned int get_n_used_vertices() const
Returns the number of used vertices.
const FE_Q< dim > fe
The finite elements.
void save_matrix_and_rhs_to_csv(std::string fname) const
Saves the system matrix and the right-hand side into a csv file.
virtual void fill_dirichlet_stack()=0
Initializes the data member StaticScalarSolver::Solver::dirichlet_stack.
void setup()
Initializes system matrix and the right-hand side vector, etc.
unsigned int get_mapping_degree() const
Returns degree of the interpolating Lagrange polynomials used for mapping from the reference cell to ...
Solver(unsigned int p, unsigned int mapping_degree, unsigned int type_of_pde_rhs, std::string fname="data", const Function< dim > *exact_solution=nullptr, bool axisymmetric=false, bool vector_potential=false, bool print_time_tables=false, bool project_exact_solution=false, bool write_higher_order_cells=false)
The only constructor.
void run()
Runs the simulation.
virtual void make_mesh()=0
Initializes the data member StaticScalarSolver::Solver::triangulation.
unsigned int get_n_vertices() const
Returns the number of vertices.
unsigned int get_n_lines() const
Returns the number of lines.