79 *
#include <deal.II/base/function.h>
80 *
#include <deal.II/base/quadrature_lib.h>
81 *
#include <deal.II/base/timer.h>
82 *
#include <deal.II/lac/generic_linear_algebra.h>
83 *
#define FORCE_USE_OF_TRILINOS
85 *
#
if defined(DEAL_II_WITH_PETSC) && !defined(DEAL_II_PETSC_WITH_COMPLEX) && \
86 *
!(defined(DEAL_II_WITH_TRILINOS) && defined(FORCE_USE_OF_TRILINOS))
87 *
using namespace dealii::LinearAlgebraPETSc;
88 *
#define USE_PETSC_LA
89 *
#elif defined(DEAL_II_WITH_TRILINOS)
90 *
using namespace dealii::LinearAlgebraTrilinos;
92 *
#error DEAL_II_WITH_PETSC or DEAL_II_WITH_TRILINOS required
96 *
#include <deal.II/base/conditional_ostream.h>
97 *
#include <deal.II/base/index_set.h>
98 *
#include <deal.II/base/utilities.h>
99 *
#include <deal.II/distributed/grid_refinement.h>
100 *
#include <deal.II/distributed/solution_transfer.h>
101 *
#include <deal.II/distributed/tria.h>
102 *
#include <deal.II/dofs/dof_handler.h>
103 *
#include <deal.II/dofs/dof_tools.h>
104 *
#include <deal.II/fe/fe_q.h>
105 *
#include <deal.II/fe/fe_values.h>
106 *
#include <deal.II/grid/grid_generator.h>
107 *
#include <deal.II/lac/affine_constraints.h>
108 *
#include <deal.II/lac/dynamic_sparsity_pattern.h>
109 *
#include <deal.II/lac/full_matrix.h>
110 *
#include <deal.II/lac/solver_cg.h>
111 *
#include <deal.II/lac/sparsity_tools.h>
112 *
#include <deal.II/lac/vector.h>
113 *
#include <deal.II/numerics/data_out.h>
114 *
#include <deal.II/numerics/error_estimator.h>
115 *
#include <deal.II/numerics/matrix_creator.h>
116 *
#include <deal.II/numerics/matrix_tools.h>
117 *
#include <deal.II/numerics/vector_tools.h>
120 *
#include <iostream>
122 *
namespace MPIHeatEquation {
123 *
using namespace dealii;
125 *
template <
int dim>
class HeatEquation {
131 *
void setup_system();
132 *
void assemble_system(
const double &time);
133 *
void solve_time_step();
134 *
void output_results()
const;
135 *
void refine_mesh(
const unsigned int min_grid_level,
136 *
const unsigned int max_grid_level);
138 *
MPI_Comm mpi_communicator;
139 *
ConditionalOStream pcout;
140 *
TimerOutput computing_timer;
142 *
parallel::distributed::Triangulation<dim> triangulation;
144 *
DoFHandler<dim> dof_handler;
146 *
IndexSet locally_owned_dofs;
147 *
IndexSet locally_relevant_dofs;
149 *
AffineConstraints<double> constraints;
151 *
LA::MPI::SparseMatrix system_matrix;
153 *
LA::MPI::Vector locally_relevant_solution;
154 *
LA::MPI::Vector old_locally_relevant_solution;
155 *
LA::MPI::Vector system_rhs;
159 *
unsigned int timestep_number;
160 *
const double theta;
163 *
template <
int dim>
class RightHandSide :
public Function<dim> {
165 *
RightHandSide() : Function<dim>(), period(0.2) {}
167 *
virtual double value(
const Point<dim> &p,
168 *
const unsigned int component = 0)
const override;
171 *
const double period;
175 *
double RightHandSide<dim>::value(
const Point<dim> &p,
176 *
const unsigned int component)
const {
179 *
Assert(dim == 2, ExcNotImplemented());
181 *
const double time = this->
get_time();
182 *
const double point_within_period =
183 *
(time / period - std::floor(time / period));
185 *
if ((point_within_period >= 0.0) && (point_within_period <= 0.2)) {
186 *
if ((p[0] > 0.5) && (p[1] > -0.5))
190 *
}
else if ((point_within_period >= 0.5) && (point_within_period <= 0.7)) {
191 *
if ((p[0] > -0.5) && (p[1] > 0.5))
199 *
template <
int dim>
class BoundaryValues :
public Function<dim> {
201 *
virtual double value(
const Point<dim> &p,
202 *
const unsigned int component = 0)
const override;
206 *
double BoundaryValues<dim>::value(
const Point<dim> & ,
207 *
const unsigned int component)
const {
209 *
Assert(component == 0, ExcIndexRange(component, 0, 1));
215 *
HeatEquation<dim>::HeatEquation()
217 *
: mpi_communicator(MPI_COMM_WORLD),
222 *
triangulation(mpi_communicator), fe(1), dof_handler(triangulation),
223 *
time_step(1. / 500),
theta(0.5) {}
225 *
template <
int dim>
void HeatEquation<dim>::setup_system() {
226 *
TimerOutput::Scope t(computing_timer,
"setup");
228 *
dof_handler.distribute_dofs(fe);
231 *
<<
"===========================================" << std::endl
232 *
<<
" Number of active cells: "
233 *
<< triangulation.n_global_active_cells() << std::endl
234 *
<<
" Number of degrees of freedom: " << dof_handler.n_dofs()
237 *
locally_owned_dofs = dof_handler.locally_owned_dofs();
239 *
locally_relevant_solution.reinit(locally_owned_dofs, locally_relevant_dofs,
241 *
old_locally_relevant_solution.reinit(locally_owned_dofs,
242 *
locally_relevant_dofs, mpi_communicator);
243 *
system_rhs.reinit(locally_owned_dofs, mpi_communicator);
245 *
constraints.clear();
246 *
constraints.reinit(locally_owned_dofs, locally_relevant_dofs);
249 *
dof_handler, 0, Functions::ZeroFunction<dim>(), constraints);
250 *
constraints.close();
252 *
DynamicSparsityPattern dsp(locally_relevant_dofs);
255 *
dsp,locally_owned_dofs, mpi_communicator,
256 *
locally_relevant_dofs);
258 *
system_matrix.reinit(locally_owned_dofs, locally_owned_dofs, dsp,
262 *
template <
int dim>
void HeatEquation<dim>::assemble_system(
const double &time) {
263 *
TimerOutput::Scope t(computing_timer,
"assemble_system");
265 *
const QGauss<dim> quadrature_formula(fe.degree + 1);
266 *
FEValues<dim> fe_values(fe, quadrature_formula,
271 *
const unsigned int n_q_points = quadrature_formula.size();
280 *
std::vector<types::global_dof_index> local_dof_indices(
dofs_per_cell);
282 *
std::vector<double> rhs_values_old(
n_q_points);
283 *
for (
const auto &cell : dof_handler.active_cell_iterators())
284 *
if (cell->is_locally_owned())
288 *
cell_mass_matrix = 0;
289 *
cell_laplace_matrix = 0;
291 *
cell_forcing_terms = 0;
296 *
for (
const unsigned int q_point : fe_values.quadrature_point_indices()) {
297 *
for (
const unsigned int i : fe_values.dof_indices()) {
299 *
for (
const unsigned int j : fe_values.dof_indices()) {
301 *
cell_mass_matrix(i, j) += fe_values.shape_value(i, q_point) *
302 *
fe_values.shape_value(j, q_point) *
303 *
fe_values.JxW(q_point);
304 *
cell_laplace_matrix(i, j) += fe_values.shape_grad(i, q_point) *
305 *
fe_values.shape_grad(j, q_point) *
306 *
fe_values.JxW(q_point);
309 *
((fe_values.shape_value(i, q_point) *
310 *
fe_values.shape_value(j, q_point)) +
311 *
(theta * time_step * fe_values.shape_grad(i, q_point) *
312 *
fe_values.shape_grad(j, q_point))) *
313 *
fe_values.JxW(q_point);
320 * First compute M*U_old -(1-
theta)*k*A*U_old
323 *
cell->get_dof_indices(local_dof_indices);
325 *
cell->get_dof_values(old_locally_relevant_solution, old_cell_solution);
326 *
cell_mass_matrix.vmult(
cell_rhs, old_cell_solution);
327 *
cell_laplace_matrix.vmult(cell_tmp, old_cell_solution);
328 *
cell_rhs.
add(-(1 - theta) * time_step, cell_tmp);
335 *
RightHandSide<dim> rhs_function;
341 *
rhs_function.set_time(time);
342 *
rhs_function.value_list(fe_values.get_quadrature_points(), rhs_values);
343 *
for (
const unsigned int q_point : fe_values.quadrature_point_indices())
344 *
for (
const unsigned int i : fe_values.dof_indices())
346 *
(fe_values.shape_value(i, q_point) *
347 *
rhs_values[q_point] * fe_values.JxW(q_point));
351 * Adding:k*(1-
theta)*F^{n-1}
354 *
rhs_function.set_time(time - time_step);
355 *
rhs_function.value_list(fe_values.get_quadrature_points(),
357 *
for (
const unsigned int q_point : fe_values.quadrature_point_indices())
358 *
for (
const unsigned int i : fe_values.dof_indices())
360 *
(fe_values.shape_value(i, q_point) *
361 *
rhs_values_old[q_point] * fe_values.JxW(q_point));
363 *
constraints.distribute_local_to_global(
364 *
cell_matrix,
cell_rhs, local_dof_indices, system_matrix, system_rhs);
371 *
template <
int dim>
void HeatEquation<dim>::solve_time_step() {
372 *
TimerOutput::Scope t(computing_timer,
"solve");
374 *
LA::MPI::Vector completely_distributed_solution(locally_owned_dofs,
377 *
SolverControl solver_control(1000, 1e-8 * system_rhs.l2_norm());
379 *
SolverCG<LA::MPI::Vector> solver(solver_control);
381 *
LA::MPI::PreconditionAMG::AdditionalData data;
382 *
#ifdef USE_PETSC_LA
383 *
data.symmetric_operator =
true;
387 *
LA::MPI::PreconditionAMG preconditioner;
388 *
preconditioner.initialize(system_matrix, data);
390 *
solver.solve(system_matrix, completely_distributed_solution, system_rhs,
393 *
pcout <<
" Solved in " << solver_control.last_step() <<
" iterations."
396 *
constraints.distribute(completely_distributed_solution);
398 *
locally_relevant_solution = completely_distributed_solution;
401 *
template <
int dim>
void HeatEquation<dim>::output_results()
const {
402 *
DataOut<dim> data_out;
403 *
data_out.attach_dof_handler(dof_handler);
404 *
data_out.add_data_vector(locally_relevant_solution,
"T");
406 *
Vector<float> subdomain(triangulation.n_active_cells());
407 *
for (
unsigned int i = 0; i < subdomain.size(); ++i)
408 *
subdomain(i) = triangulation.locally_owned_subdomain();
409 *
data_out.add_data_vector(subdomain,
"subdomain");
411 *
data_out.build_patches();
412 *
data_out.set_flags(DataOutBase::VtkFlags(time, timestep_number));
414 *
data_out.write_vtu_with_pvtu_record(
"./",
"solution", timestep_number,
415 *
mpi_communicator, 2, 8);
419 *
void HeatEquation<dim>::refine_mesh(
const unsigned int min_grid_level,
420 *
const unsigned int max_grid_level)
423 *
TimerOutput::Scope t(computing_timer,
"refine");
424 *
Vector<float> estimated_error_per_cell(
425 *
triangulation.n_locally_owned_active_cells());
428 *
dof_handler, QGauss<dim - 1>(fe.degree + 1),
430 *
locally_relevant_solution, estimated_error_per_cell);
433 *
triangulation, estimated_error_per_cell, 0.6, 0.4);
435 *
if (triangulation.n_levels() > max_grid_level) {
436 *
for (
const auto &cell :
437 *
triangulation.active_cell_iterators_on_level(max_grid_level))
438 *
if (cell->is_locally_owned())
439 *
cell->clear_refine_flag();
441 *
for (
const auto &cell :
442 *
triangulation.active_cell_iterators_on_level(min_grid_level)) {
443 *
if (cell->is_locally_owned())
444 *
cell->clear_coarsen_flag();
450 *
LA::MPI::Vector previous_locally_relevant_solution(
451 *
locally_owned_dofs, locally_relevant_dofs, mpi_communicator);
452 *
previous_locally_relevant_solution = locally_relevant_solution;
453 *
triangulation.prepare_coarsening_and_refinement();
454 *
solution_trans.prepare_for_coarsening_and_refinement(
455 *
previous_locally_relevant_solution);
456 *
triangulation.execute_coarsening_and_refinement();
458 *
LA::MPI::Vector completely_distributed_solution(locally_owned_dofs,
461 *
solution_trans.interpolate(completely_distributed_solution);
462 *
constraints.distribute(completely_distributed_solution);
463 *
locally_relevant_solution = completely_distributed_solution;
466 *
template <
int dim>
void HeatEquation<dim>::run() {
467 *
pcout <<
"Running with "
468 *
#ifdef USE_PETSC_LA
474 *
<<
" MPI rank(s)..." << std::endl;
476 *
const unsigned int initial_global_refinement = 2;
477 *
const unsigned int n_adaptive_pre_refinement_steps = 4;
479 *
triangulation.refine_global(initial_global_refinement);
483 *
unsigned int pre_refinement_step = 0;
485 *
start_time_iteration:
488 *
timestep_number = 0;
490 *
LA::MPI::Vector completely_distributed_solution(locally_owned_dofs,
493 *
completely_distributed_solution);
494 *
old_locally_relevant_solution = completely_distributed_solution;
496 *
locally_relevant_solution = completely_distributed_solution;
499 *
TimerOutput::Scope t(computing_timer,
"output");
503 *
const double end_time = 0.5;
504 *
while (time < end_time) {
507 *
while (time <= end_time) {
513 *
pcout <<
"Time step " << timestep_number <<
" at t=" << time << std::endl;
515 *
system_rhs.reinit(locally_owned_dofs, mpi_communicator);
516 *
DynamicSparsityPattern dsp(locally_relevant_dofs);
519 *
dsp, dof_handler.locally_owned_dofs(), mpi_communicator,
520 *
locally_relevant_dofs);
521 *
system_matrix.reinit(locally_owned_dofs, locally_owned_dofs, dsp,
524 *
assemble_system(time);
528 *
TimerOutput::Scope t(computing_timer,
"output");
531 *
computing_timer.print_summary();
532 *
computing_timer.reset();
533 *
pcout << std::endl;
535 *
if ((timestep_number == 1) &&
536 *
(pre_refinement_step < n_adaptive_pre_refinement_steps)) {
537 *
refine_mesh(initial_global_refinement,
538 *
initial_global_refinement + n_adaptive_pre_refinement_steps);
539 *
++pre_refinement_step;
541 *
pcout << std::endl;
543 *
goto start_time_iteration;
544 *
}
else if ((timestep_number > 0) && (timestep_number % 5 == 0)) {
545 *
refine_mesh(initial_global_refinement,
546 *
initial_global_refinement + n_adaptive_pre_refinement_steps);
549 *
old_locally_relevant_solution = locally_relevant_solution;
554 *
int main(
int argc,
char *argv[]) {
561 *
using namespace dealii;
563 *
using namespace MPIHeatEquation;
570 *
Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);
572 *
HeatEquation<2> heat_equation_solver;
573 *
heat_equation_solver.run();
574 *
}
catch (std::exception &exc) {
575 *
std::cerr << std::endl
577 *
<<
"----------------------------------------------------"
579 *
std::cerr <<
"Exception on processing: " << std::endl
580 *
<< exc.what() << std::endl
581 *
<<
"Aborting!" << std::endl
582 *
<<
"----------------------------------------------------"
587 *
std::cerr << std::endl
589 *
<<
"----------------------------------------------------"
591 *
std::cerr <<
"Unknown exception!" << std::endl
592 *
<<
"Aborting!" << std::endl
593 *
<<
"----------------------------------------------------"
* * * struct InterferenceTaperTransform *
* * int main(int argc, char **argv)
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)
void add(const std::vector< size_type > &indices, const std::vector< OtherNumber > &values)
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
const bool IsBlockVector< VectorType >::value
void make_hanging_node_constraints(const DoFHandler< dim, spacedim > &dof_handler, AffineConstraints< number > &constraints)
void make_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern, const AffineConstraints< number > &constraints={}, const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
@ update_values
Shape function values.
@ update_JxW_values
Transformed quadrature weights.
@ update_gradients
Shape function gradients.
@ update_quadrature_points
Transformed quadrature points.
void hyper_L(Triangulation< dim > &tria, const double left=-1., const double right=1., const bool colorize=false)
void cell_matrix(FullMatrix< double > &M, const FEValuesBase< dim > &fe, const FEValuesBase< dim > &fetest, const ArrayView< const std::vector< double > > &velocity, const double factor=1.)
Tensor< 2, dim, Number > F(const Tensor< 2, dim, Number > &Grad_u)
* * * ScaleZFunction< dim, Number, components >::ScaleZFunction * component(component)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
void run(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)
void refine_and_coarsen_fixed_fraction(::Triangulation< dim, spacedim > &tria, const ::Vector< Number > &criteria, const double top_fraction_of_error, const double bottom_fraction_of_error, const VectorTools::NormType norm_type=VectorTools::L1_norm)
::SolutionTransfer< dim, VectorType, spacedim > SolutionTransfer
* const unsigned int dofs_per_cell
* * Vector< double > cell_rhs(dofs_per_cell)
* const unsigned int n_q_points