$extrastylesheet
dof_object.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 
00020 // C++ includes
00021 
00022 // Local includes
00023 #include "libmesh/dof_object.h"
00024 
00025 
00026 namespace libMesh
00027 {
00028 
00029 
00030 
00031 // ------------------------------------------------------------
00032 // DofObject class static member -now initialized in header
00033 const dof_id_type       DofObject::invalid_id;
00034 const unique_id_type    DofObject::invalid_unique_id;
00035 const processor_id_type DofObject::invalid_processor_id;
00036 
00037 
00038 
00039 // ------------------------------------------------------------
00040 // DofObject class members
00041 // Copy Constructor
00042 DofObject::DofObject (const DofObject& dof_obj) :
00043   ReferenceCountedObject<DofObject>(),
00044 #ifdef LIBMESH_ENABLE_AMR
00045   old_dof_object (NULL),
00046 #endif
00047 #ifdef LIBMESH_ENABLE_UNIQUE_ID
00048   _unique_id     (dof_obj._unique_id),
00049 #endif
00050   _id            (dof_obj._id),
00051   _processor_id  (dof_obj._processor_id),
00052   _idx_buf       (dof_obj._idx_buf)
00053 {
00054 
00055   // Check that everything worked
00056 #ifdef DEBUG
00057 
00058   libmesh_assert_equal_to (this->n_systems(), dof_obj.n_systems());
00059 
00060   for (unsigned int s=0; s<this->n_systems(); s++)
00061     {
00062       libmesh_assert_equal_to (this->n_vars(s),       dof_obj.n_vars(s));
00063       libmesh_assert_equal_to (this->n_var_groups(s), dof_obj.n_var_groups(s));
00064 
00065       for (unsigned int vg=0; vg<this->n_var_groups(s); vg++)
00066         libmesh_assert_equal_to (this->n_vars(s,vg), dof_obj.n_vars(s,vg));
00067 
00068       for (unsigned int v=0; v<this->n_vars(s); v++)
00069         {
00070           libmesh_assert_equal_to (this->n_comp(s,v), dof_obj.n_comp(s,v));
00071 
00072           for (unsigned int c=0; c<this->n_comp(s,v); c++)
00073             libmesh_assert_equal_to (this->dof_number(s,v,c), dof_obj.dof_number(s,v,c));
00074         }
00075     }
00076 
00077 #endif
00078 }
00079 
00080 
00081 // Deep-copying assignment operator
00082 DofObject& DofObject::operator= (const DofObject& dof_obj)
00083 {
00084   if (&dof_obj == this)
00085     return *this;
00086 
00087 #ifdef LIBMESH_ENABLE_AMR
00088   this->clear_old_dof_object();
00089 
00090   this->old_dof_object = new DofObject(*(dof_obj.old_dof_object));
00091 #endif
00092 
00093   _id           = dof_obj._id;
00094 #ifdef LIBMESH_ENABLE_UNIQUE_ID
00095   _unique_id    = dof_obj._unique_id;
00096 #endif
00097   _processor_id = dof_obj._processor_id;
00098   _idx_buf      = dof_obj._idx_buf;
00099 
00100 
00101   // Check that everything worked
00102 #ifdef DEBUG
00103 
00104   libmesh_assert_equal_to (this->n_systems(), dof_obj.n_systems());
00105 
00106   for (unsigned int s=0; s<this->n_systems(); s++)
00107     {
00108       libmesh_assert_equal_to (this->n_vars(s),       dof_obj.n_vars(s));
00109       libmesh_assert_equal_to (this->n_var_groups(s), dof_obj.n_var_groups(s));
00110 
00111       for (unsigned int vg=0; vg<this->n_var_groups(s); vg++)
00112         libmesh_assert_equal_to (this->n_vars(s,vg), dof_obj.n_vars(s,vg));
00113 
00114       for (unsigned int v=0; v<this->n_vars(s); v++)
00115         {
00116           libmesh_assert_equal_to (this->n_comp(s,v), dof_obj.n_comp(s,v));
00117 
00118           for (unsigned int c=0; c<this->n_comp(s,v); c++)
00119             libmesh_assert_equal_to (this->dof_number(s,v,c), dof_obj.dof_number(s,v,c));
00120         }
00121     }
00122 
00123 #endif
00124 
00125   return *this;
00126 }
00127 
00128 
00129 
00130 
00131 
00132 #ifdef LIBMESH_ENABLE_AMR
00133 
00134 void  DofObject::clear_old_dof_object ()
00135 {
00136   delete this->old_dof_object;
00137   this->old_dof_object = NULL;
00138 }
00139 
00140 
00141 
00142 void DofObject::set_old_dof_object ()
00143 {
00144   this->clear_old_dof_object();
00145 
00146   libmesh_assert (!this->old_dof_object);
00147 
00148   // Make a new DofObject, assign a copy of \p this.
00149   // Make sure the copy ctor for DofObject works!!
00150   this->old_dof_object = new DofObject(*this);
00151 }
00152 
00153 #endif
00154 
00155 
00156 
00157 void DofObject::set_n_systems (const unsigned int ns)
00158 {
00159   // Check for trivial return
00160   if (ns == this->n_systems())
00161     return;
00162 
00163   // Clear any existing data.  This is safe to call
00164   // even if we don't have any data.
00165   this->clear_dofs();
00166 
00167   // Set the new number of systems
00168   _idx_buf.resize(ns, ns);
00169   _idx_buf[0] = ns;
00170 
00171 
00172 #ifdef DEBUG
00173 
00174   // check that all systems now exist and that they have 0 size
00175   libmesh_assert_equal_to (ns, this->n_systems());
00176   for (unsigned int s=0; s<this->n_systems(); s++)
00177     {
00178       libmesh_assert_equal_to (this->n_vars(s),       0);
00179       libmesh_assert_equal_to (this->n_var_groups(s), 0);
00180     }
00181 
00182 #endif
00183 }
00184 
00185 
00186 
00187 void DofObject::add_system()
00188 {
00189   // quick return?
00190   if (this->n_systems() == 0)
00191     {
00192       this->set_n_systems(1);
00193       return;
00194     }
00195 
00196   DofObject::index_buffer_t::iterator it = _idx_buf.begin();
00197 
00198   std::advance(it, this->n_systems());
00199 
00200   // this inserts the current vector size at the position for the new system - creating the
00201   // entry we need for the new system indicating there are 0 variables.
00202   _idx_buf.insert(it, cast_int<dof_id_type>(_idx_buf.size()));
00203 
00204   // cache this value before we screw it up!
00205   const unsigned int ns_orig = this->n_systems();
00206 
00207   // incriment the number of systems and the offsets for each of
00208   // the systems including the new one we just added.
00209   for (unsigned int i=0; i<ns_orig+1; i++)
00210     _idx_buf[i]++;
00211 
00212   libmesh_assert_equal_to (this->n_systems(), (ns_orig+1));
00213   libmesh_assert_equal_to (this->n_vars(ns_orig), 0);
00214   libmesh_assert_equal_to (this->n_var_groups(ns_orig), 0);
00215 }
00216 
00217 
00218 
00219 void DofObject::set_n_vars_per_group(const unsigned int s,
00220                                      const std::vector<unsigned int> &nvpg)
00221 {
00222 
00223   libmesh_assert_less (s, this->n_systems());
00224 
00225   // number of varaible groups for this system - inferred
00226   const unsigned int nvg = cast_int<unsigned int>(nvpg.size());
00227 
00228   // BSK - note that for compatibility with the previous implementation
00229   // calling this method when (nvars == this->n_vars()) requires that
00230   // we invalidate the DOF indices and set the number of components to 0.
00231   // Note this was a bit of a suprise to me - there was no quick return in
00232   // the old method, which caused removal and readdition of the DOF indices
00233   // even in the case of (nvars == this->n_vars()), resulting in n_comp(s,v)
00234   // implicitly becoming 0 regardless of any previous value.
00235   // quick return?
00236   if (nvg == this->n_var_groups(s))
00237     {
00238       for (unsigned int vg=0; vg<nvg; vg++)
00239         {
00240           this->set_n_comp_group(s,vg,0);
00241           libmesh_assert_equal_to (this->n_vars(s,vg), nvpg[vg]);
00242         }
00243       return;
00244     }
00245 
00246   // since there is ample opportunity to screw up other systems, let us
00247   // cache their current sizes and later assert that they are unchanged.
00248 #ifdef DEBUG
00249   DofObject::index_buffer_t old_system_sizes;
00250   old_system_sizes.reserve(this->n_systems());
00251 
00252   for (unsigned int s_ctr=0; s_ctr<this->n_systems(); s_ctr++)
00253     old_system_sizes.push_back(this->n_var_groups(s_ctr));
00254 #endif
00255 
00256   // remove current indices if we have some
00257   if (this->n_var_groups(s) != 0)
00258     {
00259       const unsigned int old_nvg_s = this->n_var_groups(s);
00260 
00261       DofObject::index_buffer_t::iterator
00262         it  = _idx_buf.begin(),
00263         end = _idx_buf.begin();
00264 
00265       std::advance(it,  this->start_idx(s));
00266       std::advance(end, this->end_idx(s));
00267       _idx_buf.erase(it,end);
00268 
00269       for (unsigned int ctr=(s+1); ctr<this->n_systems(); ctr++)
00270         _idx_buf[ctr] -= 2*old_nvg_s;
00271     }
00272 
00273   // better not have any now!
00274   libmesh_assert_equal_to (this->n_var_groups(s), 0);
00275 
00276   // had better not screwed up any of our sizes!
00277 #ifdef DEBUG
00278   for (unsigned int s_ctr=0; s_ctr<this->n_systems(); s_ctr++)
00279     if (s_ctr != s)
00280       libmesh_assert_equal_to (this->n_var_groups(s_ctr), old_system_sizes[s_ctr]);
00281 #endif
00282 
00283   // OK, if the user requested 0 that is what we have
00284   if (nvg == 0)
00285     return;
00286 
00287   {
00288     // array to hold new indices
00289     DofObject::index_buffer_t var_idxs(2*nvg);
00290     for (unsigned int vg=0; vg<nvg; vg++)
00291       {
00292         var_idxs[2*vg    ] = ncv_magic*nvpg[vg] + 0;
00293         var_idxs[2*vg + 1] = invalid_id - 1;
00294       }
00295 
00296     DofObject::index_buffer_t::iterator it = _idx_buf.begin();
00297     std::advance(it, this->end_idx(s));
00298     _idx_buf.insert(it, var_idxs.begin(), var_idxs.end());
00299 
00300     for (unsigned int ctr=(s+1); ctr<this->n_systems(); ctr++)
00301       _idx_buf[ctr] += 2*nvg;
00302 
00303     // resize _idx_buf to fit so no memory is wasted.
00304     DofObject::index_buffer_t(_idx_buf).swap(_idx_buf);
00305   }
00306 
00307   // that better had worked.  Assert stuff.
00308   libmesh_assert_equal_to (nvg, this->n_var_groups(s));
00309 
00310 #ifdef DEBUG
00311 
00312   // libMesh::out << " [ ";
00313   // for (unsigned int i=0; i<_idx_buf.size(); i++)
00314   //   libMesh::out << _idx_buf[i] << " ";
00315   // libMesh::out << "]\n";
00316 
00317   libmesh_assert_equal_to (this->n_var_groups(s), nvpg.size());
00318 
00319   for (unsigned int vg=0; vg<this->n_var_groups(s); vg++)
00320     {
00321       libmesh_assert_equal_to (this->n_vars(s,vg), nvpg[vg]);
00322       libmesh_assert_equal_to (this->n_comp_group(s,vg), 0);
00323     }
00324 
00325   for (unsigned int v=0; v<this->n_vars(s); v++)
00326     libmesh_assert_equal_to (this->n_comp(s,v), 0);
00327 
00328   // again, all other system sizes shoudl be unchanged!
00329   for (unsigned int s_ctr=0; s_ctr<this->n_systems(); s_ctr++)
00330     if (s_ctr != s)
00331       libmesh_assert_equal_to (this->n_var_groups(s_ctr), old_system_sizes[s_ctr]);
00332 
00333 #endif
00334 }
00335 
00336 
00337 
00338 void DofObject::set_n_comp(const unsigned int s,
00339                            const unsigned int var,
00340                            const unsigned int ncomp)
00341 {
00342   libmesh_assert_less (s,   this->n_systems());
00343   libmesh_assert_less (var, this->n_vars(s));
00344 
00345   this->set_n_comp_group(s, this->var_to_vg(s,var), ncomp);
00346 }
00347 
00348 
00349 
00350 void DofObject::set_n_comp_group(const unsigned int s,
00351                                  const unsigned int vg,
00352                                  const unsigned int ncomp)
00353 {
00354   libmesh_assert_less (s,  this->n_systems());
00355   libmesh_assert_less (vg, this->n_var_groups(s));
00356 
00357   // Check for trivial return
00358   if (ncomp == this->n_comp_group(s,vg)) return;
00359 
00360 #ifndef NDEBUG
00361   if (ncomp >= ncv_magic)
00362     {
00363       const index_t ncvm = ncv_magic;
00364       libmesh_error_msg("ERROR: ncomp must be less than DofObject::ncv_magic!\n" \
00365                         << "ncomp = "                                   \
00366                         << ncomp                                \
00367                         << ", ncv_magic = "                     \
00368                         << ncvm                                 \
00369                         << "\nrecompile and try again!");
00370     }
00371 #endif
00372 
00373   const unsigned int
00374     start_idx_sys = this->start_idx(s),
00375     n_vars_group  = this->n_vars(s,vg),
00376     base_offset   = start_idx_sys + 2*vg;
00377 
00378   libmesh_assert_less ((base_offset + 1), _idx_buf.size());
00379 
00380   // if (ncomp)
00381   //   libMesh::out << "s,vg,ncomp="
00382   //       << s  << ","
00383   //       << vg << ","
00384   //       << ncomp << '\n';
00385 
00386   // set the number of components, maintaining the number
00387   // of variables in the group
00388   _idx_buf[base_offset] = ncv_magic*n_vars_group + ncomp;
00389 
00390   // We use (invalid_id - 1) to signify no
00391   // components for this object
00392   _idx_buf[base_offset + 1] = (ncomp == 0) ? invalid_id - 1 : invalid_id;
00393 
00394   // this->debug_buffer();
00395   // libMesh::out << "s,vg = " << s << "," << vg << '\n'
00396   //     << "base_offset=" << base_offset << '\n'
00397   //     << "this->n_comp(s,vg)=" << this->n_comp(s,vg) << '\n'
00398   //     << "this->n_comp_group(s,vg)=" << this->n_comp_group(s,vg) << '\n'
00399   //     << "this->n_vars(s,vg)=" << this->n_vars(s,vg) << '\n'
00400   //     << "this->n_var_groups(s)=" << this->n_var_groups(s) << '\n';
00401 
00402   libmesh_assert_equal_to (ncomp, this->n_comp_group(s,vg));
00403 }
00404 
00405 
00406 
00407 void DofObject::set_dof_number(const unsigned int s,
00408                                const unsigned int var,
00409                                const unsigned int comp,
00410                                const dof_id_type dn)
00411 {
00412   libmesh_assert_less (s,    this->n_systems());
00413   libmesh_assert_less (var,  this->n_vars(s));
00414   libmesh_assert_less (comp, this->n_comp(s,var));
00415 
00416   const unsigned int
00417     vg            = this->var_to_vg(s,var),
00418 #ifndef NDEBUG
00419     ncg           = this->n_comp_group(s,vg),
00420 #endif
00421     vig           = this->system_var_to_vg_var(s,vg,var),
00422     start_idx_sys = this->start_idx(s);
00423 
00424   libmesh_assert_less ((start_idx_sys + 2*vg + 1), _idx_buf.size());
00425 
00426   dof_id_type &base_idx = _idx_buf[start_idx_sys + 2*vg + 1];
00427 
00428   // We intend to change all dof numbers together or not at all
00429   if (comp || vig)
00430     libmesh_assert ((dn == invalid_id && base_idx == invalid_id) ||
00431                     (dn == base_idx + vig*ncg + comp));
00432 
00433   // only explicitly store the base index for vig==0, comp==0
00434   else
00435     base_idx = dn;
00436 
00437   // #ifdef DEBUG
00438   //   libMesh::out << " [ ";
00439   //   for (unsigned int i=0; i<_idx_buf.size(); i++)
00440   //     libMesh::out << _idx_buf[i] << " ";
00441   //   libMesh::out << "]\n";
00442   // #endif
00443 
00444   libmesh_assert_equal_to (this->dof_number(s, var, comp), dn);
00445 }
00446 
00447 
00448 
00449 // FIXME: it'll be tricky getting this to work with 64-bit dof_id_type
00450 unsigned int DofObject::packed_indexing_size() const
00451 {
00452   return
00453     cast_int<unsigned int> (
00454 #ifdef LIBMESH_ENABLE_AMR
00455                             ((old_dof_object == NULL) ? 0 : old_dof_object->packed_indexing_size()) + 2 +
00456 #else
00457                             1 +
00458 #endif
00459                             _idx_buf.size());
00460 }
00461 
00462 
00463 
00464 // FIXME: it'll be tricky getting this to work with 64-bit dof_id_type
00465 unsigned int DofObject::unpackable_indexing_size
00466 (std::vector<largest_id_type>::const_iterator begin)
00467 {
00468 #ifdef LIBMESH_ENABLE_AMR
00469   const bool has_old_dof_object = cast_int<bool>(*begin++);
00470 
00471   static const int dof_header_size = 2;
00472 #else
00473   static const bool has_old_dof_object = false;
00474   static const int dof_header_size = 1;
00475 #endif
00476 
00477   const largest_id_type this_indexing_size = *begin++;
00478 
00479   return cast_int<unsigned int>
00480     (dof_header_size + this_indexing_size +
00481      (has_old_dof_object ?
00482       unpackable_indexing_size(begin+this_indexing_size) : 0));
00483 }
00484 
00485 
00486 // FIXME: it'll be tricky getting this to work with 64-bit dof_id_type
00487 void DofObject::unpack_indexing(std::vector<largest_id_type>::const_iterator begin)
00488 {
00489   _idx_buf.clear();
00490 
00491 #ifdef LIBMESH_ENABLE_AMR
00492   this->clear_old_dof_object();
00493   const bool has_old_dof_object = cast_int<bool>(*begin++);
00494 #endif
00495 
00496   const largest_id_type size = *begin++;
00497   _idx_buf.reserve(size);
00498   std::copy(begin, begin+size, back_inserter(_idx_buf));
00499 
00500   // Check as best we can for internal consistency now
00501   libmesh_assert(_idx_buf.empty() ||
00502                  (_idx_buf[0] <= _idx_buf.size()));
00503 #ifdef DEBUG
00504   if (!_idx_buf.empty())
00505     for (unsigned int i=1; i < _idx_buf[0]; ++i)
00506       {
00507         libmesh_assert_greater_equal (_idx_buf[i], _idx_buf[i-1]);
00508         libmesh_assert_equal_to ((_idx_buf[i] - _idx_buf[i-1])%2, 0);
00509         libmesh_assert_less_equal (_idx_buf[i], _idx_buf.size());
00510       }
00511 #endif
00512 
00513 #ifdef LIBMESH_ENABLE_AMR
00514   if (has_old_dof_object)
00515     {
00516       this->old_dof_object = new DofObject();
00517       this->old_dof_object->unpack_indexing(begin+size);
00518     }
00519 #endif
00520 }
00521 
00522 
00523 // FIXME: it'll be tricky getting this to work with 64-bit dof_id_type
00524 void DofObject::pack_indexing
00525 (std::back_insert_iterator<std::vector<largest_id_type> > target) const
00526 {
00527 #ifdef LIBMESH_ENABLE_AMR
00528   // We might need to pack old_dof_object too
00529   *target++ = (old_dof_object == NULL) ? 0 : 1;
00530 #endif
00531 
00532   *target++ = _idx_buf.size();
00533   std::copy(_idx_buf.begin(), _idx_buf.end(), target);
00534 
00535 #ifdef LIBMESH_ENABLE_AMR
00536   if (old_dof_object)
00537     old_dof_object->pack_indexing(target);
00538 #endif
00539 }
00540 
00541 
00542 
00543 void DofObject::debug_buffer () const
00544 {
00545   libMesh::out << " [ ";
00546   for (unsigned int i=0; i<_idx_buf.size(); i++)
00547     libMesh::out << _idx_buf[i] << " ";
00548   libMesh::out << "]\n";
00549 }
00550 
00551 
00552 
00553 } // namespace libMesh