From 4897b2676f0cfab76a99a5b58afca96af49ed4fd Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Thu, 14 Aug 2014 08:28:08 -0500 Subject: [PATCH] Mention range-based for loops in the tutorials. --- examples/step-1/step-1.cc | 111 ++++++++++++++++++++++++-------------- examples/step-3/step-3.cc | 9 +++- 2 files changed, 77 insertions(+), 43 deletions(-) diff --git a/examples/step-1/step-1.cc b/examples/step-1/step-1.cc index 3653accf24..04e8fb1ca9 100644 --- a/examples/step-1/step-1.cc +++ b/examples/step-1/step-1.cc @@ -130,51 +130,80 @@ void second_grid () // refine the grid in five steps towards the inner circle of the domain: for (unsigned int step=0; step<5; ++step) { - // Next, we need an iterator which points to a cell and which we will - // move over all active cells one by one (active cells are those that - // are not further refined, and the only ones that can be marked for - // further refinement, obviously). By convention, we almost always use - // the names cell and endc for the iterator - // pointing to the present cell and to the one-past-the-end - // iterator: + // Next, we need an iterator that points to a cell and which we will + // move over all active cells one by one. In a sense, you can think of a + // triangulation as a collection of cells. If it was an array, you would + // just get a pointer that you move from one to the next. In + // triangulations, cells aren't stored as an array, so simple pointers + // do not work, but one can generalize pointers to iterators (see this wikipedia + // link for more information). We will then get an iterator to the + // first cell and iterate over all of the cells until we hit the last + // one. + // + // The second important piece is that we only need the active cells. + // Active cells are those that are not further refined, and the only + // ones that can be marked for further refinement, obviously. deal.II + // provides iterator categories that allow us to iterate over all + // cells (including the parent cells of active ones) or only over the + // active cells. Because we want the latter, we need to choose + // Triangulation::active_cell_iterator as data type. + // + // Finally, by convention, we almost always use the names + // cell and endc for the iterator pointing to + // the present cell and to the "one-past-the-end" iterator. This is, in + // a sense a misnomer, because the object is not really a "cell": it is + // an iterator/pointer to a cell. We should really have started to call + // these objects cell_iterator when deal.II started in + // 1998, but it is what it is. + // + // After declaring the iterator variable, the loop over all cells is + // then rather trivial, and looks like any loop involving pointers + // instead of iterators: Triangulation<2>::active_cell_iterator cell = triangulation.begin_active(), endc = triangulation.end(); - - // The loop over all cells is then rather trivial, and looks like any - // loop involving pointers instead of iterators: for (; cell!=endc; ++cell) - // Next, we want to loop over all vertices of the cells. Since we are - // in 2d, we know that each cell has exactly four vertices. However, - // instead of penning down a 4 in the loop bound, we make a first - // attempt at writing it in a dimension-independent way by which we - // find out about the number of vertices of a cell. Using the - // GeometryInfo class, we will later have an easier time getting the - // program to also run in 3d: we only have to change all occurrences - // of <2> to <3>, and do not - // have to audit our code for the hidden appearance of magic numbers - // like a 4 that needs to be replaced by an 8: - for (unsigned int v=0; - v < GeometryInfo<2>::vertices_per_cell; - ++v) - { - // If this cell is at the inner boundary, then at least one of its - // vertices must sit on the inner ring and therefore have a radial - // distance from the center of exactly 0.5, up to floating point - // accuracy. Compute this distance, and if we have found a vertex - // with this property flag this cell for later refinement. We can - // then also break the loop over all vertices and move on to the - // next cell. - const double distance_from_center - = center.distance (cell->vertex(v)); - - if (std::fabs(distance_from_center - inner_radius) < 1e-10) - { - cell->set_refine_flag (); - break; - } - } - + { + // @note Writing a loop like this requires a lot of typing, but it + // is the only way of doing it in C++98 and C++03. However, if you + // have a C++11-compliant compiler, you can also use the C++11 + // range-based for loop style that requires significantly less + // typing. Take a look at @ref CPP11 "the deal.II C++11 page" to see + // how this works. + // + // Next, we want to loop over all vertices of the cells. Since we are + // in 2d, we know that each cell has exactly four vertices. However, + // instead of penning down a 4 in the loop bound, we make a first + // attempt at writing it in a dimension-independent way by which we + // find out about the number of vertices of a cell. Using the + // GeometryInfo class, we will later have an easier time getting the + // program to also run in 3d: we only have to change all occurrences + // of <2> to <3>, and do not + // have to audit our code for the hidden appearance of magic numbers + // like a 4 that needs to be replaced by an 8: + for (unsigned int v=0; + v < GeometryInfo<2>::vertices_per_cell; + ++v) + { + // If this cell is at the inner boundary, then at least one of its + // vertices must sit on the inner ring and therefore have a radial + // distance from the center of exactly 0.5, up to floating point + // accuracy. Compute this distance, and if we have found a vertex + // with this property flag this cell for later refinement. We can + // then also break the loop over all vertices and move on to the + // next cell. + const double distance_from_center + = center.distance (cell->vertex(v)); + + if (std::fabs(distance_from_center - inner_radius) < 1e-10) + { + cell->set_refine_flag (); + break; + } + } + } + // Now that we have marked all the cells that we want refined, we let // the triangulation actually do this refinement. The function that does // so owes its long name to the fact that one can also mark cells for diff --git a/examples/step-3/step-3.cc b/examples/step-3/step-3.cc index c692a1f58f..0ca76a4654 100644 --- a/examples/step-3/step-3.cc +++ b/examples/step-3/step-3.cc @@ -356,13 +356,18 @@ void Step3::assemble_system () std::vector local_dof_indices (dofs_per_cell); // Now for the loop over all cells. We have seen before how this works, so - // this should be familiar including the conventional names for these - // variables: + // the following code should be familiar including the conventional names + // for these variables: DoFHandler<2>::active_cell_iterator cell = dof_handler.begin_active(), endc = dof_handler.end(); for (; cell!=endc; ++cell) { + // @note As already mentioned in step-1, there is a more convenient way + // of writing such loops if your compiler supports the C++11 + // standard. See @ref CPP11 "the deal.II C++11 page" to see + // how this works. + // // We are now sitting on one cell, and we would like the values and // gradients of the shape functions be computed, as well as the // determinants of the Jacobian matrices of the mapping between -- 2.39.5