12 #ifndef ProjectHcurlToL2_H__
13 #define ProjectHcurlToL2_H__
15 #define BOOST_ALLOW_DEPRECATED_HEADERS
17 #include <deal.II/base/timer.h>
18 #include <deal.II/base/work_stream.h>
20 #include <deal.II/grid/tria.h>
22 #include <deal.II/dofs/dof_handler.h>
23 #include <deal.II/dofs/dof_renumbering.h>
24 #include <deal.II/dofs/dof_tools.h>
26 #include <deal.II/lac/full_matrix.h>
27 #include <deal.II/lac/sparse_direct.h>
29 #include <deal.II/lac/precondition.h>
30 #include <deal.II/lac/solver_cg.h>
31 #include <deal.II/lac/solver_control.h>
33 #include <deal.II/fe/fe_dgq.h>
35 #include <deal.II/fe/fe_values.h>
36 #include <deal.II/fe/mapping_q1.h>
38 #include <deal.II/numerics/data_out.h>
39 #include <deal.II/numerics/matrix_tools.h>
40 #include <deal.II/numerics/vector_tools.h>
48 #include "constants.hpp"
49 #include "static_vector_input.hpp"
51 #define SE scratch_data.se
53 #define TMR(__name) TimerOutput::Scope timer_section(timer, __name)
55 using namespace dealii;
57 namespace StaticVectorSolver {
91 template<
int stage = 1>
136 unsigned int mapping_degree,
137 const Triangulation<2>& triangulation_Hcurl,
138 const DoFHandler<2>& dof_handler_Hcurl,
139 const Vector<double>& solution_Hcurl,
140 std::string fname =
"L2",
141 const Function<2>* exact_solution =
nullptr,
142 bool print_time_tables =
false,
143 bool project_exact_solution =
false,
144 bool log_cg_convergence =
false,
145 bool write_higher_order_cells =
false);
162 return static_cast<unsigned int>(triangulation_Hcurl.n_active_cells());
170 return static_cast<unsigned int>(dof_handler_L2.n_dofs());
179 system_matrix.clear();
180 system_rhs.reinit(0);
186 const Triangulation<2>&
get_tria()
const {
return triangulation_Hcurl; }
221 void compute_error_norms();
222 void project_exact_solution_fcn();
224 const std::string fname;
226 const DoFHandler<2>& dof_handler_Hcurl;
227 const Vector<double>& solution_Hcurl;
229 const Triangulation<2>& triangulation_Hcurl;
230 const FE_DGQ<2> fe_L2;
231 DoFHandler<2> dof_handler_L2;
233 SparsityPattern sparsity_pattern;
234 SparseMatrix<double> system_matrix;
236 Vector<double> solution_L2;
237 Vector<double> system_rhs;
239 Vector<double> projected_exact_solution;
241 AffineConstraints<double> constraints;
243 const Function<2>* exact_solution;
245 const unsigned int mapping_degree;
246 const bool project_exact_solution;
247 const bool log_cg_convergence;
248 const bool write_higher_order_cells;
250 Vector<double> L2_per_cell;
253 Vector<double> Linfty_per_cell;
263 using IteratorTuple =
264 std::tuple<typename DoFHandler<2>::active_cell_iterator,
265 typename DoFHandler<2>::active_cell_iterator>;
267 using IteratorPair = SynchronousIterators<IteratorTuple>;
269 struct AssemblyScratchData
271 AssemblyScratchData(
const FiniteElement<2>& fe,
272 const DoFHandler<2>& dof_handr_Hcurl,
273 const Vector<double>& dofs_Hcurl,
274 unsigned int mapping_degree);
276 AssemblyScratchData(
const AssemblyScratchData& scratch_data);
280 FEValues<2> fe_values_L2;
281 FEValues<2> fe_values_Hcurl;
283 const unsigned int dofs_per_cell;
284 const unsigned int n_q_points;
286 std::vector<std::vector<Tensor<1, 2>>> vector_gradients;
287 Tensor<1, 1> curl_vec_in_Hcurl;
289 const FEValuesExtractors::Scalar se;
291 const DoFHandler<2>& dof_hand_Hcurl;
292 const Vector<double>& dofs_Hcurl;
295 struct AssemblyCopyData
297 FullMatrix<double> cell_matrix;
298 Vector<double> cell_rhs;
299 std::vector<types::global_dof_index> local_dof_indices;
302 void system_matrix_local(
const IteratorPair& IP,
303 AssemblyScratchData& scratch_data,
304 AssemblyCopyData& copy_data);
306 void copy_local_to_global(
const AssemblyCopyData& copy_data);
316 unsigned int mapping_degree,
317 const Triangulation<2>& triangulation_Hcurl,
318 const DoFHandler<2>& dof_handler_Hcurl,
319 const Vector<double>& solution_Hcurl,
321 const Function<2>* exact_solution,
322 bool print_time_tables,
323 bool project_exact_solution,
324 bool log_cg_convergence,
325 bool write_higher_order_cells)
327 , dof_handler_Hcurl(dof_handler_Hcurl)
328 , solution_Hcurl(solution_Hcurl)
329 , triangulation_Hcurl(triangulation_Hcurl)
331 , exact_solution(exact_solution)
332 , mapping_degree(mapping_degree)
333 , project_exact_solution(project_exact_solution)
334 , log_cg_convergence(log_cg_convergence)
335 , write_higher_order_cells(write_higher_order_cells)
337 TimerOutput::OutputFrequency tf =
338 (print_time_tables) ? TimerOutput::summary : TimerOutput::never;
340 TimerOutput timer(std::cout, tf, TimerOutput::cpu_and_wall_times_grouped);
355 if (exact_solution) {
357 TMR(
"Compute error norms");
358 compute_error_norms();
361 if (project_exact_solution) {
363 TMR(
"Project exact solution");
364 project_exact_solution_fcn();
379 std::ofstream ofs_matrix(fname +
"_matrix.csv");
380 std::ofstream ofs_rhs(fname +
"_rhs.csv");
382 for (
unsigned int i = 0; i < system_matrix.m(); ++i) {
383 ofs_rhs << system_rhs(i);
384 if (i < (system_matrix.m() - 1))
387 for (
unsigned int j = 0; j < system_matrix.n(); ++j) {
388 ofs_matrix << std::scientific << std::setprecision(16)
389 << system_matrix.el(i, j);
391 if (j < (system_matrix.m() - 1))
394 if (i < (system_matrix.m() - 1))
408 dof_handler_L2.reinit(triangulation_Hcurl);
409 dof_handler_L2.distribute_dofs(fe_L2);
412 DynamicSparsityPattern dsp(dof_handler_L2.n_dofs(), dof_handler_L2.n_dofs());
413 DoFTools::make_sparsity_pattern(dof_handler_L2, dsp, constraints,
false);
415 sparsity_pattern.copy_from(dsp);
416 system_matrix.reinit(sparsity_pattern);
417 solution_L2.reinit(dof_handler_L2.n_dofs());
418 system_rhs.reinit(dof_handler_L2.n_dofs());
420 if (project_exact_solution)
421 projected_exact_solution.reinit(dof_handler_L2.n_dofs());
423 if (exact_solution) {
424 L2_per_cell.reinit(triangulation_Hcurl.n_active_cells());
425 Linfty_per_cell.reinit(triangulation_Hcurl.n_active_cells());
431 ProjectHcurlToL2<stage>::assemble()
434 IteratorPair(IteratorTuple(dof_handler_L2.begin_active(),
435 dof_handler_Hcurl.begin_active())),
436 IteratorPair(IteratorTuple(dof_handler_L2.end(), dof_handler_Hcurl.end())),
438 &ProjectHcurlToL2<stage>::system_matrix_local,
439 &ProjectHcurlToL2<stage>::copy_local_to_global,
441 fe_L2, dof_handler_Hcurl, solution_Hcurl, mapping_degree),
446 ProjectHcurlToL2<stage>::AssemblyScratchData::AssemblyScratchData(
447 const FiniteElement<2>& fe,
448 const DoFHandler<2>& dof_hand_Hcurl,
449 const Vector<double>& dofs_Hcurl,
450 unsigned int mapping_degree)
451 : mapping(mapping_degree)
453 , fe_values_L2(mapping,
456 update_values | update_quadrature_points | update_JxW_values)
457 , fe_values_Hcurl(mapping,
458 dof_hand_Hcurl.get_fe(),
461 , dofs_per_cell(fe_values_L2.dofs_per_cell)
462 , n_q_points(fe_values_L2.get_quadrature().size())
463 , vector_gradients(n_q_points, std::vector<Tensor<1, 2>>(2))
465 , dof_hand_Hcurl(dof_hand_Hcurl)
466 , dofs_Hcurl(dofs_Hcurl)
471 ProjectHcurlToL2<stage>::AssemblyScratchData::AssemblyScratchData(
472 const AssemblyScratchData& scratch_data)
473 : mapping(scratch_data.mapping.get_degree())
474 , qt(scratch_data.qt)
475 , fe_values_L2(mapping,
476 scratch_data.fe_values_L2.get_fe(),
477 scratch_data.fe_values_L2.get_quadrature(),
478 update_values | update_quadrature_points | update_JxW_values)
479 , fe_values_Hcurl(mapping,
480 scratch_data.fe_values_Hcurl.get_fe(),
481 scratch_data.fe_values_Hcurl.get_quadrature(),
483 , dofs_per_cell(fe_values_L2.dofs_per_cell)
484 , n_q_points(fe_values_L2.get_quadrature().size())
485 , vector_gradients(n_q_points, std::vector<Tensor<1, 2>>(2))
487 , dof_hand_Hcurl(scratch_data.dof_hand_Hcurl)
488 , dofs_Hcurl(scratch_data.dofs_Hcurl)
494 ProjectHcurlToL2<stage>::system_matrix_local(
const IteratorPair& IP,
495 AssemblyScratchData& scratch_data,
496 AssemblyCopyData& copy_data)
501 copy_data.cell_matrix.reinit(scratch_data.dofs_per_cell,
502 scratch_data.dofs_per_cell);
504 copy_data.cell_rhs.reinit(scratch_data.dofs_per_cell);
506 copy_data.local_dof_indices.resize(scratch_data.dofs_per_cell);
508 scratch_data.fe_values_L2.reinit(std::get<0>(*IP));
509 scratch_data.fe_values_Hcurl.reinit(std::get<1>(*IP));
511 scratch_data.fe_values_Hcurl.get_function_gradients(
512 scratch_data.dofs_Hcurl, scratch_data.vector_gradients);
514 for (
unsigned int q_index = 0; q_index < scratch_data.n_q_points; ++q_index) {
515 for (
unsigned int i = 0; i < scratch_data.dofs_per_cell; ++i) {
516 for (
unsigned int j = 0; j < scratch_data.dofs_per_cell; ++j) {
517 copy_data.cell_matrix(i, j) +=
518 scratch_data.fe_values_L2[SE].value(i, q_index) *
519 scratch_data.fe_values_L2[SE].value(j, q_index) *
520 scratch_data.fe_values_L2.JxW(q_index);
522 scratch_data.curl_vec_in_Hcurl[0] =
523 scratch_data.vector_gradients[q_index][1][0] -
524 scratch_data.vector_gradients[q_index][0][1];
526 copy_data.cell_rhs(i) += scratch_data.curl_vec_in_Hcurl[0] *
527 scratch_data.fe_values_L2[SE].value(i, q_index) *
528 scratch_data.fe_values_L2.JxW(q_index);
532 std::get<0>(*IP)->get_dof_indices(copy_data.local_dof_indices);
537 ProjectHcurlToL2<stage>::copy_local_to_global(
const AssemblyCopyData& copy_data)
539 constraints.distribute_local_to_global(copy_data.cell_matrix,
541 copy_data.local_dof_indices,
548 ProjectHcurlToL2<stage>::solve()
550 SolverControl control(
551 1000 * system_rhs.size(), 1e-12 * system_rhs.l2_norm(),
false,
false);
553 if (log_cg_convergence)
554 control.enable_history_data();
556 GrowingVectorMemory<Vector<double>> memory;
557 SolverCG<Vector<double>> cg(control, memory);
559 PreconditionSSOR<SparseMatrix<double>> preconditioner;
560 preconditioner.initialize(system_matrix, 1.2);
562 cg.solve(system_matrix, solution_L2, system_rhs, preconditioner);
564 if (log_cg_convergence) {
565 const std::vector<double> history_data = control.get_history_data();
567 std::ofstream ofs(fname +
"_cg_convergence.csv");
570 for (
auto item : history_data) {
571 ofs << i <<
", " << item <<
"\n";
580 ProjectHcurlToL2<stage>::save()
const
582 std::vector<std::string> solution_names(1,
"ScalarField");
583 std::vector<DataComponentInterpretation::DataComponentInterpretation>
584 data_component_interpretation(
585 1, DataComponentInterpretation::component_is_scalar);
588 data_out.attach_dof_handler(dof_handler_L2);
589 data_out.add_data_vector(solution_L2,
591 DataOut<2>::type_dof_data,
592 data_component_interpretation);
594 if (project_exact_solution && exact_solution) {
595 solution_names[0] =
"ScalarFieldExact";
597 data_out.add_data_vector(projected_exact_solution,
599 DataOut<2>::type_dof_data,
600 data_component_interpretation);
603 if (exact_solution) {
604 solution_names[0] =
"L2norm";
606 data_out.add_data_vector(L2_per_cell,
608 DataOut<2>::type_cell_data,
609 data_component_interpretation);
611 solution_names[0] =
"LinftyNorm";
613 data_out.add_data_vector(Linfty_per_cell,
615 DataOut<2>::type_cell_data,
616 data_component_interpretation);
621 if (write_higher_order_cells) {
622 DataOutBase::VtkFlags flags;
623 flags.write_higher_order_cells =
true;
624 data_out.set_flags(flags);
626 const MappingQ<2> mapping(mapping_degree);
628 data_out.build_patches(mapping,
630 DataOut<2>::CurvedCellRegion::curved_inner_cells);
632 ofs.open(fname +
".vtu");
633 data_out.write_vtu(ofs);
637 data_out.build_patches();
639 ofs.open(fname +
".vtk");
640 data_out.write_vtk(ofs);
648 ProjectHcurlToL2<stage>::compute_error_norms()
650 Weight<2, stage> weight;
651 const Function<2, double>* mask = &weight;
655 VectorTools::integrate_difference(MappingQ<2>(mapping_degree),
660 QGauss<2>(qt.enorm()),
661 VectorTools::L2_norm,
664 L2_norm = VectorTools::compute_global_error(
665 triangulation_Hcurl, L2_per_cell, VectorTools::L2_norm);
667 VectorTools::integrate_difference(MappingQ<2>(mapping_degree),
673 VectorTools::Linfty_norm,
677 Linfty_norm = Linfty_per_cell.linfty_norm();
682 ProjectHcurlToL2<stage>::project_exact_solution_fcn()
686 AffineConstraints<double> constraints_empty;
687 constraints_empty.close();
689 VectorTools::project(MappingQ<2>(mapping_degree),
694 projected_exact_solution);
The tables that contain the amount of quadrature points used in the scalar problems.
void save_matrix_and_rhs_to_csv(std::string fname) const
Saves the system matrix and the right-hand side into a csv file.
void clear()
Releases computer memory associated with system matrix and right-hand side.
const Vector< double > & get_solution() const
Returns a reference to solution, i.e., the result of the projection.
unsigned int get_n_dofs() const
Returns the total amount of the degrees of freedom.
unsigned int get_n_cells() const
Returns the number of active cells in the mesh.
const Triangulation< 2 > & get_tria() const
Returns a reference to triangulation.
double get_Linfty_norm()
Returns error norm.
const DoFHandler< 2 > & get_dof_handler() const
Returns a reference to dof handler associated with the Raviart-Thomas finite elements.
double get_L2_norm()
Returns error norm.
ProjectHcurlToL2(unsigned int p, unsigned int mapping_degree, const Triangulation< 2 > &triangulation_Hcurl, const DoFHandler< 2 > &dof_handler_Hcurl, const Vector< double > &solution_Hcurl, std::string fname="L2", const Function< 2 > *exact_solution=nullptr, bool print_time_tables=false, bool project_exact_solution=false, bool log_cg_convergence=false, bool write_higher_order_cells=false)
The only constructor.