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