12 #ifndef ProjectHcurlToHdiv_H__
13 #define ProjectHcurlToHdiv_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_raviart_thomas.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 VE scratch_data.ve
53 #define TMR(__name) TimerOutput::Scope timer_section(timer, __name)
55 using namespace dealii;
57 namespace StaticVectorSolver {
105 template<
int stage = 1>
149 unsigned int mapping_degree,
150 const Triangulation<3>& triangulation_Hcurl,
151 const DoFHandler<3>& dof_handler_Hcurl,
152 const Vector<double>& solution_Hcurl,
153 std::string fname =
"Hdiv",
154 const Function<3>* exact_solution =
nullptr,
155 bool print_time_tables =
false,
156 bool project_exact_solution =
false,
157 bool log_cg_convergence =
false,
158 bool write_higher_order_cells =
false);
175 return static_cast<unsigned int>(triangulation_Hcurl.n_active_cells());
183 return static_cast<unsigned int>(dof_handler_Hdiv.n_dofs());
192 system_matrix.clear();
193 system_rhs.reinit(0);
199 const Triangulation<3>&
get_tria()
const {
return triangulation_Hcurl; }
234 void compute_error_norms();
235 void project_exact_solution_fcn();
237 const std::string fname;
239 const DoFHandler<3>& dof_handler_Hcurl;
240 const Vector<double>& solution_Hcurl;
242 const Triangulation<3>& triangulation_Hcurl;
243 const FE_RaviartThomas<3> fe_Hdiv;
244 DoFHandler<3> dof_handler_Hdiv;
246 SparsityPattern sparsity_pattern;
247 SparseMatrix<double> system_matrix;
249 Vector<double> solution_Hdiv;
250 Vector<double> system_rhs;
252 Vector<double> projected_exact_solution;
254 AffineConstraints<double> constraints;
256 const Function<3>* exact_solution;
258 const unsigned int mapping_degree;
259 const bool project_exact_solution;
260 const bool log_cg_convergence;
261 const bool write_higher_order_cells;
263 Vector<double> L2_per_cell;
266 Vector<double> Linfty_per_cell;
276 using IteratorTuple =
277 std::tuple<typename DoFHandler<3>::active_cell_iterator,
278 typename DoFHandler<3>::active_cell_iterator>;
280 using IteratorPair = SynchronousIterators<IteratorTuple>;
282 struct AssemblyScratchData
284 AssemblyScratchData(
const FiniteElement<3>& fe,
285 const DoFHandler<3>& dof_handr_Hcurl,
286 const Vector<double>& dofs_Hcurl,
287 unsigned int mapping_degree);
289 AssemblyScratchData(
const AssemblyScratchData& scratch_data);
293 FEValues<3> fe_values_Hdiv;
294 FEValues<3> fe_values_Hcurl;
296 const unsigned int dofs_per_cell;
297 const unsigned int n_q_points;
299 std::vector<std::vector<Tensor<1, 3>>> vector_gradients;
300 Tensor<1, 3> curl_vec_in_Hcurl;
302 const FEValuesExtractors::Vector ve;
304 const DoFHandler<3>& dof_hand_Hcurl;
305 const Vector<double>& dofs_Hcurl;
308 struct AssemblyCopyData
310 FullMatrix<double> cell_matrix;
311 Vector<double> cell_rhs;
312 std::vector<types::global_dof_index> local_dof_indices;
315 void system_matrix_local(
const IteratorPair& IP,
316 AssemblyScratchData& scratch_data,
317 AssemblyCopyData& copy_data);
319 void copy_local_to_global(
const AssemblyCopyData& copy_data);
329 unsigned int mapping_degree,
330 const Triangulation<3>& triangulation_Hcurl,
331 const DoFHandler<3>& dof_handler_Hcurl,
332 const Vector<double>& solution_Hcurl,
334 const Function<3>* exact_solution,
335 bool print_time_tables,
336 bool project_exact_solution,
337 bool log_cg_convergence,
338 bool write_higher_order_cells)
340 , dof_handler_Hcurl(dof_handler_Hcurl)
341 , solution_Hcurl(solution_Hcurl)
342 , triangulation_Hcurl(triangulation_Hcurl)
351 , exact_solution(exact_solution)
352 , mapping_degree(mapping_degree)
353 , project_exact_solution(project_exact_solution)
354 , log_cg_convergence(log_cg_convergence)
355 , write_higher_order_cells(write_higher_order_cells)
357 TimerOutput::OutputFrequency tf =
358 (print_time_tables) ? TimerOutput::summary : TimerOutput::never;
360 TimerOutput timer(std::cout, tf, TimerOutput::cpu_and_wall_times_grouped);
375 if (exact_solution) {
377 TMR(
"Compute error norms");
378 compute_error_norms();
381 if (project_exact_solution) {
383 TMR(
"Project exact solution");
384 project_exact_solution_fcn();
399 std::ofstream ofs_matrix(fname +
"_matrix.csv");
400 std::ofstream ofs_rhs(fname +
"_rhs.csv");
402 for (
unsigned int i = 0; i < system_matrix.m(); ++i) {
403 ofs_rhs << system_rhs(i);
404 if (i < (system_matrix.m() - 1))
407 for (
unsigned int j = 0; j < system_matrix.n(); ++j) {
408 ofs_matrix << std::scientific << std::setprecision(16)
409 << system_matrix.el(i, j);
411 if (j < (system_matrix.m() - 1))
414 if (i < (system_matrix.m() - 1))
428 dof_handler_Hdiv.reinit(triangulation_Hcurl);
429 dof_handler_Hdiv.distribute_dofs(fe_Hdiv);
431 DynamicSparsityPattern dsp(dof_handler_Hdiv.n_dofs(),
432 dof_handler_Hdiv.n_dofs());
433 DoFTools::make_sparsity_pattern(dof_handler_Hdiv, dsp, constraints,
false);
435 sparsity_pattern.copy_from(dsp);
436 system_matrix.reinit(sparsity_pattern);
437 solution_Hdiv.reinit(dof_handler_Hdiv.n_dofs());
438 system_rhs.reinit(dof_handler_Hdiv.n_dofs());
440 if (project_exact_solution)
441 projected_exact_solution.reinit(dof_handler_Hdiv.n_dofs());
443 if (exact_solution) {
444 L2_per_cell.reinit(triangulation_Hcurl.n_active_cells());
445 Linfty_per_cell.reinit(triangulation_Hcurl.n_active_cells());
451 ProjectHcurlToHdiv<stage>::assemble()
453 WorkStream::run(IteratorPair(IteratorTuple(dof_handler_Hdiv.begin_active(),
454 dof_handler_Hcurl.begin_active())),
455 IteratorPair(IteratorTuple(dof_handler_Hdiv.end(),
456 dof_handler_Hcurl.end())),
458 &ProjectHcurlToHdiv<stage>::system_matrix_local,
459 &ProjectHcurlToHdiv<stage>::copy_local_to_global,
461 fe_Hdiv, dof_handler_Hcurl, solution_Hcurl, mapping_degree),
466 ProjectHcurlToHdiv<stage>::AssemblyScratchData::AssemblyScratchData(
467 const FiniteElement<3>& fe,
468 const DoFHandler<3>& dof_hand_Hcurl,
469 const Vector<double>& dofs_Hcurl,
470 unsigned int mapping_degree)
471 : mapping(mapping_degree)
473 , fe_values_Hdiv(mapping,
476 update_values | update_quadrature_points | update_JxW_values)
477 , fe_values_Hcurl(mapping,
478 dof_hand_Hcurl.get_fe(),
481 , dofs_per_cell(fe_values_Hdiv.dofs_per_cell)
482 , n_q_points(fe_values_Hdiv.get_quadrature().size())
483 , vector_gradients(n_q_points, std::vector<Tensor<1, 3>>(3))
485 , dof_hand_Hcurl(dof_hand_Hcurl)
486 , dofs_Hcurl(dofs_Hcurl)
491 ProjectHcurlToHdiv<stage>::AssemblyScratchData::AssemblyScratchData(
492 const AssemblyScratchData& scratch_data)
493 : mapping(scratch_data.mapping.get_degree())
494 , qt(scratch_data.qt)
495 , fe_values_Hdiv(mapping,
496 scratch_data.fe_values_Hdiv.get_fe(),
497 scratch_data.fe_values_Hdiv.get_quadrature(),
498 update_values | update_quadrature_points | update_JxW_values)
499 , fe_values_Hcurl(mapping,
500 scratch_data.fe_values_Hcurl.get_fe(),
501 scratch_data.fe_values_Hcurl.get_quadrature(),
503 , dofs_per_cell(fe_values_Hdiv.dofs_per_cell)
504 , n_q_points(fe_values_Hdiv.get_quadrature().size())
505 , vector_gradients(n_q_points, std::vector<Tensor<1, 3>>(3))
507 , dof_hand_Hcurl(scratch_data.dof_hand_Hcurl)
508 , dofs_Hcurl(scratch_data.dofs_Hcurl)
514 ProjectHcurlToHdiv<stage>::system_matrix_local(
515 const IteratorPair& IP,
516 AssemblyScratchData& scratch_data,
517 AssemblyCopyData& copy_data)
522 copy_data.cell_matrix.reinit(scratch_data.dofs_per_cell,
523 scratch_data.dofs_per_cell);
525 copy_data.cell_rhs.reinit(scratch_data.dofs_per_cell);
527 copy_data.local_dof_indices.resize(scratch_data.dofs_per_cell);
529 scratch_data.fe_values_Hdiv.reinit(std::get<0>(*IP));
530 scratch_data.fe_values_Hcurl.reinit(std::get<1>(*IP));
532 scratch_data.fe_values_Hcurl.get_function_gradients(
533 scratch_data.dofs_Hcurl, scratch_data.vector_gradients);
535 for (
unsigned int q_index = 0; q_index < scratch_data.n_q_points; ++q_index) {
536 for (
unsigned int i = 0; i < scratch_data.dofs_per_cell; ++i) {
537 for (
unsigned int j = 0; j < scratch_data.dofs_per_cell; ++j) {
538 copy_data.cell_matrix(i, j) +=
539 scratch_data.fe_values_Hdiv[VE].value(i, q_index) *
540 scratch_data.fe_values_Hdiv[VE].value(j, q_index) *
541 scratch_data.fe_values_Hdiv.JxW(q_index);
544 scratch_data.curl_vec_in_Hcurl[0] =
545 scratch_data.vector_gradients[q_index][2][1] -
546 scratch_data.vector_gradients[q_index][1][2];
548 scratch_data.curl_vec_in_Hcurl[1] =
549 scratch_data.vector_gradients[q_index][0][2] -
550 scratch_data.vector_gradients[q_index][2][0];
552 scratch_data.curl_vec_in_Hcurl[2] =
553 scratch_data.vector_gradients[q_index][1][0] -
554 scratch_data.vector_gradients[q_index][0][1];
556 copy_data.cell_rhs(i) +=
557 scratch_data.curl_vec_in_Hcurl *
558 scratch_data.fe_values_Hdiv[VE].value(i, q_index) *
559 scratch_data.fe_values_Hdiv.JxW(q_index);
563 std::get<0>(*IP)->get_dof_indices(copy_data.local_dof_indices);
568 ProjectHcurlToHdiv<stage>::copy_local_to_global(
569 const AssemblyCopyData& copy_data)
571 constraints.distribute_local_to_global(copy_data.cell_matrix,
573 copy_data.local_dof_indices,
580 ProjectHcurlToHdiv<stage>::solve()
582 SolverControl control(
583 1000 * system_rhs.size(), 1e-12 * system_rhs.l2_norm(),
false,
false);
585 if (log_cg_convergence)
586 control.enable_history_data();
588 GrowingVectorMemory<Vector<double>> memory;
589 SolverCG<Vector<double>> cg(control, memory);
591 PreconditionSSOR<SparseMatrix<double>> preconditioner;
592 preconditioner.initialize(system_matrix, 1.2);
594 cg.solve(system_matrix, solution_Hdiv, system_rhs, preconditioner);
596 if (log_cg_convergence) {
597 const std::vector<double> history_data = control.get_history_data();
599 std::ofstream ofs(fname +
"_cg_convergence.csv");
602 for (
auto item : history_data) {
603 ofs << i <<
", " << item <<
"\n";
612 ProjectHcurlToHdiv<stage>::save()
const
614 std::vector<std::string> solution_names(3,
"VectorField");
615 std::vector<DataComponentInterpretation::DataComponentInterpretation>
616 interpretation(3, DataComponentInterpretation::component_is_part_of_vector);
620 data_out.add_data_vector(
621 dof_handler_Hdiv, solution_Hdiv, solution_names, interpretation);
623 if (project_exact_solution) {
624 std::vector<std::string> solution_names_ex(3,
"VectorFieldExact");
626 data_out.add_data_vector(dof_handler_Hdiv,
627 projected_exact_solution,
632 if (exact_solution) {
633 data_out.add_data_vector(L2_per_cell,
"L2norm");
634 data_out.add_data_vector(Linfty_per_cell,
"LinftyNorm");
639 if (write_higher_order_cells) {
640 DataOutBase::VtkFlags flags;
641 flags.write_higher_order_cells =
true;
642 data_out.set_flags(flags);
644 const MappingQ<3> mapping(mapping_degree);
646 data_out.build_patches(mapping,
648 DataOut<3>::CurvedCellRegion::curved_inner_cells);
650 ofs.open(fname +
".vtu");
651 data_out.write_vtu(ofs);
655 data_out.build_patches();
657 ofs.open(fname +
".vtk");
658 data_out.write_vtk(ofs);
666 ProjectHcurlToHdiv<stage>::compute_error_norms()
668 Weight<3, stage> weight;
669 const Function<3, double>* mask = &weight;
673 VectorTools::integrate_difference(MappingQ<3>(mapping_degree),
678 QGauss<3>(qt.enorm()),
679 VectorTools::L2_norm,
683 L2_norm = VectorTools::compute_global_error(
684 triangulation_Hcurl, L2_per_cell, VectorTools::L2_norm);
686 VectorTools::integrate_difference(MappingQ<3>(mapping_degree),
692 VectorTools::Linfty_norm,
696 Linfty_norm = Linfty_per_cell.linfty_norm();
701 ProjectHcurlToHdiv<stage>::project_exact_solution_fcn()
705 AffineConstraints<double> constraints_empty;
706 constraints_empty.close();
708 VectorTools::project(MappingQ<3>(mapping_degree),
713 projected_exact_solution);
double get_L2_norm()
Returns error norm.
unsigned int get_n_cells() const
Returns the number of active cells in the mesh.
const Triangulation< 3 > & get_tria() const
Returns a reference to triangulation.
const Vector< double > & get_solution() const
Returns a reference to solution, i.e., the result of the projection.
void save_matrix_and_rhs_to_csv(std::string fname) const
Saves the system matrix and the right-hand side into a csv file.
unsigned int get_n_dofs() const
Returns the total amount of the degrees of freedom.
double get_Linfty_norm()
Returns error norm.
const DoFHandler< 3 > & get_dof_handler() const
Returns a reference to dof handler associated with the Raviart-Thomas finite elements.
void clear()
Releases computer memory associated with system matrix and right-hand side.
ProjectHcurlToHdiv(unsigned int p, unsigned int mapping_degree, const Triangulation< 3 > &triangulation_Hcurl, const DoFHandler< 3 > &dof_handler_Hcurl, const Vector< double > &solution_Hcurl, std::string fname="Hdiv", const Function< 3 > *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.