dof_object.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // C++ includes
21 
22 // Local includes
23 #include "libmesh/dof_object.h"
24 
25 
26 namespace libMesh
27 {
28 
29 
30 
31 // ------------------------------------------------------------
32 // DofObject class static member -now initialized in header
36 
37 
38 
39 // ------------------------------------------------------------
40 // DofObject class members
41 // Copy Constructor
42 DofObject::DofObject (const DofObject & dof_obj) :
44 #ifdef LIBMESH_ENABLE_AMR
45  old_dof_object (nullptr),
46 #endif
47 #ifdef LIBMESH_ENABLE_UNIQUE_ID
48  _unique_id (dof_obj._unique_id),
49 #endif
50  _id (dof_obj._id),
51  _processor_id (dof_obj._processor_id),
52  _idx_buf (dof_obj._idx_buf)
53 {
54  // DO NOT copy old_dof_object, because this isn't a *real* copy
55  // constructor, it's a "copy almost everything" constructor that
56  // is intended to be used solely for internal construction of
57  // old_dof_object, never for a true deep copy where the newly
58  // created object really matches the source object.
59  //
60  // if (dof_obj.old_dof_object)
61  // this->old_dof_object = new DofObject(*(dof_obj.old_dof_object));
62 
63  // Check that everything worked
64 #ifdef DEBUG
65 
66  libmesh_assert_equal_to (this->n_systems(), dof_obj.n_systems());
67 
68  for (unsigned int s=0; s<this->n_systems(); s++)
69  {
70  libmesh_assert_equal_to (this->n_vars(s), dof_obj.n_vars(s));
71  libmesh_assert_equal_to (this->n_var_groups(s), dof_obj.n_var_groups(s));
72 
73  for (unsigned int vg=0; vg<this->n_var_groups(s); vg++)
74  libmesh_assert_equal_to (this->n_vars(s,vg), dof_obj.n_vars(s,vg));
75 
76  for (unsigned int v=0; v<this->n_vars(s); v++)
77  {
78  libmesh_assert_equal_to (this->n_comp(s,v), dof_obj.n_comp(s,v));
79 
80  for (unsigned int c=0; c<this->n_comp(s,v); c++)
81  libmesh_assert_equal_to (this->dof_number(s,v,c), dof_obj.dof_number(s,v,c));
82  }
83  }
84 
85 #endif
86 }
87 
88 
89 // Deep-copying assignment operator
91 {
92  if (&dof_obj == this)
93  return *this;
94 
95 #ifdef LIBMESH_ENABLE_AMR
96  this->clear_old_dof_object();
97 
98  this->old_dof_object = new DofObject(*(dof_obj.old_dof_object));
99 #endif
100 
101  _id = dof_obj._id;
102 #ifdef LIBMESH_ENABLE_UNIQUE_ID
103  _unique_id = dof_obj._unique_id;
104 #endif
105  _processor_id = dof_obj._processor_id;
106  _idx_buf = dof_obj._idx_buf;
107 
108 
109  // Check that everything worked
110 #ifdef DEBUG
111 
112  libmesh_assert_equal_to (this->n_systems(), dof_obj.n_systems());
113 
114  for (unsigned int s=0; s<this->n_systems(); s++)
115  {
116  libmesh_assert_equal_to (this->n_vars(s), dof_obj.n_vars(s));
117  libmesh_assert_equal_to (this->n_var_groups(s), dof_obj.n_var_groups(s));
118 
119  for (unsigned int vg=0; vg<this->n_var_groups(s); vg++)
120  libmesh_assert_equal_to (this->n_vars(s,vg), dof_obj.n_vars(s,vg));
121 
122  for (unsigned int v=0; v<this->n_vars(s); v++)
123  {
124  libmesh_assert_equal_to (this->n_comp(s,v), dof_obj.n_comp(s,v));
125 
126  for (unsigned int c=0; c<this->n_comp(s,v); c++)
127  libmesh_assert_equal_to (this->dof_number(s,v,c), dof_obj.dof_number(s,v,c));
128  }
129  }
130 
131 #endif
132 
133  return *this;
134 }
135 
136 
137 
138 
139 
140 #ifdef LIBMESH_ENABLE_AMR
141 
143 {
144  delete this->old_dof_object;
145  this->old_dof_object = nullptr;
146 }
147 
148 
149 
151 {
152  this->clear_old_dof_object();
153 
154  libmesh_assert (!this->old_dof_object);
155 
156  // Make a new DofObject, assign a copy of \p this.
157  // Make sure the copy ctor for DofObject works!!
158  this->old_dof_object = new DofObject(*this);
159 }
160 
161 #endif
162 
163 
164 
165 void DofObject::set_n_systems (const unsigned int ns)
166 {
167  // Check for trivial return
168  if (ns == this->n_systems())
169  return;
170 
171  // Clear any existing data. This is safe to call
172  // even if we don't have any data.
173  this->clear_dofs();
174 
175  // Set the new number of systems
176  _idx_buf.resize(ns, ns);
177  _idx_buf[0] = ns;
178 
179 
180 #ifdef DEBUG
181 
182  // check that all systems now exist and that they have 0 size
183  libmesh_assert_equal_to (ns, this->n_systems());
184  for (unsigned int s=0; s<this->n_systems(); s++)
185  {
186  libmesh_assert_equal_to (this->n_vars(s), 0);
187  libmesh_assert_equal_to (this->n_var_groups(s), 0);
188  }
189 
190 #endif
191 }
192 
193 
194 
196 {
197  // quick return?
198  if (this->n_systems() == 0)
199  {
200  this->set_n_systems(1);
201  return;
202  }
203 
204  DofObject::index_buffer_t::iterator it = _idx_buf.begin();
205 
206  std::advance(it, this->n_systems());
207 
208  // this inserts the current vector size at the position for the new system - creating the
209  // entry we need for the new system indicating there are 0 variables.
210  _idx_buf.insert(it, cast_int<dof_id_type>(_idx_buf.size()));
211 
212  // cache this value before we screw it up!
213  const unsigned int ns_orig = this->n_systems();
214 
215  // increment the number of systems and the offsets for each of
216  // the systems including the new one we just added.
217  for (unsigned int i=0; i<ns_orig+1; i++)
218  _idx_buf[i]++;
219 
220  libmesh_assert_equal_to (this->n_systems(), (ns_orig+1));
221  libmesh_assert_equal_to (this->n_vars(ns_orig), 0);
222  libmesh_assert_equal_to (this->n_var_groups(ns_orig), 0);
223 }
224 
225 
226 
227 void DofObject::set_n_vars_per_group(const unsigned int s,
228  const std::vector<unsigned int> & nvpg)
229 {
230 
231  libmesh_assert_less (s, this->n_systems());
232 
233  // number of variable groups for this system - inferred
234  const unsigned int nvg = cast_int<unsigned int>(nvpg.size());
235 
236  // BSK - note that for compatibility with the previous implementation
237  // calling this method when (nvars == this->n_vars()) requires that
238  // we invalidate the DOF indices and set the number of components to 0.
239  // Note this was a bit of a surprise to me - there was no quick return in
240  // the old method, which caused removal and readdition of the DOF indices
241  // even in the case of (nvars == this->n_vars()), resulting in n_comp(s,v)
242  // implicitly becoming 0 regardless of any previous value.
243  // quick return?
244  if (nvg == this->n_var_groups(s))
245  {
246  for (unsigned int vg=0; vg<nvg; vg++)
247  {
248  this->set_n_comp_group(s,vg,0);
249  libmesh_assert_equal_to (this->n_vars(s,vg), nvpg[vg]);
250  }
251  return;
252  }
253 
254  // since there is ample opportunity to screw up other systems, let us
255  // cache their current sizes and later assert that they are unchanged.
256 #ifdef DEBUG
257  DofObject::index_buffer_t old_system_sizes;
258  old_system_sizes.reserve(this->n_systems());
259 
260  for (unsigned int s_ctr=0; s_ctr<this->n_systems(); s_ctr++)
261  old_system_sizes.push_back(this->n_var_groups(s_ctr));
262 #endif
263 
264  // remove current indices if we have some
265  if (this->n_var_groups(s) != 0)
266  {
267  const unsigned int old_nvg_s = this->n_var_groups(s);
268 
269  DofObject::index_buffer_t::iterator
270  it = _idx_buf.begin(),
271  end = _idx_buf.begin();
272 
273  std::advance(it, this->start_idx(s));
274  std::advance(end, this->end_idx(s));
275  _idx_buf.erase(it,end);
276 
277  for (unsigned int ctr=(s+1); ctr<this->n_systems(); ctr++)
278  _idx_buf[ctr] -= 2*old_nvg_s;
279  }
280 
281  // better not have any now!
282  libmesh_assert_equal_to (this->n_var_groups(s), 0);
283 
284  // Make sure we didn't screw up any of our sizes!
285 #ifdef DEBUG
286  for (unsigned int s_ctr=0; s_ctr<this->n_systems(); s_ctr++)
287  if (s_ctr != s)
288  libmesh_assert_equal_to (this->n_var_groups(s_ctr), old_system_sizes[s_ctr]);
289 #endif
290 
291  // OK, if the user requested 0 that is what we have
292  if (nvg == 0)
293  return;
294 
295  {
296  // array to hold new indices
297  DofObject::index_buffer_t var_idxs(2*nvg);
298  for (unsigned int vg=0; vg<nvg; vg++)
299  {
300  var_idxs[2*vg ] = ncv_magic*nvpg[vg] + 0;
301  var_idxs[2*vg + 1] = invalid_id - 1;
302  }
303 
304  DofObject::index_buffer_t::iterator it = _idx_buf.begin();
305  std::advance(it, this->end_idx(s));
306  _idx_buf.insert(it, var_idxs.begin(), var_idxs.end());
307 
308  for (unsigned int ctr=(s+1); ctr<this->n_systems(); ctr++)
309  _idx_buf[ctr] += 2*nvg;
310 
311  // resize _idx_buf to fit so no memory is wasted.
313  }
314 
315  libmesh_assert_equal_to (nvg, this->n_var_groups(s));
316 
317 #ifdef DEBUG
318 
319  libmesh_assert_equal_to (this->n_var_groups(s), nvpg.size());
320 
321  for (unsigned int vg=0; vg<this->n_var_groups(s); vg++)
322  {
323  libmesh_assert_equal_to (this->n_vars(s,vg), nvpg[vg]);
324  libmesh_assert_equal_to (this->n_comp_group(s,vg), 0);
325  }
326 
327  for (unsigned int v=0; v<this->n_vars(s); v++)
328  libmesh_assert_equal_to (this->n_comp(s,v), 0);
329 
330  // again, all other system sizes should be unchanged!
331  for (unsigned int s_ctr=0; s_ctr<this->n_systems(); s_ctr++)
332  if (s_ctr != s)
333  libmesh_assert_equal_to (this->n_var_groups(s_ctr), old_system_sizes[s_ctr]);
334 
335 #endif
336 }
337 
338 
339 
340 void DofObject::set_n_comp(const unsigned int s,
341  const unsigned int var,
342  const unsigned int ncomp)
343 {
344  libmesh_assert_less (s, this->n_systems());
345  libmesh_assert_less (var, this->n_vars(s));
346 
347  this->set_n_comp_group(s, this->var_to_vg(s,var), ncomp);
348 }
349 
350 
351 
352 void DofObject::set_n_comp_group(const unsigned int s,
353  const unsigned int vg,
354  const unsigned int ncomp)
355 {
356  libmesh_assert_less (s, this->n_systems());
357  libmesh_assert_less (vg, this->n_var_groups(s));
358 
359  // Check for trivial return
360  if (ncomp == this->n_comp_group(s,vg)) return;
361 
362 #ifndef NDEBUG
363  if (ncomp >= ncv_magic)
364  {
365  const index_t ncvm = ncv_magic;
366  libmesh_error_msg("ERROR: ncomp must be less than DofObject::ncv_magic!\n" \
367  << "ncomp = " \
368  << ncomp \
369  << ", ncv_magic = " \
370  << ncvm \
371  << "\nrecompile and try again!");
372  }
373 #endif
374 
375  const unsigned int
376  start_idx_sys = this->start_idx(s),
377  n_vars_group = this->n_vars(s,vg),
378  base_offset = start_idx_sys + 2*vg;
379 
380  libmesh_assert_less ((base_offset + 1), _idx_buf.size());
381 
382  // if (ncomp)
383  // libMesh::out << "s,vg,ncomp="
384  // << s << ","
385  // << vg << ","
386  // << ncomp << '\n';
387 
388  // set the number of components, maintaining the number
389  // of variables in the group
390  _idx_buf[base_offset] = ncv_magic*n_vars_group + ncomp;
391 
392  // We use (invalid_id - 1) to signify no
393  // components for this object
394  _idx_buf[base_offset + 1] = (ncomp == 0) ? invalid_id - 1 : invalid_id;
395 
396  // this->debug_buffer();
397  // libMesh::out << "s,vg = " << s << "," << vg << '\n'
398  // << "base_offset=" << base_offset << '\n'
399  // << "this->n_comp(s,vg)=" << this->n_comp(s,vg) << '\n'
400  // << "this->n_comp_group(s,vg)=" << this->n_comp_group(s,vg) << '\n'
401  // << "this->n_vars(s,vg)=" << this->n_vars(s,vg) << '\n'
402  // << "this->n_var_groups(s)=" << this->n_var_groups(s) << '\n';
403 
404  libmesh_assert_equal_to (ncomp, this->n_comp_group(s,vg));
405 }
406 
407 
408 
409 void DofObject::set_dof_number(const unsigned int s,
410  const unsigned int var,
411  const unsigned int comp,
412  const dof_id_type dn)
413 {
414  libmesh_assert_less (s, this->n_systems());
415  libmesh_assert_less (var, this->n_vars(s));
416  libmesh_assert_less (comp, this->n_comp(s,var));
417 
418  const unsigned int
419  vg = this->var_to_vg(s,var),
420 #ifndef NDEBUG
421  ncg = this->n_comp_group(s,vg),
422 #endif
423  vig = this->system_var_to_vg_var(s,vg,var),
424  start_idx_sys = this->start_idx(s);
425 
426  libmesh_assert_less ((start_idx_sys + 2*vg + 1), _idx_buf.size());
427 
428  dof_id_type & base_idx = _idx_buf[start_idx_sys + 2*vg + 1];
429 
430  // We intend to change all dof numbers together or not at all
431  if (comp || vig)
432  libmesh_assert ((dn == invalid_id && base_idx == invalid_id) ||
433  (dn == base_idx + vig*ncg + comp));
434 
435  // only explicitly store the base index for vig==0, comp==0
436  else
437  base_idx = dn;
438 
439  libmesh_assert_equal_to (this->dof_number(s, var, comp), dn);
440 }
441 
442 
443 
444 // FIXME: it'll be tricky getting this to work with 64-bit dof_id_type
446 {
447  return
448  cast_int<unsigned int> (
449 #ifdef LIBMESH_ENABLE_AMR
450  ((old_dof_object == nullptr) ? 0 : old_dof_object->packed_indexing_size()) + 2 +
451 #else
452  1 +
453 #endif
454  _idx_buf.size());
455 }
456 
457 
458 
459 // FIXME: it'll be tricky getting this to work with 64-bit dof_id_type
460 unsigned int
461 DofObject::unpackable_indexing_size(std::vector<largest_id_type>::const_iterator begin)
462 {
463 #ifdef LIBMESH_ENABLE_AMR
464  const bool has_old_dof_object = cast_int<bool>(*begin++);
465 
466  static const int dof_header_size = 2;
467 #else
468  static const bool has_old_dof_object = false;
469  static const int dof_header_size = 1;
470 #endif
471 
472  const largest_id_type this_indexing_size = *begin++;
473 
474  return cast_int<unsigned int>
475  (dof_header_size + this_indexing_size +
476  (has_old_dof_object ?
477  unpackable_indexing_size(begin+this_indexing_size) : 0));
478 }
479 
480 
481 // FIXME: it'll be tricky getting this to work with 64-bit dof_id_type
482 void DofObject::unpack_indexing(std::vector<largest_id_type>::const_iterator begin)
483 {
484  _idx_buf.clear();
485 
486 #ifdef LIBMESH_ENABLE_AMR
487  this->clear_old_dof_object();
488  const bool has_old_dof_object = cast_int<bool>(*begin++);
489 #endif
490 
491  const largest_id_type size = *begin++;
492  _idx_buf.reserve(size);
493  std::copy(begin, begin+size, back_inserter(_idx_buf));
494 
495  // Check as best we can for internal consistency now
496  libmesh_assert(_idx_buf.empty() ||
497  (_idx_buf[0] <= _idx_buf.size()));
498 #ifdef DEBUG
499  if (!_idx_buf.empty())
500  for (unsigned int i=1; i < _idx_buf[0]; ++i)
501  {
502  libmesh_assert_greater_equal (_idx_buf[i], _idx_buf[i-1]);
503  libmesh_assert_equal_to ((_idx_buf[i] - _idx_buf[i-1])%2, 0);
504  libmesh_assert_less_equal (_idx_buf[i], _idx_buf.size());
505  }
506 #endif
507 
508 #ifdef LIBMESH_ENABLE_AMR
509  if (has_old_dof_object)
510  {
511  this->old_dof_object = new DofObject();
512  this->old_dof_object->unpack_indexing(begin+size);
513  }
514 #endif
515 }
516 
517 
518 // FIXME: it'll be tricky getting this to work with 64-bit dof_id_type
519 void
520 DofObject::pack_indexing(std::back_insert_iterator<std::vector<largest_id_type>> target) const
521 {
522 #ifdef LIBMESH_ENABLE_AMR
523  // We might need to pack old_dof_object too
524  *target++ = (old_dof_object == nullptr) ? 0 : 1;
525 #endif
526 
527  *target++ = _idx_buf.size();
528  std::copy(_idx_buf.begin(), _idx_buf.end(), target);
529 
530 #ifdef LIBMESH_ENABLE_AMR
531  if (old_dof_object)
532  old_dof_object->pack_indexing(target);
533 #endif
534 }
535 
536 
537 
539 {
540  libMesh::out << " [ ";
541  for (const auto & idx : _idx_buf)
542  libMesh::out << idx << " ";
543  libMesh::out << "]\n";
544 }
545 
546 
547 
549 {
550  libMesh::out << this->id() << " [ ";
551 
552  for (unsigned int s=0; s<this->n_systems(); s++)
553  {
554  libMesh::out << "s:" << s << " ";
555  for (unsigned int var=0; var<this->n_vars(s); var++)
556  {
557  libMesh::out << "v:" << var << " ";
558  for (unsigned int comp=0; comp<this->n_comp(s,var); comp++)
559  {
560  libMesh::out << "c:" << comp << " dof:" << this->dof_number(s,var,comp) << " ";
561  }
562  }
563  }
564 
565  libMesh::out << "]\n";
566 }
567 
568 
569 
570 } // namespace libMesh
void set_n_comp(const unsigned int s, const unsigned int var, const unsigned int ncomp)
Definition: dof_object.C:340
unsigned int system_var_to_vg_var(const unsigned int s, const unsigned int vg, const unsigned int var) const
Definition: dof_object.h:1022
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:833
void set_old_dof_object()
Definition: dof_object.C:150
static unsigned int unpackable_indexing_size(std::vector< largest_id_type >::const_iterator begin)
Definition: dof_object.C:461
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:803
unsigned int n_var_groups(const unsigned int s) const
Definition: dof_object.h:758
unsigned int var_to_vg(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:1004
uint64_t largest_id_type
Definition: id_types.h:139
uint8_t processor_id_type
Definition: id_types.h:99
dof_id_type _id
Definition: dof_object.h:442
IterBase * end
dof_id_type index_t
Definition: dof_object.h:506
unique_id_type _unique_id
Definition: dof_object.h:436
unsigned int end_idx(const unsigned int s) const
Definition: dof_object.h:947
dof_id_type id() const
Definition: dof_object.h:655
DofObject & operator=(const DofObject &dof_obj)
Definition: dof_object.C:90
static const unique_id_type invalid_unique_id
Definition: dof_object.h:352
static const processor_id_type invalid_processor_id
Definition: dof_object.h:358
void set_dof_number(const unsigned int s, const unsigned int var, const unsigned int comp, const dof_id_type dn)
Definition: dof_object.C:409
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Definition: dof_object.h:768
unsigned int n_systems() const
Definition: dof_object.h:749
processor_id_type _processor_id
Definition: libmesh.C:236
void print_dof_info() const
Definition: dof_object.C:548
void clear_old_dof_object()
Definition: dof_object.C:142
static const dof_id_type invalid_id
Definition: dof_object.h:347
std::vector< index_t > index_buffer_t
Definition: dof_object.h:507
void set_n_comp_group(const unsigned int s, const unsigned int vg, const unsigned int ncomp)
Definition: dof_object.C:352
void set_n_systems(const unsigned int s)
Definition: dof_object.C:165
void set_n_vars_per_group(const unsigned int s, const std::vector< unsigned int > &nvpg)
Definition: dof_object.C:227
DofObject * old_dof_object
Definition: dof_object.h:79
unsigned int start_idx(const unsigned int s) const
Definition: dof_object.h:936
unsigned int packed_indexing_size() const
Definition: dof_object.C:445
void pack_indexing(std::back_insert_iterator< std::vector< largest_id_type >> target) const
Definition: dof_object.C:520
void unpack_indexing(std::vector< largest_id_type >::const_iterator begin)
Definition: dof_object.C:482
index_buffer_t _idx_buf
Definition: dof_object.h:508
void debug_buffer() const
Definition: dof_object.C:538
unsigned int n_comp_group(const unsigned int s, const unsigned int vg) const
Definition: dof_object.h:816
OStreamProxy out(std::cout)
uint8_t unique_id_type
Definition: id_types.h:79
processor_id_type _processor_id
Definition: dof_object.h:453
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
uint8_t dof_id_type
Definition: id_types.h:64
static const index_t ncv_magic
Definition: dof_object.h:519