Reference documentation for deal.II version 8.5.1
loop.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2006 - 2016 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #ifndef dealii__mesh_worker_loop_h
18 #define dealii__mesh_worker_loop_h
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/base/std_cxx11/function.h>
22 #include <deal.II/base/work_stream.h>
23 #include <deal.II/base/template_constraints.h>
24 #include <deal.II/grid/tria.h>
25 #include <deal.II/grid/filtered_iterator.h>
26 #include <deal.II/meshworker/local_integrator.h>
27 #include <deal.II/meshworker/dof_info.h>
28 #include <deal.II/meshworker/integration_info.h>
29 
30 
31 #define DEAL_II_MESHWORKER_PARALLEL 1
32 
33 DEAL_II_NAMESPACE_OPEN
34 
35 template <typename> class TriaActiveIterator;
36 
37 namespace internal
38 {
42  template <class DI>
43  inline bool is_active_iterator(const DI &)
44  {
45  return false;
46  }
47 
48  template <class ACCESSOR>
50  {
51  return true;
52  }
53 
54  template <class ACCESSOR>
55  inline bool is_active_iterator(const ::FilteredIterator<TriaActiveIterator<ACCESSOR> > &)
56  {
57  return true;
58  }
59 
60  template<int dim, class DOFINFO, class A>
61  void assemble(const MeshWorker::DoFInfoBox<dim, DOFINFO> &dinfo, A *assembler)
62  {
63  dinfo.assemble(*assembler);
64  }
65 }
66 
67 
68 
69 namespace MeshWorker
70 {
75  {
76  public:
77 
82  : own_cells(true), ghost_cells(false),
84  cells_first(true)
85  {
86  }
87 
91  bool own_cells;
97 
104  {
117  };
118 
128 
136 
137 
143  };
144 
145 
146 
174  template<class INFOBOX, class DOFINFO, int dim, int spacedim, class ITERATOR>
176  ITERATOR cell,
177  DoFInfoBox<dim, DOFINFO> &dof_info,
178  INFOBOX &info,
179  const std_cxx11::function<void (DOFINFO &, typename INFOBOX::CellInfo &)> &cell_worker,
180  const std_cxx11::function<void (DOFINFO &, typename INFOBOX::CellInfo &)> &boundary_worker,
181  const std_cxx11::function<void (DOFINFO &, DOFINFO &,
182  typename INFOBOX::CellInfo &,
183  typename INFOBOX::CellInfo &)> &face_worker,
184  const LoopControl &loop_control)
185  {
186  const bool ignore_subdomain = (cell->get_triangulation().locally_owned_subdomain()
188 
189  types::subdomain_id csid = (cell->is_level_cell())
190  ? cell->level_subdomain_id()
191  : cell->subdomain_id();
192 
193  const bool own_cell = ignore_subdomain || (csid == cell->get_triangulation().locally_owned_subdomain());
194 
195  dof_info.reset();
196 
197  if ((!ignore_subdomain) && (csid == numbers::artificial_subdomain_id))
198  return;
199 
200  dof_info.cell.reinit(cell);
201  dof_info.cell_valid = true;
202 
203  const bool integrate_cell = (cell_worker != 0);
204  const bool integrate_boundary = (boundary_worker != 0);
205  const bool integrate_interior_face = (face_worker != 0);
206 
207  if (integrate_cell)
208  info.cell.reinit(dof_info.cell);
209  // Execute this, if cells
210  // have to be dealt with
211  // before faces
212  if (integrate_cell && loop_control.cells_first &&
213  ((loop_control.own_cells && own_cell) || (loop_control.ghost_cells && !own_cell)))
214  cell_worker(dof_info.cell, info.cell);
215 
216  // Call the callback function in
217  // the info box to do
218  // computations between cell and
219  // face action.
220  info.post_cell(dof_info);
221 
222  if (integrate_interior_face || integrate_boundary)
223  for (unsigned int face_no=0; face_no < GeometryInfo<ITERATOR::AccessorType::Container::dimension>::faces_per_cell; ++face_no)
224  {
225  typename ITERATOR::AccessorType::Container::face_iterator face = cell->face(face_no);
226  if (cell->at_boundary(face_no) && !cell->has_periodic_neighbor(face_no))
227  {
228  // only integrate boundary faces of own cells
229  if (integrate_boundary && own_cell)
230  {
231  dof_info.interior_face_available[face_no] = true;
232  dof_info.interior[face_no].reinit(cell, face, face_no);
233  info.boundary.reinit(dof_info.interior[face_no]);
234  boundary_worker(dof_info.interior[face_no], info.boundary);
235  }
236  }
237  else if (integrate_interior_face)
238  {
239  // Interior face
240  TriaIterator<typename ITERATOR::AccessorType> neighbor = cell->neighbor_or_periodic_neighbor(face_no);
241 
243  if (neighbor->is_level_cell())
244  neighbid = neighbor->level_subdomain_id();
245  //subdomain id is only valid for active cells
246  else if (neighbor->active())
247  neighbid = neighbor->subdomain_id();
248 
249  const bool own_neighbor = ignore_subdomain ||
250  (neighbid == cell->get_triangulation().locally_owned_subdomain());
251 
252  // skip all faces between two ghost cells
253  if (!own_cell && !own_neighbor)
254  continue;
255 
256  // skip if the user doesn't want faces between own cells
257  if (own_cell && own_neighbor && loop_control.own_faces==LoopControl::never)
258  continue;
259 
260  // skip face to ghost
261  if (own_cell != own_neighbor && loop_control.faces_to_ghost==LoopControl::never)
262  continue;
263 
264  // Deal with refinement edges from the refined side. Assuming one-irregular
265  // meshes, this situation should only occur if both cells are active.
266  const bool periodic_neighbor = cell->has_periodic_neighbor(face_no);
267 
268  if ((!periodic_neighbor && cell->neighbor_is_coarser(face_no))
269  || (periodic_neighbor && cell->periodic_neighbor_is_coarser(face_no)))
270  {
271  Assert(!cell->has_children(), ExcInternalError());
272  Assert(!neighbor->has_children(), ExcInternalError());
273 
274  // skip if only one processor needs to assemble the face
275  // to a ghost cell and the fine cell is not ours.
276  if (!own_cell
277  && loop_control.faces_to_ghost == LoopControl::one)
278  continue;
279 
280  const std::pair<unsigned int, unsigned int> neighbor_face_no
281  = periodic_neighbor?
282  cell->periodic_neighbor_of_coarser_periodic_neighbor(face_no):
283  cell->neighbor_of_coarser_neighbor(face_no);
284  const typename ITERATOR::AccessorType::Container::face_iterator nface
285  = neighbor->face(neighbor_face_no.first);
286 
287  dof_info.interior_face_available[face_no] = true;
288  dof_info.exterior_face_available[face_no] = true;
289  dof_info.interior[face_no].reinit(cell, face, face_no);
290  info.face.reinit(dof_info.interior[face_no]);
291  dof_info.exterior[face_no].reinit(
292  neighbor, nface, neighbor_face_no.first, neighbor_face_no.second);
293  info.subface.reinit(dof_info.exterior[face_no]);
294 
295  face_worker(dof_info.interior[face_no], dof_info.exterior[face_no],
296  info.face, info.subface);
297  }
298  else
299  {
300  // If iterator is active and neighbor is refined, skip
301  // internal face.
302  if (internal::is_active_iterator(cell) && neighbor->has_children())
303  {
304  Assert(loop_control.own_faces != LoopControl::both, ExcMessage(
305  "Assembling from both sides for own_faces is not "
306  "supported with hanging nodes!"));
307  continue;
308  }
309 
310  // Now neighbor is on same level, double-check this:
311  Assert(cell->level()==neighbor->level(), ExcInternalError());
312 
313  // If we own both cells only do faces from one side (unless
314  // LoopControl says otherwise). Here, we rely on cell comparison
315  // that will look at cell->index().
316  if (own_cell && own_neighbor
317  && loop_control.own_faces == LoopControl::one
318  && (neighbor < cell))
319  continue;
320 
321  // independent of loop_control.faces_to_ghost,
322  // we only look at faces to ghost on the same level once
323  // (only where own_cell=true and own_neighbor=false)
324  if (!own_cell)
325  continue;
326 
327  // now only one processor assembles faces_to_ghost. We let the
328  // processor with the smaller (level-)subdomain id assemble the
329  // face.
330  if (own_cell && !own_neighbor
331  && loop_control.faces_to_ghost == LoopControl::one
332  && (neighbid < csid))
333  continue;
334 
335  const unsigned int neighbor_face_no = periodic_neighbor?
336  cell->periodic_neighbor_face_no(face_no):
337  cell->neighbor_face_no(face_no);
338  Assert (periodic_neighbor || neighbor->face(neighbor_face_no) == face, ExcInternalError());
339  // Regular interior face
340  dof_info.interior_face_available[face_no] = true;
341  dof_info.exterior_face_available[face_no] = true;
342  dof_info.interior[face_no].reinit(cell, face, face_no);
343  info.face.reinit(dof_info.interior[face_no]);
344  dof_info.exterior[face_no].reinit(
345  neighbor, neighbor->face(neighbor_face_no), neighbor_face_no);
346  info.neighbor.reinit(dof_info.exterior[face_no]);
347 
348  face_worker(dof_info.interior[face_no], dof_info.exterior[face_no],
349  info.face, info.neighbor);
350  }
351  }
352  } // faces
353  // Call the callback function in
354  // the info box to do
355  // computations between face and
356  // cell action.
357  info.post_faces(dof_info);
358 
359  // Execute this, if faces
360  // have to be handled first
361  if (integrate_cell && !loop_control.cells_first &&
362  ((loop_control.own_cells && own_cell) || (loop_control.ghost_cells && !own_cell)))
363  cell_worker(dof_info.cell, info.cell);
364  }
365 
366 
382  template<int dim, int spacedim, class DOFINFO, class INFOBOX, class ASSEMBLER, class ITERATOR>
383  void loop(ITERATOR begin,
384  typename identity<ITERATOR>::type end,
385  DOFINFO &dinfo,
386  INFOBOX &info,
387  const std_cxx11::function<void (DOFINFO &, typename INFOBOX::CellInfo &)> &cell_worker,
388  const std_cxx11::function<void (DOFINFO &, typename INFOBOX::CellInfo &)> &boundary_worker,
389  const std_cxx11::function<void (DOFINFO &, DOFINFO &,
390  typename INFOBOX::CellInfo &,
391  typename INFOBOX::CellInfo &)> &face_worker,
392  ASSEMBLER &assembler,
393  const LoopControl &lctrl = LoopControl())
394  {
395  DoFInfoBox<dim, DOFINFO> dof_info(dinfo);
396 
397  assembler.initialize_info(dof_info.cell, false);
398  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
399  {
400  assembler.initialize_info(dof_info.interior[i], true);
401  assembler.initialize_info(dof_info.exterior[i], true);
402  }
403 
404  // Loop over all cells
405 #ifdef DEAL_II_MESHWORKER_PARALLEL
406  WorkStream::run(begin, end,
407  std_cxx11::bind(&cell_action<INFOBOX, DOFINFO, dim, spacedim, ITERATOR>,
408  std_cxx11::_1, std_cxx11::_3, std_cxx11::_2,
409  cell_worker, boundary_worker, face_worker, lctrl),
410  std_cxx11::bind(&internal::assemble<dim,DOFINFO,ASSEMBLER>, std_cxx11::_1, &assembler),
411  info, dof_info);
412 #else
413  for (ITERATOR cell = begin; cell != end; ++cell)
414  {
415  cell_action<INFOBOX,DOFINFO,dim,spacedim>(cell, dof_info,
416  info, cell_worker,
417  boundary_worker, face_worker,
418  lctrl);
419  dof_info.assemble(assembler);
420  }
421 #endif
422  }
423 
424 
432  template<int dim, int spacedim, class ITERATOR, class ASSEMBLER>
433  void integration_loop(ITERATOR begin,
434  typename identity<ITERATOR>::type end,
435  DoFInfo<dim, spacedim> &dof_info,
437  const LocalIntegrator<dim, spacedim> &integrator,
438  ASSEMBLER &assembler,
439  const LoopControl &lctrl = LoopControl())
440  {
441  std_cxx11::function<void (DoFInfo<dim>&, IntegrationInfo<dim, spacedim>&)> cell_worker;
442  std_cxx11::function<void (DoFInfo<dim>&, IntegrationInfo<dim, spacedim>&)> boundary_worker;
443  std_cxx11::function<void (DoFInfo<dim> &, DoFInfo<dim> &,
445  IntegrationInfo<dim, spacedim> &)> face_worker;
446  if (integrator.use_cell)
447  cell_worker = std_cxx11::bind(&LocalIntegrator<dim, spacedim>::cell, &integrator, std_cxx11::_1, std_cxx11::_2);
448  if (integrator.use_boundary)
449  boundary_worker = std_cxx11::bind(&LocalIntegrator<dim, spacedim>::boundary, &integrator, std_cxx11::_1, std_cxx11::_2);
450  if (integrator.use_face)
451  face_worker = std_cxx11::bind(&LocalIntegrator<dim, spacedim>::face, &integrator, std_cxx11::_1, std_cxx11::_2, std_cxx11::_3, std_cxx11::_4);
452 
453  loop<dim, spacedim>
454  (begin, end,
455  dof_info,
456  box,
457  cell_worker,
458  boundary_worker,
459  face_worker,
460  assembler,
461  lctrl);
462  }
463 
464 }
465 
466 DEAL_II_NAMESPACE_CLOSE
467 
468 #endif
const types::subdomain_id invalid_subdomain_id
Definition: types.h:245
FaceOption own_faces
Definition: loop.h:135
bool exterior_face_available[GeometryInfo< dim >::faces_per_cell]
Definition: dof_info.h:264
static ::ExceptionBase & ExcMessage(std::string arg1)
void cell_action(ITERATOR cell, DoFInfoBox< dim, DOFINFO > &dof_info, INFOBOX &info, const std_cxx11::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &cell_worker, const std_cxx11::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &boundary_worker, const std_cxx11::function< void(DOFINFO &, DOFINFO &, typename INFOBOX::CellInfo &, typename INFOBOX::CellInfo &)> &face_worker, const LoopControl &loop_control)
Definition: loop.h:175
bool interior_face_available[GeometryInfo< dim >::faces_per_cell]
Definition: dof_info.h:258
#define Assert(cond, exc)
Definition: exceptions.h:313
bool is_active_iterator(const DI &)
Definition: loop.h:43
void loop(ITERATOR begin, typename identity< ITERATOR >::type end, DOFINFO &dinfo, INFOBOX &info, const std_cxx11::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &cell_worker, const std_cxx11::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &boundary_worker, const std_cxx11::function< void(DOFINFO &, DOFINFO &, typename INFOBOX::CellInfo &, typename INFOBOX::CellInfo &)> &face_worker, ASSEMBLER &assembler, const LoopControl &lctrl=LoopControl())
Definition: loop.h:383
void assemble(ASSEMBLER &ass) const
Definition: dof_info.h:455
unsigned int subdomain_id
Definition: types.h:42
const types::subdomain_id artificial_subdomain_id
Definition: types.h:261
DOFINFO interior[GeometryInfo< dim >::faces_per_cell]
Definition: dof_info.h:248
void run(const std::vector< std::vector< Iterator > > &colored_iterators, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length=2 *MultithreadInfo::n_threads(), const unsigned int chunk_size=8)
Definition: work_stream.h:1110
void integration_loop(ITERATOR begin, typename identity< ITERATOR >::type end, DoFInfo< dim, spacedim > &dof_info, IntegrationInfoBox< dim, spacedim > &box, const LocalIntegrator< dim, spacedim > &integrator, ASSEMBLER &assembler, const LoopControl &lctrl=LoopControl())
Definition: loop.h:433
DOFINFO exterior[GeometryInfo< dim >::faces_per_cell]
Definition: dof_info.h:252
FaceOption faces_to_ghost
Definition: loop.h:127
static ::ExceptionBase & ExcInternalError()