12 #ifndef ProjectHgradToHcurl_H__
13 #define ProjectHgradToHcurl_H__
15 #include <deal.II/base/timer.h>
16 #include <deal.II/base/work_stream.h>
18 #include <deal.II/grid/tria.h>
20 #include <deal.II/dofs/dof_handler.h>
21 #include <deal.II/dofs/dof_tools.h>
23 #include <deal.II/lac/full_matrix.h>
24 #include <deal.II/lac/sparse_direct.h>
26 #include <deal.II/lac/precondition.h>
27 #include <deal.II/lac/solver_cg.h>
28 #include <deal.II/lac/solver_control.h>
30 #include <deal.II/fe/fe_nedelec.h>
32 #include <deal.II/fe/fe_values.h>
33 #include <deal.II/fe/mapping_q1.h>
35 #include <deal.II/numerics/data_out.h>
36 #include <deal.II/numerics/matrix_tools.h>
37 #include <deal.II/numerics/vector_tools.h>
45 #include "constants.hpp"
46 #include "static_scalar_input.hpp"
48 #define VE scratch_data.ve
50 #define TMR(__name) TimerOutput::Scope timer_section(timer, __name)
52 using namespace dealii;
54 namespace StaticScalarSolver {
113 template<
int dim,
int stage = 1>
163 unsigned int mapping_degree,
164 const Triangulation<dim>& triangulation_Hgrad,
165 const DoFHandler<dim>& dof_handler_Hgrad,
166 const Vector<double>& solution_Hgrad,
167 const std::string fname =
"Hcurl",
168 const Function<dim>* exact_solution =
nullptr,
169 bool axisymmetric =
false,
170 bool vector_potential =
false,
171 bool print_time_tables =
false,
172 bool project_exact_solution =
false,
173 bool log_cg_convergence =
false,
174 bool write_higher_order_cells =
false);
191 return static_cast<unsigned int>(triangulation_Hgrad.n_active_cells());
199 return static_cast<unsigned int>(dof_handler_Hcurl.n_dofs());
208 system_matrix.clear();
209 system_rhs.reinit(0);
215 const Triangulation<dim>&
get_tria()
const {
return triangulation_Hgrad; }
250 void compute_error_norms();
251 void project_exact_solution_fcn();
253 const std::string fname;
255 const DoFHandler<dim>& dof_handler_Hgrad;
256 const Vector<double>& solution_Hgrad;
258 const Triangulation<dim>& triangulation_Hgrad;
259 const FE_Nedelec<dim> fe_Hcurl;
260 DoFHandler<dim> dof_handler_Hcurl;
262 SparsityPattern sparsity_pattern;
263 SparseMatrix<double> system_matrix;
265 Vector<double> solution_Hcurl;
266 Vector<double> system_rhs;
268 Vector<double> projected_exact_solution;
270 AffineConstraints<double> constraints;
272 const Function<dim>* exact_solution;
274 const unsigned int mapping_degree;
275 const bool axisymmetric;
276 const bool vector_potential;
277 const bool project_exact_solution;
278 const bool log_cg_convergence;
279 const bool write_higher_order_cells;
281 Vector<double> L2_per_cell;
284 Vector<double> Linfty_per_cell;
294 using IteratorTuple =
295 std::tuple<typename DoFHandler<dim>::active_cell_iterator,
296 typename DoFHandler<dim>::active_cell_iterator>;
298 using IteratorPair = SynchronousIterators<IteratorTuple>;
300 struct AssemblyScratchData
302 AssemblyScratchData(
const FiniteElement<dim>& fe,
303 const DoFHandler<dim>& dof_hand_Hgrad,
304 const Vector<double>& dofs_Hgrad,
306 bool vector_potential,
307 unsigned int mapping_degree);
309 AssemblyScratchData(
const AssemblyScratchData& scratch_data);
311 MappingQ<dim> mapping;
313 FEValues<dim> fe_values_Hcurl;
314 FEValues<dim> fe_values_Hgrad;
316 const unsigned int dofs_per_cell;
317 const unsigned int n_q_points;
320 std::vector<double> the_coefficient_list;
322 std::vector<Tensor<1, dim>> vector_gradients;
325 std::vector<Tensor<1, dim>> nabla_xV_oopvector;
327 const FEValuesExtractors::Vector ve;
329 const DoFHandler<dim>& dof_hand_Hgrad;
330 const Vector<double>& dofs_Hgrad;
332 const bool axisymmetric;
333 const bool vector_potential;
341 struct AssemblyCopyData
343 FullMatrix<double> cell_matrix;
344 Vector<double> cell_rhs;
345 std::vector<types::global_dof_index> local_dof_indices;
348 void system_matrix_local(
const IteratorPair& IP,
349 AssemblyScratchData& scratch_data,
350 AssemblyCopyData& copy_data);
352 void copy_local_to_global(
const AssemblyCopyData& copy_data);
359 template<
int dim,
int stage>
362 unsigned int mapping_degree,
363 const Triangulation<dim>& triangulation_Hgrad,
364 const DoFHandler<dim>& dof_handler_Hgrad,
365 const Vector<double>& solution_Hgrad,
367 const Function<dim>* exact_solution,
369 bool vector_potential,
370 bool print_time_tables,
371 bool project_exact_solution,
372 bool log_cg_convergence,
373 bool write_higher_order_cells)
375 , dof_handler_Hgrad(dof_handler_Hgrad)
376 , solution_Hgrad(solution_Hgrad)
377 , triangulation_Hgrad(triangulation_Hgrad)
386 , exact_solution(exact_solution)
387 , mapping_degree(mapping_degree)
388 , axisymmetric(axisymmetric)
389 , vector_potential(vector_potential)
390 , project_exact_solution(project_exact_solution)
391 , log_cg_convergence(log_cg_convergence)
392 , write_higher_order_cells(write_higher_order_cells)
397 ExcMessage(
"The setting axisymmetric=true is only allowed if dim=2."));
400 if (vector_potential) {
403 "The setting vector_potential=true can only be used if dim=2."));
406 TimerOutput::OutputFrequency tf =
407 (print_time_tables) ? TimerOutput::summary : TimerOutput::never;
409 TimerOutput timer(std::cout, tf, TimerOutput::cpu_and_wall_times_grouped);
424 if (exact_solution) {
426 TMR(
"Compute error norms");
427 compute_error_norms();
430 if (project_exact_solution) {
432 TMR(
"Project exact solution");
433 project_exact_solution_fcn();
444 template<
int dim,
int stage>
447 std::string fname)
const
449 std::ofstream ofs_matrix(fname +
"_matrix.csv");
450 std::ofstream ofs_rhs(fname +
"_rhs.csv");
452 for (
unsigned int i = 0; i < system_matrix.m(); ++i) {
453 ofs_rhs << system_rhs(i);
454 if (i < (system_matrix.m() - 1))
457 for (
unsigned int j = 0; j < system_matrix.n(); ++j) {
458 ofs_matrix << std::scientific << std::setprecision(16)
459 << system_matrix.el(i, j);
461 if (j < (system_matrix.m() - 1))
464 if (i < (system_matrix.m() - 1))
472 template<
int dim,
int stage>
478 dof_handler_Hcurl.reinit(triangulation_Hgrad);
479 dof_handler_Hcurl.distribute_dofs(fe_Hcurl);
481 DynamicSparsityPattern dsp(dof_handler_Hcurl.n_dofs(),
482 dof_handler_Hcurl.n_dofs());
483 DoFTools::make_sparsity_pattern(dof_handler_Hcurl, dsp, constraints,
false);
485 sparsity_pattern.copy_from(dsp);
486 system_matrix.reinit(sparsity_pattern);
487 solution_Hcurl.reinit(dof_handler_Hcurl.n_dofs());
488 system_rhs.reinit(dof_handler_Hcurl.n_dofs());
490 if (project_exact_solution)
491 projected_exact_solution.reinit(dof_handler_Hcurl.n_dofs());
493 if (exact_solution) {
494 L2_per_cell.reinit(triangulation_Hgrad.n_active_cells());
495 Linfty_per_cell.reinit(triangulation_Hgrad.n_active_cells());
499 template<
int dim,
int stage>
501 ProjectHgradToHcurl<dim, stage>::assemble()
503 WorkStream::run(IteratorPair(IteratorTuple(dof_handler_Hcurl.begin_active(),
504 dof_handler_Hgrad.begin_active())),
505 IteratorPair(IteratorTuple(dof_handler_Hcurl.end(),
506 dof_handler_Hgrad.end())),
508 &ProjectHgradToHcurl::system_matrix_local,
509 &ProjectHgradToHcurl::copy_local_to_global,
510 AssemblyScratchData(fe_Hcurl,
519 template<
int dim,
int stage>
520 ProjectHgradToHcurl<dim, stage>::AssemblyScratchData::AssemblyScratchData(
521 const FiniteElement<dim>& fe,
522 const DoFHandler<dim>& dof_hand_Hgrad,
523 const Vector<double>& dofs_Hgrad,
525 bool vector_potential,
526 unsigned int mapping_degree)
527 : mapping(mapping_degree)
529 , fe_values_Hcurl(mapping,
531 QGauss<dim>(qt.sim()),
532 update_values | update_quadrature_points |
534 , fe_values_Hgrad(mapping,
535 dof_hand_Hgrad.get_fe(),
536 QGauss<dim>(qt.sim()),
538 , dofs_per_cell(fe_values_Hcurl.dofs_per_cell)
539 , n_q_points(fe_values_Hcurl.get_quadrature().size())
540 , the_coefficient_list(n_q_points)
541 , vector_gradients(n_q_points, Tensor<1, dim>())
542 , nabla_xV_oopvector(n_q_points, Tensor<1, dim>())
544 , dof_hand_Hgrad(dof_hand_Hgrad)
545 , dofs_Hgrad(dofs_Hgrad)
546 , axisymmetric(axisymmetric)
547 , vector_potential(vector_potential)
552 template<
int dim,
int stage>
553 ProjectHgradToHcurl<dim, stage>::AssemblyScratchData::AssemblyScratchData(
554 const AssemblyScratchData& scratch_data)
555 : mapping(scratch_data.mapping.get_degree())
556 , qt(scratch_data.qt)
557 , fe_values_Hcurl(mapping,
558 scratch_data.fe_values_Hcurl.get_fe(),
559 scratch_data.fe_values_Hcurl.get_quadrature(),
560 update_values | update_quadrature_points |
562 , fe_values_Hgrad(mapping,
563 scratch_data.fe_values_Hgrad.get_fe(),
564 scratch_data.fe_values_Hgrad.get_quadrature(),
566 , dofs_per_cell(fe_values_Hcurl.dofs_per_cell)
567 , n_q_points(fe_values_Hcurl.get_quadrature().size())
568 , the_coefficient_list(n_q_points)
569 , vector_gradients(n_q_points, Tensor<1, dim>())
570 , nabla_xV_oopvector(n_q_points, Tensor<1, dim>())
572 , dof_hand_Hgrad(scratch_data.dof_hand_Hgrad)
573 , dofs_Hgrad(scratch_data.dofs_Hgrad)
574 , axisymmetric(scratch_data.axisymmetric)
575 , vector_potential(scratch_data.vector_potential)
580 template<
int dim,
int stage>
582 ProjectHgradToHcurl<dim, stage>::system_matrix_local(
583 const IteratorPair& IP,
584 AssemblyScratchData& scratch_data,
585 AssemblyCopyData& copy_data)
597 copy_data.cell_matrix.reinit(scratch_data.dofs_per_cell,
598 scratch_data.dofs_per_cell);
600 copy_data.cell_rhs.reinit(scratch_data.dofs_per_cell);
602 copy_data.local_dof_indices.resize(scratch_data.dofs_per_cell);
604 scratch_data.fe_values_Hcurl.reinit(std::get<0>(*IP));
605 scratch_data.fe_values_Hgrad.reinit(std::get<1>(*IP));
607 scratch_data.fe_values_Hgrad.get_function_gradients(
608 scratch_data.dofs_Hgrad, scratch_data.vector_gradients);
610 if (scratch_data.vector_potential)
611 scratch_data.the_coefficient.value_list(
612 scratch_data.fe_values_Hcurl.get_quadrature_points(),
613 std::get<0>(*IP)->material_id(),
614 std::get<0>(*IP)->user_index(),
615 scratch_data.the_coefficient_list);
617 for (
unsigned int q_index = 0; q_index < scratch_data.n_q_points; ++q_index) {
618 scratch_data.axi_mult = 1.0;
619 if ((scratch_data.axisymmetric) && (!scratch_data.vector_potential))
620 scratch_data.axi_mult =
621 scratch_data.fe_values_Hcurl.quadrature_point(q_index)[0];
623 for (
unsigned int i = 0; i < scratch_data.dofs_per_cell; ++i) {
624 for (
unsigned int j = 0; j < scratch_data.dofs_per_cell; ++j) {
626 copy_data.cell_matrix(i, j) +=
627 scratch_data.axi_mult *
628 scratch_data.fe_values_Hcurl[VE].value(i, q_index) *
629 scratch_data.fe_values_Hcurl[VE].value(j, q_index) *
630 scratch_data.fe_values_Hcurl.JxW(q_index);
633 if (scratch_data.vector_potential)
636 scratch_data.nabla_xV_oopvector[q_index][0] =
637 scratch_data.vector_gradients[q_index][1];
640 .nabla_xV_oopvector[q_index][1] =
641 -scratch_data.vector_gradients[q_index][0];
645 tmp = scratch_data.the_coefficient_list[q_index] *
646 scratch_data.nabla_xV_oopvector[q_index] *
647 scratch_data.fe_values_Hcurl[VE].value(i, q_index) *
648 scratch_data.fe_values_Hcurl.JxW(q_index);
650 if (scratch_data.axisymmetric)
655 copy_data.cell_rhs(i) -=
656 tmp * scratch_data.fe_values_Hcurl.quadrature_point(q_index)[0];
666 copy_data.cell_rhs(i) += tmp;
672 copy_data.cell_rhs(i) -=
673 scratch_data.axi_mult *
674 scratch_data.vector_gradients[q_index] *
675 scratch_data.fe_values_Hcurl[VE].value(i, q_index) *
676 scratch_data.fe_values_Hcurl.JxW(q_index);
681 std::get<0>(*IP)->get_dof_indices(copy_data.local_dof_indices);
684 template<
int dim,
int stage>
686 ProjectHgradToHcurl<dim, stage>::copy_local_to_global(
687 const AssemblyCopyData& copy_data)
689 constraints.distribute_local_to_global(copy_data.cell_matrix,
691 copy_data.local_dof_indices,
696 template<
int dim,
int stage>
698 ProjectHgradToHcurl<dim, stage>::solve()
700 SolverControl control(
701 1000 * system_rhs.size(), 1e-12 * system_rhs.l2_norm(),
false,
false);
703 if (log_cg_convergence)
704 control.enable_history_data();
706 GrowingVectorMemory<Vector<double>> memory;
707 SolverCG<Vector<double>> cg(control, memory);
709 PreconditionJacobi<SparseMatrix<double>> preconditioner;
710 preconditioner.initialize(system_matrix, 1.0);
712 cg.solve(system_matrix, solution_Hcurl, system_rhs, preconditioner);
714 if (log_cg_convergence) {
715 const std::vector<double> history_data = control.get_history_data();
717 std::ofstream ofs(fname +
"_cg_convergence.csv");
720 for (
auto item : history_data) {
721 ofs << i <<
", " << item <<
"\n";
729 template<
int dim,
int stage>
731 ProjectHgradToHcurl<dim, stage>::save()
const
733 std::vector<std::string> solution_names(dim,
"VectorField");
734 std::vector<DataComponentInterpretation::DataComponentInterpretation>
736 DataComponentInterpretation::component_is_part_of_vector);
738 DataOut<dim> data_out;
740 data_out.add_data_vector(
741 dof_handler_Hcurl, solution_Hcurl, solution_names, interpretation);
743 if (project_exact_solution) {
744 std::vector<std::string> solution_names_ex(dim,
"VectorFieldExact");
746 data_out.add_data_vector(dof_handler_Hcurl,
747 projected_exact_solution,
752 data_out.add_data_vector(L2_per_cell,
"L2norm");
753 data_out.add_data_vector(Linfty_per_cell,
"LinftyNorm");
757 if (write_higher_order_cells) {
758 DataOutBase::VtkFlags flags;
759 flags.write_higher_order_cells =
true;
760 data_out.set_flags(flags);
762 const MappingQ<dim> mapping(mapping_degree);
764 data_out.build_patches(mapping,
766 DataOut<dim>::CurvedCellRegion::curved_inner_cells);
768 ofs.open(fname +
".vtu");
769 data_out.write_vtu(ofs);
773 data_out.build_patches();
775 ofs.open(fname +
".vtk");
776 data_out.write_vtk(ofs);
782 template<
int dim,
int stage>
784 ProjectHgradToHcurl<dim, stage>::compute_error_norms()
786 Weight<dim, stage> weight;
787 const Function<dim, double>* mask = &weight;
791 QGauss<dim> quadrature(qt.enorm());
793 VectorTools::integrate_difference(MappingQ<dim>(mapping_degree),
799 VectorTools::L2_norm,
802 L2_norm = VectorTools::compute_global_error(
803 triangulation_Hgrad, L2_per_cell, VectorTools::L2_norm);
805 VectorTools::integrate_difference(MappingQ<dim>(mapping_degree),
811 VectorTools::Linfty_norm,
815 Linfty_norm = Linfty_per_cell.linfty_norm();
818 template<
int dim,
int stage>
820 ProjectHgradToHcurl<dim, stage>::project_exact_solution_fcn()
824 AffineConstraints<double> constraints_empty;
825 constraints_empty.close();
827 VectorTools::project(MappingQ<dim>(mapping_degree),
830 QGauss<dim>(qt.sim()),
832 projected_exact_solution);
The tables that contain the amount of quadrature points used in vector problems.
unsigned int get_n_dofs() const
Returns the total amount of the degrees of freedom.
double get_L2_norm()
Returns error norm.
void save_matrix_and_rhs_to_csv(std::string fname) const
Saves the system matrix and the right-hand side into a csv file.
ProjectHgradToHcurl(unsigned int p, unsigned int mapping_degree, const Triangulation< dim > &triangulation_Hgrad, const DoFHandler< dim > &dof_handler_Hgrad, const Vector< double > &solution_Hgrad, const std::string fname="Hcurl", const Function< dim > *exact_solution=nullptr, bool axisymmetric=false, bool vector_potential=false, bool print_time_tables=false, bool project_exact_solution=false, bool log_cg_convergence=false, bool write_higher_order_cells=false)
The only constructor.
double get_Linfty_norm()
Returns error norm.
const Vector< double > & get_solution() const
Returns a reference to solution, i.e., the result of the projection.
unsigned int get_n_cells() const
Returns the number of active cells in the mesh.
const Triangulation< dim > & get_tria() const
Returns a reference to triangulation.
const DoFHandler< dim > & get_dof_handler() const
Returns a reference to dof handler associated with the Nedelec finite elements.
void clear()
Releases computer memory associated with system matrix and right-hand side.