Flow123d  release_2.2.0-19-g1279b7e
dofhandler.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file dofhandler.cc
15  * @brief Declaration of class which handles the ordering of degrees of freedom (dof) and mappings between local and global dofs.
16  * @author Jan Stebel
17  */
18 
19 #include "fem/dofhandler.hh"
20 #include "fem/finite_element.hh"
21 #include "mesh/mesh.h"
22 #include "mesh/partitioning.hh"
23 #include "la/distribution.hh"
24 
25 
26 
27 
28 
29 
30 
31 //template<unsigned int dim, unsigned int spacedim> inline
32 //DOFHandler<dim,spacedim>::DOFHandler(Mesh & _mesh)
33 //: DOFHandlerBase(_mesh),
34 // finite_element(0)
35 //{
36 // object_dofs = new int**[mesh->n_elements()];
37 // for (int i=0; i<mesh->n_elements(); i++)
38 // object_dofs[i] = NULL;
39 //}
40 //
41 //
42 //template<unsigned int dim, unsigned int spacedim> inline
43 //DOFHandler<dim,spacedim>::~DOFHandler()
44 //{
45 // for (int i=0; i<mesh->n_elements(); i++)
46 // if (object_dofs[i] != NULL)
47 // {
48 // for (int j=0; j<mesh->element[i].dim(); j++)
49 // if (object_dofs[i][j] != NULL)
50 // delete[] object_dofs[i][j];
51 //
52 // delete[] object_dofs[i];
53 // }
54 // delete[] object_dofs;
55 //}
56 //
57 //
58 //template<unsigned int dim, unsigned int spacedim> inline
59 //void DOFHandler<dim,spacedim>::distribute_dofs(FiniteElement<dim,spacedim> & fe, const unsigned int offset)
60 //{
61 // // First check if dofs are already distributed.
62 // OLD_ASSERT(finite_element == 0, "Attempt to distribute DOFs multiple times!");
63 //
64 // unsigned int next_free_dof = offset;
65 // unsigned int n_obj_dofs[dim+1];
66 //
67 // finite_element = &fe;
68 // global_dof_offset = offset;
69 //
70 // for (unsigned int dm=0; dm <= dim; dm++)
71 // {
72 // n_obj_dofs[dm] = 0;
73 // for (unsigned int m=0; m<dof_multiplicities.size(); m++)
74 // n_obj_dofs[dm] += fe.n_object_dofs(dm, dof_multiplicities[m])*dof_multiplicities[m];
75 // }
76 //
77 // // Broadcast partition of elements to all processes.
78 // int *loc_part;
79 // int myp = mesh->get_part()->get_init_distr()->myp();
80 // if (myp == 0)
81 // {
82 // loc_part = (int*)mesh->get_part()->get_loc_part();
83 // }
84 // else
85 // {
86 // loc_part = new int[mesh->n_elements()];
87 // }
88 // MPI_Bcast(loc_part, mesh->n_elements(), MPI_INT, 0, mesh->get_part()->get_init_distr()->get_comm());
89 //
90 // // Distribute element dofs.
91 // // First we distribute dofs on elements associated to process 0 and so on.
92 // for (int proc=0; proc<mesh->get_part()->get_init_distr()->np(); proc++)
93 // {
94 // if (proc == myp)
95 // loffset_ = next_free_dof;
96 //
97 // FOR_ELEMENTS(mesh, cell)
98 // {
99 // if (cell->dim() != dim) continue;
100 //
101 // if (loc_part[cell.index()] != proc) continue;
102 //
103 // // distribute dofs
104 // // TODO: For the moment we distribute only dofs associated to the cell
105 // // In the future we want to distribute dofs on vertices, lines,
106 // // and triangles as well.
107 // object_dofs[cell.index()] = new int*[dim+1];
108 // for (int i=0; i<dim+1; i++)
109 // object_dofs[cell.index()][i] = NULL;
110 // object_dofs[cell.index()][dim] = new int[n_obj_dofs[dim]];
111 //
112 // for (unsigned int i=0; i<n_obj_dofs[dim]; i++)
113 // object_dofs[cell.index()][dim][i] = next_free_dof++;
114 // }
115 //
116 // if (proc == myp)
117 // lsize_ = next_free_dof - loffset_;
118 // }
119 //
120 // // Finally we free the unused array loc_part.
121 // if (mesh->get_part()->get_init_distr()->myp() != 0)
122 // delete[] loc_part;
123 //
124 //// FOR_ELEMENTS(mesh,cell)
125 //// {
126 //// // skip cells of different dimension
127 //// if (cell->dim() != dim) continue;
128 ////
129 //// // distribute dofs
130 //// // TODO: For the moment we distribute only dofs associated to the cell
131 //// // In the future we want to distribute dofs on vertices, lines,
132 //// // and triangles as well.
133 //// object_dofs[dim][cell] = new int[n_obj_dofs[dim]];
134 //// for (unsigned int i=0; i<n_obj_dofs[dim]; i++)
135 //// object_dofs[dim][cell][i] = next_free_dof++;
136 //// }
137 //
138 //
139 //// FOR_ELEMENTS(mesh,cell)
140 //// {
141 //// // skip cells of different dimension
142 //// if (cell->dim != dim) continue;
143 ////
144 //// // distribute dofs
145 //// for (int dm=0; dm<=dim; dm++)
146 //// {
147 //// for (int i=0; i<cell->n_sides_by_dim(dm); i++)
148 //// {
149 //// void *side = cell->side_by_dim(dm, i);
150 //// // check if node has already assigned dofs, otherwise
151 //// // distribute
152 //// if (object_dofs[dm].find(side) == object_dofs[dm].end())
153 //// {
154 //// object_dofs[dm][side] = new int[n_obj_dofs[dm]];
155 //// for (int i=0; i<n_obj_dofs[dm]; i++)
156 //// object_dofs[dm][side][i] = next_free_dof++;
157 //// }
158 //// }
159 //// }
160 //// }
161 //
162 // n_dofs = next_free_dof - offset;
163 //}
164 //
165 //
166 //
167 //template<unsigned int dim, unsigned int spacedim> inline
168 //const unsigned int DOFHandler<dim,spacedim>::n_local_dofs()
169 //{
170 // return finite_element->n_dofs();
171 //}
172 //
173 //
174 //
175 //template<unsigned int dim, unsigned int spacedim>
176 //void DOFHandler<dim,spacedim>::get_dof_indices(const CellIterator &cell, unsigned int indices[])
177 //{
178 //// void *side;
179 //// unsigned int offset, pid;
180 //
181 // for (unsigned int k=0; k<finite_element->n_object_dofs(dim,DOF_SINGLE); k++)
182 // indices[k] = object_dofs[cell.index()][dim][k];
183 //
184 //// indices.clear();
185 ////
186 //// get_object_dof_indices<0>(cell, indices);
187 //// get_object_dof_indices<1>(cell, indices);
188 //// get_object_dof_indices<2>(cell, indices);
189 //// get_object_dof_indices<3>(cell, indices);
190 //}
191 //
192 ////template<unsigned int dim> template<unsigned int obj_dim> inline void DOFHandler<dim>::get_object_dof_indices(const CellIterator &cell, unsigned int indices[])
193 ////{
194 // // TODO: implement for lower dimensional objects
195 //
196 //// void *side;
197 //// unsigned int offset, pid;
198 ////
199 //// // loop over cell points/lines/triangles/tetrahedra
200 //// for (int i=0; i<n_simplex_objects<dim>(obj_dim); i++)
201 //// {
202 //// side = cell->side_by_dim(obj_dim,i);
203 //// pid = permutation_id<dim,obj_dim>(cell,i);
204 //// offset = 0;
205 //// // loop over dof multiplicities (single dofs, pairs, triples, sextuples)
206 //// for (vector<unsigned int>::iterator m=dof_multiplicities.begin(); m!=dof_multiplicities.end(); m++)
207 //// {
208 //// // loop over particular single dofs/dof pairs/triples/sextuples
209 //// for (int j=0; j<finite_element.n_object_dofs(obj_dim,*m); j++)
210 //// {
211 //// // loop over particular dofs (the single dof/2 dofs in the pair etc.)
212 //// for (int k=0; k<*m; k++)
213 //// indices.push_back(object_dofs[obj_dim][side][offset+Simplex<obj_dim>::pair_permutations[pid][k]]);
214 ////
215 //// offset += *m;
216 //// }
217 //// }
218 //// }
219 ////}
220 //
221 //template<unsigned int dim, unsigned int spacedim> inline
222 //void DOFHandler<dim,spacedim>::get_dof_values(const CellIterator &cell, const Vec &values, double local_values[])
223 //{
224 // unsigned int indices[finite_element->n_dofs()];
225 //
226 // get_dof_indices(cell, indices);
227 // VecGetValues(values, finite_element->n_dofs(), (PetscInt *)indices, local_values);
228 //}
229 
230 
231 
233  : DOFHandlerBase(_mesh),
234  fe1d_(0),
235  fe2d_(0),
236  fe3d_(0)
237 {
238  object_dofs = new int**[mesh_->n_elements()];
239  for (unsigned int i=0; i<mesh_->n_elements(); i++)
240  object_dofs[i] = NULL;
241 
243 }
244 
247  const unsigned int offset)
248 {
249  // First check if dofs are already distributed.
250  OLD_ASSERT((fe1d_ == 0) && (fe2d_ == 0) && (fe3d_ == 0), "Attempt to distribute DOFs multiple times!");
251 
252  unsigned int next_free_dof = offset;
253  // n_obj_dofs[element_dim][general_face_dim]
254  // for every dim of ref. element, number of DoFs on its generalized face (face, edge, vertex)
255  unsigned int n_obj_dofs[4][4];
256 
257 
258  fe1d_ = &fe1d;
259  fe2d_ = &fe2d;
260  fe3d_ = &fe3d;
262 
263  for (unsigned int dm=0; dm <= 1; dm++)
264  {
265  n_obj_dofs[1][dm] = 0;
266  for (unsigned int m=0; m<dof_multiplicities.size(); m++)
267  n_obj_dofs[1][dm] += fe1d.n_object_dofs(dm, dof_multiplicities[m])*dof_multiplicities[m];
268  }
269  for (unsigned int dm=0; dm <= 2; dm++)
270  {
271  n_obj_dofs[2][dm] = 0;
272  for (unsigned int m=0; m<dof_multiplicities.size(); m++)
273  n_obj_dofs[2][dm] += fe2d.n_object_dofs(dm, dof_multiplicities[m])*dof_multiplicities[m];
274  }
275  for (unsigned int dm=0; dm <= 3; dm++)
276  {
277  n_obj_dofs[3][dm] = 0;
278  for (unsigned int m=0; m<dof_multiplicities.size(); m++)
279  n_obj_dofs[3][dm] += fe3d.n_object_dofs(dm, dof_multiplicities[m])*dof_multiplicities[m];
280  }
281 
282  // Broadcast partition of elements to all processes.
283  int *loc_part;
284  unsigned int myp = mesh_->get_part()->get_init_distr()->myp();
285  if (myp == 0)
286  {
287  loc_part = (int*)mesh_->get_part()->get_loc_part();
288  }
289  else
290  {
291  loc_part = new int[mesh_->n_elements()];
292  }
294 
295  // Distribute element dofs.
296  // First we distribute dofs on elements associated to process 0 and so on.
297  for (unsigned int proc=0; proc<mesh_->get_part()->get_init_distr()->np(); proc++)
298  {
299  if (proc == myp)
300  loffset_ = next_free_dof;
301 
302  FOR_ELEMENTS(mesh_, cell)
303  {
304  if (loc_part[cell.index()] != (int)proc) continue;
305 
306  unsigned int dim = cell->dim();
307 
308  // distribute dofs
309  // TODO: For the moment we distribute only dofs associated to the cell
310  // In the future we want to distribute dofs on vertices, lines,
311  // and triangles as well.
312  object_dofs[cell.index()] = new int*[dim+1];
313  for (unsigned int i=0; i<dim+1; i++)
314  object_dofs[cell.index()][i] = NULL;
315  object_dofs[cell.index()][dim] = new int[n_obj_dofs[dim][dim]];
316 
317  for (unsigned int i=0; i<n_obj_dofs[dim][dim]; i++)
318  object_dofs[cell.index()][dim][i] = next_free_dof++;
319  }
320 
321  if (proc == myp) {
322  lsize_ = next_free_dof - loffset_;
323  ds_ = new Distribution(lsize_, PETSC_COMM_WORLD);
324  }
325  }
326 
327  // Finally we free the unused array loc_part.
328  if (mesh_->get_part()->get_init_distr()->myp() != 0)
329  delete[] loc_part;
330 
331  n_dofs = next_free_dof - offset;
332 }
333 
334 void DOFHandlerMultiDim::get_dof_indices(const CellIterator &cell, unsigned int indices[]) const
335 {
336  unsigned int dim = cell->dim();
337  unsigned int n_objects_dofs;
338 
339  switch (dim)
340  {
341  case 1:
342  n_objects_dofs = fe1d_->n_object_dofs(dim,DOF_SINGLE);
343  break;
344  case 2:
345  n_objects_dofs = fe2d_->n_object_dofs(dim,DOF_SINGLE);
346  break;
347  case 3:
348  n_objects_dofs = fe3d_->n_object_dofs(dim,DOF_SINGLE);
349  break;
350  }
351 
352  for (unsigned int k = 0; k < n_objects_dofs; k++)
353  indices[k] = object_dofs[cell.index()][dim][k];
354 }
355 
356 void DOFHandlerMultiDim::get_loc_dof_indices(const CellIterator &cell, unsigned int indices[]) const
357 {
358  unsigned int dim = cell->dim();
359  unsigned int n_objects_dofs;
360 
361  switch (dim)
362  {
363  case 1:
364  n_objects_dofs = fe1d_->n_object_dofs(dim,DOF_SINGLE);
365  break;
366  case 2:
367  n_objects_dofs = fe2d_->n_object_dofs(dim,DOF_SINGLE);
368  break;
369  case 3:
370  n_objects_dofs = fe3d_->n_object_dofs(dim,DOF_SINGLE);
371  break;
372  }
373 
374  for (unsigned int k = 0; k < n_objects_dofs; k++)
375  indices[k] = object_dofs[cell.index()][dim][k] - loffset_;
376 }
377 
378 void DOFHandlerMultiDim::get_dof_values(const CellIterator &cell, const Vec &values, double local_values[]) const
379 {
380  int ndofs=0;
381 
382  switch (cell->dim())
383  {
384  case 1:
385  ndofs = fe1d_->n_dofs();
386  break;
387  case 2:
388  ndofs = fe2d_->n_dofs();
389  break;
390  case 3:
391  ndofs = fe3d_->n_dofs();
392  break;
393  }
394 
395  unsigned int indices[ndofs];
396 
397  get_dof_indices(cell, indices);
398  VecGetValues(values, ndofs, (PetscInt *)indices, local_values);
399 }
400 
402 {
403  for (ElementFullIter elem=mesh_->element.begin(); elem!=mesh_->element.end(); ++elem)
404  if (object_dofs[elem.index()] != NULL)
405  {
406  for (unsigned int j=0; j<=elem->dim(); j++)
407  if (object_dofs[elem.index()][j] != NULL)
408  delete[] object_dofs[elem.index()][j];
409 
410  delete[] object_dofs[elem.index()];
411  }
412  delete[] object_dofs;
413 }
414 
415 
416 
418 {
419  // create local arrays of elements
420  el_ds_ = mesh_->get_el_ds();
423 
424  // create local array of edges
425  for (unsigned int iedg=0; iedg<mesh_->edges.size(); iedg++)
426  {
427  bool is_edge_local = false;
428  Edge *edg = &mesh_->edges[iedg];
429  for (int sid=0; sid<edg->n_sides; sid++)
430  if (el_is_local(edg->side(sid)->element().index()))
431  {
432  is_edge_local = true;
433  break;
434  }
435  if (is_edge_local)
436  edg_4_loc.push_back(iedg);
437  }
438 
439  // create local array of neighbours
440  for (unsigned int inb=0; inb<mesh_->vb_neighbours_.size(); inb++)
441  {
442  Neighbour *nb = &mesh_->vb_neighbours_[inb];
443  if (el_is_local(mesh_->element.index(nb->element()))
444  || el_is_local(nb->side()->element().index()))
445  nb_4_loc.push_back(inb);
446  }
447 }
448 
449 
450 bool DOFHandlerMultiDim::el_is_local(int index) const
451 {
452  return el_ds_->is_local(row_4_el[index]);
453 }
454 
455 
456 
457 
458 
459 template<> FiniteElement<1,3> *DOFHandlerMultiDim::fe<1>() const { return fe1d_; }
460 template<> FiniteElement<2,3> *DOFHandlerMultiDim::fe<2>() const { return fe2d_; }
461 template<> FiniteElement<3,3> *DOFHandlerMultiDim::fe<3>() const { return fe3d_; }
462 
463 
464 //template class DOFHandler<0,3>;
465 //template class DOFHandler<1,3>;
466 //template class DOFHandler<2,3>;
467 //template class DOFHandler<3,3>;
Declaration of class which handles the ordering of degrees of freedom (dof) and mappings between loca...
vector< int > edg_4_loc
Local edge index -> global edge index.
Definition: dofhandler.hh:385
DOFHandlerMultiDim(Mesh &_mesh)
Constructor.
Definition: dofhandler.cc:232
FiniteElement< 3, 3 > * fe3d_
Definition: dofhandler.hh:365
#define FOR_ELEMENTS(_mesh_, __i)
Definition: mesh.h:426
FiniteElement< 1, 3 > * fe1d_
Pointer to the finite element class for which the handler distributes dofs.
Definition: dofhandler.hh:363
Distribution * el_ds_
Distribution of elements.
Definition: dofhandler.hh:382
Definition: mesh.h:97
void distribute_dofs(FiniteElement< 1, 3 > &fe1d, FiniteElement< 2, 3 > &fe2d, FiniteElement< 3, 3 > &fe3d, const unsigned int offset=0)
Distributes degrees of freedom on the mesh needed for the given finite elements.
Definition: dofhandler.cc:245
int index() const
Definition: sys_vector.hh:78
int * get_el_4_loc() const
Definition: mesh.h:180
int n_sides
Definition: edges.h:36
unsigned int global_dof_offset
Index of first global dof.
Definition: dofhandler.hh:110
Definition: edges.h:26
Partitioning * get_part()
Definition: mesh.cc:194
const std::vector< DofMultiplicity > dof_multiplicities
unsigned int lsize_
Number of dofs associated to local process.
Definition: dofhandler.hh:131
#define OLD_ASSERT(...)
Definition: global_defs.h:131
unsigned int n_elements() const
Definition: mesh.h:141
const unsigned int offset() const
Returns the number of the first global dof handled by this DOFHandler.
Definition: dofhandler.hh:67
bool is_local(unsigned int idx) const
identify local index
Mesh * mesh_
Pointer to the mesh to which the dof handler is associated.
Definition: dofhandler.hh:141
SideIter side()
unsigned int index(const T *pointer) const
Definition: sys_vector.hh:373
void get_loc_dof_indices(const CellIterator &cell, unsigned int indices[]) const override
Returns the indices of dofs associated to the cell on the local process.
Definition: dofhandler.cc:356
FullIter begin()
Definition: sys_vector.hh:383
unsigned int np() const
get num of processors
Distribution * get_el_ds() const
Definition: mesh.h:174
void make_elem_partitioning()
Prepare parallel distribution of elements, edges and neighbours.
Definition: dofhandler.cc:417
Distribution * ds_
Distribution of dofs associated to local process.
Definition: dofhandler.hh:146
ElementIter element()
int *** object_dofs
Number of dofs associated to geometrical entities.
Definition: dofhandler.hh:374
unsigned int myp() const
get my processor
Support classes for parallel programing.
FiniteElement< 2, 3 > * fe2d_
Definition: dofhandler.hh:364
vector< Neighbour > vb_neighbours_
Definition: mesh.h:258
unsigned int loffset_
Index of the first dof on the local process.
Definition: dofhandler.hh:136
const unsigned int n_object_dofs(unsigned int object_dim, DofMultiplicity multiplicity)
Returns the number of single dofs/dof pairs/triples/sextuples that lie on a single geometric entity o...
void get_dof_indices(const CellIterator &cell, unsigned int indices[]) const override
Returns the global indices of dofs associated to the cell.
Definition: dofhandler.cc:334
ElementFullIter element() const
Definition: side_impl.hh:52
#define MPI_INT
Definition: mpi.h:160
~DOFHandlerMultiDim() override
Destructor.
Definition: dofhandler.cc:401
int * get_row_4_el() const
Definition: mesh.h:177
MPI_Comm get_comm() const
Returns communicator.
std::vector< Edge > edges
Vector of MH edges, this should not be part of the geometrical mesh.
Definition: mesh.h:239
unsigned int n_dofs
Number of global dofs assigned by the handler.
Definition: dofhandler.hh:126
const Distribution * get_init_distr() const
Definition: partitioning.cc:74
const int * get_loc_part() const
Definition: partitioning.cc:81
#define MPI_Bcast(buffer, count, datatype, root, comm)
Definition: mpi.h:534
int * row_4_el
Global element index -> index according to partitioning.
Definition: dofhandler.hh:378
const unsigned int n_dofs() const
Returns the number of degrees of freedom needed by the finite element.
Abstract class for description of finite elements.
void get_dof_values(const CellIterator &cell, const Vec &values, double local_values[]) const override
Returns the dof values associated to the cell.
Definition: dofhandler.cc:378
bool el_is_local(int index) const
Definition: dofhandler.cc:450
vector< int > nb_4_loc
Local neighbour index -> global neighbour index.
Definition: dofhandler.hh:388
FullIter end()
Returns FullFullIterer of the fictions past the end element.
Definition: sys_vector.hh:387
int * el_4_loc
Local element index -> global element index.
Definition: dofhandler.hh:380
SideIter side(const unsigned int i) const
Definition: edges.h:31
ElementVector element
Vector of elements of the mesh.
Definition: mesh.h:228