770 *
LA::MPI::PreconditionAMG preconditioner;
771 *
preconditioner.initialize(system_matrix, data);
773 *
solver.solve(system_matrix,
778 *
pcout <<
" Solved in " << solver_control.last_step() <<
" iterations."
791 * <a name=
"LaplaceProblemrefine_grid"></a>
792 * <
h4>LaplaceProblem::refine_grid</
h4>
806 * KellyErrorEstimator class: we just give it a vector with as many elements
807 * as the local triangulation has cells (locally owned cells, ghost cells,
808 * and artificial ones), but it only fills those entries that correspond to
809 * cells that are locally owned.
813 * void LaplaceProblem<dim>::refine_grid()
815 * TimerOutput::Scope t(computing_timer, "refine");
817 * Vector<float> estimated_error_per_cell(triangulation.n_active_cells());
818 * KellyErrorEstimator<dim>::estimate(
820 * QGauss<dim - 1>(fe.degree + 1),
821 * std::map<types::boundary_id, const Function<dim> *>(),
822 * locally_relevant_solution,
823 * estimated_error_per_cell);
824 * parallel::distributed::GridRefinement::refine_and_coarsen_fixed_number(
825 * triangulation, estimated_error_per_cell, 0.3, 0.03);
826 * triangulation.execute_coarsening_and_refinement();
834 * <a name="LaplaceProblemoutput_results"></a>
835 * <h4>LaplaceProblem::output_results</h4>
839 * Compared to the corresponding function in @ref step_6 "step-6", the one here is
840 * a tad more complicated. There are two reasons: the first one is
841 * that we do not just want to output the solution but also for each
842 * cell which processor owns it (i.e. which "subdomain" it is
843 * in). Secondly, as discussed at length in @ref step_17 "step-17" and @ref step_18 "step-18",
844 * generating graphical data can be a bottleneck in
845 * parallelizing. In those two programs, we simply generate one
846 * output file per process. That worked because the
847 * parallel::shared::Triangulation cannot be used with large numbers
848 * of MPI processes anyway. But this doesn't
scale:
Creating a
872 * vector entries: we simply fill the entire vector with the number of the
873 * current MPI process (i.e. the subdomain_id of the current process); this
874 * correctly sets the values we care for, i.e. the entries that correspond
875 * to locally owned cells, while providing the wrong value for all other
876 * elements -- but these are then ignored anyway.
880 * void LaplaceProblem<dim>::output_results(const unsigned int cycle) const
882 * DataOut<dim> data_out;
883 * data_out.attach_dof_handler(dof_handler);
884 * data_out.add_data_vector(locally_relevant_solution, "u");
886 * Vector<float> subdomain(triangulation.n_active_cells());
887 * for (unsigned int i = 0; i < subdomain.size(); ++i)
888 * subdomain(i) = triangulation.locally_owned_subdomain();
889 * data_out.add_data_vector(subdomain, "subdomain");
891 * data_out.build_patches();
895 * The final step is to write this data to disk. We write up to 8 VTU files
896 * in parallel with the help of MPI-IO. Additionally a PVTU record is
897 * generated, which groups the written VTU files.
900 * data_out.write_vtu_with_pvtu_record(
901 * "./", "solution", cycle, mpi_communicator, 2, 8);
909 * <a name="LaplaceProblemrun"></a>
910 * <h4>LaplaceProblem::run</h4>
914 * The function that controls the overall behavior of the program is again
915 * like the one in @ref step_6 "step-6". The minor difference are the use of
916 * <code>pcout</code> instead of <code>std::cout</code> for output to the
917 * console (see also @ref step_17 "step-17").
921 * A functional difference to @ref step_6 "step-6" is the use of a square domain and that
922 * we start with a slightly finer mesh (5 global refinement cycles) -- there
931 *
pcout <<
"Running with "
938 *
<<
" MPI rank(s)..." << std::endl;
940 *
const unsigned int n_cycles = 8;
941 *
for (
unsigned int cycle = 0; cycle < n_cycles; ++cycle)
943 *
pcout <<
"Cycle " << cycle <<
':' << std::endl;
955 *
pcout <<
" Number of active cells: "
957 *
<<
" Number of degrees of freedom: " << dof_handler.n_dofs()
971 *
pcout << std::endl;
981 * <a name=
"main"></a>
1016 *
using namespace dealii;
1017 *
using namespace Step40;
1024 *
catch (std::exception &exc)
1026 *
std::cerr << std::endl
1028 *
<<
"----------------------------------------------------"
1030 *
std::cerr <<
"Exception on processing: " << std::endl
1031 *
<< exc.what() << std::endl
1032 *
<<
"Aborting!" << std::endl
1033 *
<<
"----------------------------------------------------"
1040 *
std::cerr << std::endl
1042 *
<<
"----------------------------------------------------"
1044 *
std::cerr <<
"Unknown exception!" << std::endl
1045 *
<<
"Aborting!" << std::endl
1046 *
<<
"----------------------------------------------------"
1066+---------------------------------------------+------------+------------+
1070+---------------------------------+-----------+------------+------------+
1072| output | 1 | 0.0189s | 11% |
1073| setup | 1 | 0.0299s | 17% |
1074| solve | 1 | 0.0419s | 24% |
1075+---------------------------------+-----------+------------+------------+
1084+---------------------------------------------+------------+------------+
1088+---------------------------------+-----------+------------+------------+
1090| output | 1 | 0.0208s | 6.4% |
1091|
refine | 1 | 0.157s | 48% |
1092| setup | 1 | 0.0452s | 14% |
1093| solve | 1 | 0.0668s | 20% |
1094+---------------------------------+-----------+------------+------------+
1123 <
img src=
"https://www.dealii.org/images/steps/developer/step-40.mesh.png" alt=
"">
1126 <
img src=
"https://www.dealii.org/images/steps/developer/step-40.solution.png" alt=
"">
1146 <
img src=
"https://www.dealii.org/images/steps/developer/step-40.strong2.png" alt=
"">
1149 <
img src=
"https://www.dealii.org/images/steps/developer/step-40.strong.png" alt=
"">
1174 <
img src=
"https://www.dealii.org/images/steps/developer/step-40.256.png" alt=
"">
1177 <
img src=
"https://www.dealii.org/images/steps/developer/step-40.4096.png" alt=
"">
1208<a name=
"extensions"></a>
1209<a name=
"Possibilitiesforextensions"></a><
h3>Possibilities
for extensions</
h3>
1241<a name=
"PlainProg"></a>
value_type * data() const noexcept
void apply(const Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type &team_member, const Kokkos::View< Number *, MemorySpace::Default::kokkos_space > shape_data, const ViewTypeIn in, ViewTypeOut out)
void hyper_cube(Triangulation< dim, spacedim > &tria, const double left=0., const double right=1., const bool colorize=false)
void refine(Triangulation< dim, spacedim > &tria, const Vector< Number > &criteria, const double threshold, const unsigned int max_to_mark=numbers::invalid_unsigned_int)
void coarsen(Triangulation< dim, spacedim > &tria, const Vector< Number > &criteria, const double threshold)
@ matrix
Contents is actually a matrix.
Point< spacedim > point(const gp_Pnt &p, const double tolerance=1e-10)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
VectorType::value_type * end(VectorType &V)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
T reduce(const T &local_value, const MPI_Comm comm, const std::function< T(const T &, const T &)> &combiner, const unsigned int root_process=0)
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)
int(&) functions(const void *v1, const void *v2)
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation