$extrastylesheet
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