From: Guido Kanschat Date: Mon, 22 Feb 2010 20:55:26 +0000 (+0000) Subject: reduce MeshWorker::loop() to a simple loop suitable for WorkStream X-Git-Tag: v8.0.0~6415 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1168bee20d43887fd75aa78e8e7d361309675bd;p=dealii.git reduce MeshWorker::loop() to a simple loop suitable for WorkStream git-svn-id: https://svn.dealii.org/trunk@20673 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/deal.II/include/numerics/mesh_worker_info.h b/deal.II/deal.II/include/numerics/mesh_worker_info.h index 8be76611c1..54c2e54564 100644 --- a/deal.II/deal.II/include/numerics/mesh_worker_info.h +++ b/deal.II/deal.II/include/numerics/mesh_worker_info.h @@ -373,6 +373,19 @@ namespace MeshWorker * Reset all the availability flags. */ void reset(); + + /** + * After all info objects have + * been filled appropriately, + * use the ASSEMBLER object + * to assemble them into the + * global data. See + * MeshWorker::Assembler for + * available classes. + */ + template + void assemble(ASSEMBLER& ass) const; + /** * The data for the cell. @@ -974,7 +987,31 @@ namespace MeshWorker exterior_face_available[i] = false; } } + + + template < int dim, int spacedim> + template + inline void + DoFInfoBox::assemble (ASSEMBLER& assembler) const + { + assembler.assemble(cell); + for (unsigned int i=0;i::faces_per_cell;++i) + { + // Only do something if data available + if (interior_face_available[i]) + { + // If both data + // available, it is an + // interior face + if (exterior_face_available[i]) + assembler.assemble(interior[i], exterior[i]); + else + assembler.assemble(interior[i]); + } + } + } + //----------------------------------------------------------------------// template diff --git a/deal.II/deal.II/include/numerics/mesh_worker_loop.h b/deal.II/deal.II/include/numerics/mesh_worker_loop.h index f489e07334..05023e5e9a 100644 --- a/deal.II/deal.II/include/numerics/mesh_worker_loop.h +++ b/deal.II/deal.II/include/numerics/mesh_worker_loop.h @@ -47,6 +47,157 @@ namespace internal namespace MeshWorker { +/** + * The function called by loop() to perform the required actions on a + * cell and its faces. The three functions cell_worker, + * boundary_worker and face_worker are the same ones + * handed to loop(). While there we only run the loop over all cells, + * here, we do a single cell and, if necessary, its faces, interior + * and boundary. + * + * Upon return, the DoFInfo objects in the DoFInfoBox are filled with + * the data computed on the cell and each of the faces. Thus, after + * the execution of this function, we are ready to call + * DoFInfoBox::assemble() to distribute the local data into global + * data. + * + * @param cell is the cell we work on + * @param dof_info is the object into which local results are + * entered. It is expected to have been set up for the right types of + * data. + * @param info is the object containing additional data only needed + * for internal processing. + * @param cell_worker defines the local action on each cell. + * @param boundary_worker defines the local action on boundary faces + * @param face_worker defines the local action on interior faces. + * @param cells_first determines, whether faces or cells are to be + * dealt with first. + * + * @author Guido Kanschat, 2010 + */ + template + void cell_action( + ITERATOR cell, + DoFInfoBox& dof_info, + INFOBOX& info, + const std_cxx1x::function&, typename INFOBOX::CellInfo &)> &cell_worker, + const std_cxx1x::function&, typename INFOBOX::FaceInfo &)> &boundary_worker, + const std_cxx1x::function&, DoFInfo&, + typename INFOBOX::FaceInfo &, + typename INFOBOX::FaceInfo &)> &face_worker, + bool cells_first = true) + { + const bool integrate_cell = (cell_worker != 0); + const bool integrate_boundary = (boundary_worker != 0); + const bool integrate_interior_face = (face_worker != 0); + + dof_info.reset(); + // Execute this, if cells + // have to be dealt with + // before faces + if (integrate_cell && cells_first) + { + dof_info.cell.reinit(cell); + info.cell.reinit(dof_info.cell); + cell_worker(dof_info.cell, info.cell); + } + + if (integrate_interior_face || integrate_boundary) + for (unsigned int face_no=0; face_no < GeometryInfo::faces_per_cell; ++face_no) + { + typename ITERATOR::AccessorType::Container::face_iterator face = cell->face(face_no); + if (cell->at_boundary(face_no)) + { + if (integrate_boundary) + { + dof_info.interior_face_available[face_no] = true; + dof_info.interior[face_no].reinit(cell, face, face_no); + info.boundary.reinit(dof_info.interior[face_no]); + boundary_worker(dof_info.interior[face_no], info.boundary); + } + } + else if (integrate_interior_face) + { + // Interior face + typename ITERATOR::AccessorType::Container::cell_iterator + neighbor = cell->neighbor(face_no); + + // Deal with + // refinement edges + // from the refined + // side. Assuming + // one-irregular + // meshes, this + // situation should + // only occur if + // both cells are + // active. + if (neighbor->level() < cell->level()) + { + Assert(!cell->has_children(), ExcInternalError()); + Assert(!neighbor->has_children(), ExcInternalError()); + + std::pair neighbor_face_no + = cell->neighbor_of_coarser_neighbor(face_no); + typename ITERATOR::AccessorType::Container::face_iterator nface + = neighbor->face(neighbor_face_no.first); + + dof_info.interior_face_available[face_no] = true; + dof_info.exterior_face_available[face_no] = true; + dof_info.interior[face_no].reinit(cell, face, face_no); + info.face.reinit(dof_info.interior[face_no]); + dof_info.exterior[face_no].reinit( + neighbor, nface, neighbor_face_no.first, neighbor_face_no.second); + info.subface.reinit(dof_info.exterior[face_no]); + + face_worker(dof_info.interior[face_no], dof_info.exterior[face_no], + info.face, info.subface); + } + else + { + // Neighbor is + // on same + // level, but + // only do this + // from one side. + if (neighbor < cell) continue; + + // If iterator + // is active + // and neighbor + // is refined, + // skip + // internal face. + if (internal::is_active_iterator(cell) && neighbor->has_children()) + continue; + + unsigned int neighbor_face_no = cell->neighbor_of_neighbor(face_no); + Assert (neighbor->face(neighbor_face_no) == face, ExcInternalError()); + // Regular interior face + dof_info.interior_face_available[face_no] = true; + dof_info.exterior_face_available[face_no] = true; + dof_info.interior[face_no].reinit(cell, face, face_no); + info.face.reinit(dof_info.interior[face_no]); + dof_info.exterior[face_no].reinit( + neighbor, neighbor->face(neighbor_face_no), neighbor_face_no); + info.neighbor.reinit(dof_info.exterior[face_no]); + + face_worker(dof_info.interior[face_no], dof_info.exterior[face_no], + info.face, info.neighbor); + } + } + } // faces + // Execute this, if faces + // have to be handled first + if (integrate_cell && !cells_first) + { + dof_info.cell.reinit(cell); + info.cell.reinit(dof_info.cell); + cell_worker(dof_info.cell, info.cell); + } + } + + /** * The main work function of this namespace. Its action consists of two * loops. @@ -81,10 +232,6 @@ namespace MeshWorker ASSEMBLER &assembler, bool cells_first = true) { - const bool integrate_cell = (cell_worker != 0); - const bool integrate_boundary = (boundary_worker != 0); - const bool integrate_interior_face = (face_worker != 0); - DoFInfoBox dof_info(dinfo); assembler.initialize_info(dof_info.cell, false); @@ -97,118 +244,8 @@ namespace MeshWorker // Loop over all cells for (ITERATOR cell = begin; cell != end; ++cell) { - // Execute this, if cells - // have to be dealt with - // before faces - if (integrate_cell && cells_first) - { - dof_info.cell.reinit(cell); - info.cell.reinit(dof_info.cell); - cell_worker(dof_info.cell, info.cell); - assembler.assemble(dof_info.cell); - } - - if (integrate_interior_face || integrate_boundary) - for (unsigned int face_no=0; face_no < GeometryInfo::faces_per_cell; ++face_no) - { - typename ITERATOR::AccessorType::Container::face_iterator face = cell->face(face_no); - if (cell->at_boundary(face_no)) - { - if (integrate_boundary) - { - dof_info.interior_face_available[face_no] = true; - dof_info.interior[face_no].reinit(cell, face, face_no); - info.boundary.reinit(dof_info.interior[face_no]); - boundary_worker(dof_info.interior[face_no], info.boundary); - assembler.assemble(dof_info.interior[face_no]); - } - } - else if (integrate_interior_face) - { - // Interior face - typename ITERATOR::AccessorType::Container::cell_iterator - neighbor = cell->neighbor(face_no); - - // Deal with - // refinement edges - // from the refined - // side. Assuming - // one-irregular - // meshes, this - // situation should - // only occur if - // both cells are - // active. - if (neighbor->level() < cell->level()) - { - Assert(!cell->has_children(), ExcInternalError()); - Assert(!neighbor->has_children(), ExcInternalError()); - - std::pair neighbor_face_no - = cell->neighbor_of_coarser_neighbor(face_no); - typename ITERATOR::AccessorType::Container::face_iterator nface - = neighbor->face(neighbor_face_no.first); - - dof_info.interior_face_available[face_no] = true; - dof_info.exterior_face_available[face_no] = true; - dof_info.interior[face_no].reinit(cell, face, face_no); - info.face.reinit(dof_info.interior[face_no]); - dof_info.exterior[face_no].reinit( - neighbor, nface, neighbor_face_no.first, neighbor_face_no.second); - info.subface.reinit(dof_info.exterior[face_no]); - - // Neighbor - // first to - // conform to - // old version - face_worker(dof_info.interior[face_no], dof_info.exterior[face_no], - info.face, info.subface); - assembler.assemble (dof_info.interior[face_no], dof_info.exterior[face_no]); - } - else - { - // Neighbor is - // on same - // level, but - // only do this - // from one side. - if (neighbor < cell) continue; - - // If iterator - // is active - // and neighbor - // is refined, - // skip - // internal face. - if (internal::is_active_iterator(cell) && neighbor->has_children()) - continue; - - unsigned int neighbor_face_no = cell->neighbor_of_neighbor(face_no); - Assert (neighbor->face(neighbor_face_no) == face, ExcInternalError()); - // Regular interior face - dof_info.interior_face_available[face_no] = true; - dof_info.exterior_face_available[face_no] = true; - dof_info.interior[face_no].reinit(cell, face, face_no); - info.face.reinit(dof_info.interior[face_no]); - dof_info.exterior[face_no].reinit( - neighbor, neighbor->face(neighbor_face_no), neighbor_face_no); - info.neighbor.reinit(dof_info.exterior[face_no]); - - face_worker(dof_info.interior[face_no], dof_info.exterior[face_no], - info.face, info.neighbor); - assembler.assemble(dof_info.interior[face_no], dof_info.exterior[face_no]); - } - } - } // faces - // Execute this, if faces - // have to be handled first - if (integrate_cell && !cells_first) - { - dof_info.cell.reinit(cell); - info.cell.reinit(dof_info.cell); - cell_worker(dof_info.cell, info.cell); - assembler.assemble(dof_info.cell); - } + cell_action(cell, dof_info, info, cell_worker, boundary_worker, face_worker, cells_first); + dof_info.assemble(assembler); } }