00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <set>
00024 #include <algorithm>
00025
00026
00027 #include "coupling_matrix.h"
00028 #include "dense_matrix.h"
00029 #include "dense_vector_base.h"
00030 #include "dof_map.h"
00031 #include "elem.h"
00032 #include "fe_interface.h"
00033 #include "fe_type.h"
00034 #include "fe_base.h"
00035 #include "libmesh_logging.h"
00036 #include "mesh_base.h"
00037 #include "mesh_tools.h"
00038 #include "numeric_vector.h"
00039 #include "parallel.h"
00040 #include "sparse_matrix.h"
00041 #include "string_to_enum.h"
00042 #include "threads_allocators.h"
00043
00044
00045
00046
00047
00048
00049 DofMap::~DofMap()
00050 {
00051 this->clear();
00052 }
00053
00054
00055
00056 void DofMap::add_variable (const System::Variable &var)
00057 {
00058 _variables.push_back (var);
00059 }
00060
00061
00062
00063 const System::Variable & DofMap::variable (const unsigned int c) const
00064 {
00065 libmesh_assert (c < _variables.size());
00066
00067 return _variables[c];
00068 }
00069
00070
00071
00072 Order DofMap::variable_order (const unsigned int c) const
00073 {
00074 libmesh_assert (c < _variables.size());
00075
00076 return _variables[c].type().order;
00077 }
00078
00079
00080
00081 const FEType& DofMap::variable_type (const unsigned int c) const
00082 {
00083 libmesh_assert (c < _variables.size());
00084
00085 return _variables[c].type();
00086 }
00087
00088
00089
00090 void DofMap::attach_matrix (SparseMatrix<Number>& matrix)
00091 {
00092 _matrices.push_back(&matrix);
00093
00094 matrix.attach_dof_map (*this);
00095 }
00096
00097
00098
00099 DofObject* DofMap::node_ptr(MeshBase& mesh, unsigned int i) const
00100 {
00101 return mesh.node_ptr(i);
00102 }
00103
00104
00105
00106 DofObject* DofMap::elem_ptr(MeshBase& mesh, unsigned int i) const
00107 {
00108 return mesh.elem(i);
00109 }
00110
00111
00112
00113 template <typename iterator_type>
00114 void DofMap::set_nonlocal_dof_objects(iterator_type objects_begin,
00115 iterator_type objects_end,
00116 MeshBase &mesh,
00117 dofobject_accessor objects)
00118 {
00119
00120 parallel_only();
00121
00122
00123
00124 std::vector<unsigned int>
00125 ghost_objects_from_proc(libMesh::n_processors(), 0);
00126
00127 iterator_type it = objects_begin;
00128
00129 for (; it != objects_end; ++it)
00130 {
00131 DofObject *obj = *it;
00132
00133 if (obj)
00134 {
00135 unsigned int obj_procid = obj->processor_id();
00136
00137 libmesh_assert(obj_procid != DofObject::invalid_processor_id);
00138 ghost_objects_from_proc[obj_procid]++;
00139 }
00140 }
00141
00142 std::vector<unsigned int> objects_on_proc(libMesh::n_processors(), 0);
00143 Parallel::allgather(ghost_objects_from_proc[libMesh::processor_id()],
00144 objects_on_proc);
00145
00146 #ifdef DEBUG
00147 for (unsigned int p=0; p != libMesh::n_processors(); ++p)
00148 libmesh_assert(ghost_objects_from_proc[p] <= objects_on_proc[p]);
00149 #endif
00150
00151
00152 std::vector<std::vector<unsigned int> >
00153 requested_ids(libMesh::n_processors());
00154
00155
00156
00157 for (unsigned int p=0; p != libMesh::n_processors(); ++p)
00158 if (p != libMesh::processor_id())
00159 requested_ids[p].reserve(ghost_objects_from_proc[p]);
00160
00161 for (it = objects_begin; it != objects_end; ++it)
00162 {
00163 DofObject *obj = *it;
00164 if (obj->processor_id() != DofObject::invalid_processor_id)
00165 requested_ids[obj->processor_id()].push_back(obj->id());
00166 }
00167 #ifdef DEBUG
00168 for (unsigned int p=0; p != libMesh::n_processors(); ++p)
00169 libmesh_assert(requested_ids[p].size() == ghost_objects_from_proc[p]);
00170 #endif
00171
00172
00173 for (unsigned int p=1; p != libMesh::n_processors(); ++p)
00174 {
00175
00176 unsigned int procup = (libMesh::processor_id() + p) %
00177 libMesh::n_processors();
00178 unsigned int procdown = (libMesh::n_processors() +
00179 libMesh::processor_id() - p) %
00180 libMesh::n_processors();
00181 std::vector<unsigned int> request_to_fill;
00182 Parallel::send_receive(procup, requested_ids[procup],
00183 procdown, request_to_fill);
00184
00185
00186 const unsigned int n_variables = this->n_variables();
00187
00188 std::vector<unsigned int> ghost_data
00189 (request_to_fill.size() * 2 * n_variables);
00190
00191 for (unsigned int i=0; i != request_to_fill.size(); ++i)
00192 {
00193 DofObject *requested = (this->*objects)(mesh, request_to_fill[i]);
00194 libmesh_assert(requested);
00195 libmesh_assert(requested->processor_id() == libMesh::processor_id());
00196 libmesh_assert(requested->n_vars(this->sys_number()) == n_variables);
00197 for (unsigned int v=0; v != n_variables; ++v)
00198 {
00199 unsigned int n_comp =
00200 requested->n_comp(this->sys_number(), v);
00201 ghost_data[i*2*n_variables+v] = n_comp;
00202 unsigned int first_dof = n_comp ?
00203 requested->dof_number(this->sys_number(), v, 0) : 0;
00204 libmesh_assert(first_dof != DofObject::invalid_id);
00205 ghost_data[i*2*n_variables+n_variables+v] = first_dof;
00206 }
00207 }
00208
00209
00210 std::vector<unsigned int> filled_request;
00211 Parallel::send_receive(procdown, ghost_data,
00212 procup, filled_request);
00213
00214
00215 libmesh_assert(filled_request.size() ==
00216 requested_ids[procup].size() * 2 * n_variables);
00217 for (unsigned int i=0; i != requested_ids[procup].size(); ++i)
00218 {
00219 DofObject *requested = (this->*objects)(mesh, requested_ids[procup][i]);
00220 libmesh_assert(requested);
00221 libmesh_assert (requested->processor_id() == procup);
00222 for (unsigned int v=0; v != n_variables; ++v)
00223 {
00224 unsigned int n_comp = filled_request[i*2*n_variables+v];
00225 requested->set_n_comp(this->sys_number(), v, n_comp);
00226 if (n_comp)
00227 {
00228 unsigned int first_dof =
00229 filled_request[i*2*n_variables+n_variables+v];
00230 libmesh_assert(first_dof != DofObject::invalid_id);
00231 requested->set_dof_number
00232 (this->sys_number(), v, 0, first_dof);
00233
00234
00235 for (unsigned int comp=0; comp!=n_comp; ++comp)
00236 _send_list.push_back(first_dof+comp);
00237 }
00238 }
00239 }
00240 }
00241
00242 #ifdef DEBUG
00243
00244 for (it = objects_begin; it != objects_end; ++it)
00245 {
00246 DofObject *obj = *it;
00247 libmesh_assert (obj);
00248 unsigned int n_variables = obj->n_vars(this->sys_number());
00249 for (unsigned int v=0; v != n_variables; ++v)
00250 {
00251 unsigned int n_comp =
00252 obj->n_comp(this->sys_number(), v);
00253 unsigned int first_dof = n_comp ?
00254 obj->dof_number(this->sys_number(), v, 0) : 0;
00255 libmesh_assert(first_dof != DofObject::invalid_id);
00256 }
00257 }
00258 #endif
00259 }
00260
00261
00262
00263 void DofMap::reinit(MeshBase& mesh)
00264 {
00265 libmesh_assert (mesh.is_prepared());
00266
00267 START_LOG("reinit()", "DofMap");
00268
00269
00270
00271 const unsigned int n_var = this->n_variables();
00272
00273 #ifdef LIBMESH_ENABLE_AMR
00274
00275
00276
00277
00278 {
00279 MeshBase::node_iterator node_it = mesh.nodes_begin();
00280 const MeshBase::node_iterator node_end = mesh.nodes_end();
00281
00282 for ( ; node_it != node_end; ++node_it)
00283 {
00284 (*node_it)->clear_old_dof_object();
00285 libmesh_assert ((*node_it)->old_dof_object == NULL);
00286 }
00287
00288 MeshBase::element_iterator elem_it = mesh.elements_begin();
00289 const MeshBase::element_iterator elem_end = mesh.elements_end();
00290
00291 for ( ; elem_it != elem_end; ++elem_it)
00292 {
00293 (*elem_it)->clear_old_dof_object();
00294 libmesh_assert ((*elem_it)->old_dof_object == NULL);
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303 {
00304 MeshBase::element_iterator elem_it = mesh.elements_begin();
00305 const MeshBase::element_iterator elem_end = mesh.elements_end();
00306
00307 for ( ; elem_it != elem_end; ++elem_it)
00308 {
00309 Elem* elem = *elem_it;
00310
00311
00312 if (elem->refinement_flag() == Elem::JUST_REFINED) continue;
00313
00314 for (unsigned int n=0; n<elem->n_nodes(); n++)
00315 {
00316 Node* node = elem->get_node(n);
00317
00318 if (node->old_dof_object == NULL)
00319 if (node->has_dofs())
00320 node->set_old_dof_object();
00321 }
00322
00323 libmesh_assert (elem->old_dof_object == NULL);
00324
00325 if (elem->has_dofs())
00326 elem->set_old_dof_object();
00327 }
00328 }
00329
00330 #endif // #ifdef LIBMESH_ENABLE_AMR
00331
00332
00333
00334
00335
00336
00337 {
00338
00339 MeshBase::node_iterator node_it = mesh.nodes_begin();
00340 const MeshBase::node_iterator node_end = mesh.nodes_end();
00341
00342 for ( ; node_it != node_end; ++node_it)
00343 (*node_it)->set_n_vars(this->sys_number(),n_var);
00344
00345
00346 MeshBase::element_iterator elem_it = mesh.elements_begin();
00347 const MeshBase::element_iterator elem_end = mesh.elements_end();
00348
00349 for ( ; elem_it != elem_end; ++elem_it)
00350 (*elem_it)->set_n_vars(this->sys_number(),n_var);
00351 }
00352
00353
00354
00355 this->_n_SCALAR_dofs = 0;
00356
00357
00358
00359 for (unsigned int var=0; var<this->n_variables(); var++)
00360 {
00361 const System::Variable &var_description = this->variable(var);
00362 const FEType& base_fe_type = this->variable_type(var);
00363
00364
00365
00366 if(base_fe_type.family == SCALAR)
00367 {
00368 this->_n_SCALAR_dofs += base_fe_type.order;
00369 continue;
00370 }
00371
00372
00373 const bool extra_hanging_dofs =
00374 FEInterface::extra_hanging_dofs(base_fe_type);
00375
00376
00377 MeshBase::element_iterator elem_it = mesh.active_elements_begin();
00378 const MeshBase::element_iterator elem_end = mesh.active_elements_end();
00379
00380
00381 for ( ; elem_it != elem_end; ++elem_it)
00382 {
00383 Elem* elem = *elem_it;
00384 libmesh_assert (elem != NULL);
00385
00386
00387
00388 if (!var_description.active_on_subdomain(elem->subdomain_id()))
00389 continue;
00390
00391 const ElemType type = elem->type();
00392 const unsigned int dim = elem->dim();
00393
00394 FEType fe_type = base_fe_type;
00395
00396 #ifdef LIBMESH_ENABLE_AMR
00397
00398
00399 if (elem->p_level() + base_fe_type.order >
00400 FEInterface::max_order(base_fe_type, type))
00401 {
00402 # ifdef DEBUG
00403 if (FEInterface::max_order(base_fe_type,type) <
00404 static_cast<unsigned int>(base_fe_type.order))
00405 {
00406 std::cerr << "ERROR: Finite element "
00407 << Utility::enum_to_string(base_fe_type.family)
00408 << " on geometric element "
00409 << Utility::enum_to_string(type) << std::endl
00410 << "only supports FEInterface::max_order = "
00411 << FEInterface::max_order(base_fe_type,type)
00412 << ", not fe_type.order = " << base_fe_type.order
00413 << std::endl;
00414
00415 libmesh_error();
00416 }
00417
00418 std::cerr << "WARNING: Finite element "
00419 << Utility::enum_to_string(base_fe_type.family)
00420 << " on geometric element "
00421 << Utility::enum_to_string(type) << std::endl
00422 << "could not be p refined past FEInterface::max_order = "
00423 << FEInterface::max_order(base_fe_type,type)
00424 << std::endl;
00425 # endif
00426 elem->set_p_level(FEInterface::max_order(base_fe_type,type)
00427 - base_fe_type.order);
00428 }
00429 #endif
00430
00431 fe_type.order = static_cast<Order>(fe_type.order +
00432 elem->p_level());
00433
00434
00435 for (unsigned int n=0; n<elem->n_nodes(); n++)
00436 {
00437 Node* node = elem->get_node(n);
00438
00439 if (elem->is_vertex(n))
00440 {
00441 const unsigned int old_node_dofs =
00442 node->n_comp(this->sys_number(), var);
00443
00444 const unsigned int vertex_dofs =
00445 std::max(FEInterface::n_dofs_at_node(dim, fe_type,
00446 type, n),
00447 old_node_dofs);
00448
00449
00450 if (vertex_dofs > old_node_dofs)
00451 {
00452 node->set_n_comp(this->sys_number(), var,
00453 vertex_dofs);
00454
00455
00456 node->set_dof_number(this->sys_number(),
00457 var, 0, vertex_dofs);
00458 }
00459 }
00460 }
00461 }
00462
00463
00464 elem_it = mesh.active_elements_begin();
00465
00466 for ( ; elem_it != elem_end; ++elem_it)
00467 {
00468 Elem* elem = *elem_it;
00469 libmesh_assert (elem != NULL);
00470
00471
00472
00473 if (!var_description.active_on_subdomain(elem->subdomain_id()))
00474 continue;
00475
00476 const ElemType type = elem->type();
00477 const unsigned int dim = elem->dim();
00478
00479 FEType fe_type = base_fe_type;
00480 fe_type.order = static_cast<Order>(fe_type.order +
00481 elem->p_level());
00482
00483
00484 for (unsigned int n=0; n<elem->n_nodes(); n++)
00485 {
00486 Node* node = elem->get_node(n);
00487
00488 const unsigned int old_node_dofs =
00489 node->n_comp(this->sys_number(), var);
00490
00491 const unsigned int vertex_dofs = old_node_dofs?
00492 node->dof_number (this->sys_number(),var,0):0;
00493
00494 const unsigned int new_node_dofs =
00495 FEInterface::n_dofs_at_node(dim, fe_type, type, n);
00496
00497
00498 if (elem->is_vertex(n))
00499 {
00500 libmesh_assert(old_node_dofs >= vertex_dofs);
00501 libmesh_assert(vertex_dofs >= new_node_dofs);
00502 }
00503
00504 else
00505 {
00506
00507
00508 if (!old_node_dofs)
00509 {
00510 node->set_n_comp(this->sys_number(), var,
00511 new_node_dofs);
00512
00513
00514 if (new_node_dofs)
00515 node->set_dof_number(this->sys_number(),
00516 var, 0, 0);
00517 }
00518
00519
00520
00521
00522 else if (vertex_dofs == 0)
00523 {
00524 if (new_node_dofs > old_node_dofs)
00525 {
00526 node->set_n_comp(this->sys_number(), var,
00527 new_node_dofs);
00528 node->set_dof_number(this->sys_number(),
00529 var, 0, vertex_dofs);
00530 }
00531 }
00532
00533
00534
00535 else if (extra_hanging_dofs)
00536 {
00537 if (new_node_dofs > old_node_dofs - vertex_dofs)
00538 {
00539 node->set_n_comp(this->sys_number(), var,
00540 vertex_dofs + new_node_dofs);
00541 node->set_dof_number(this->sys_number(),
00542 var, 0, vertex_dofs);
00543 }
00544 }
00545
00546
00547 else
00548 {
00549 libmesh_assert(old_node_dofs >= vertex_dofs);
00550 if (new_node_dofs > old_node_dofs)
00551 {
00552 node->set_n_comp(this->sys_number(), var,
00553 new_node_dofs);
00554 node->set_dof_number(this->sys_number(),
00555 var, 0, vertex_dofs);
00556 }
00557 }
00558 }
00559 }
00560
00561 const unsigned int dofs_per_elem =
00562 FEInterface::n_dofs_per_elem(dim, fe_type,
00563 type);
00564
00565 elem->set_n_comp(this->sys_number(), var, dofs_per_elem);
00566
00567 }
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 this->invalidate_dofs(mesh);
00595
00596 STOP_LOG("reinit()", "DofMap");
00597 }
00598
00599
00600
00601 void DofMap::invalidate_dofs(MeshBase& mesh) const
00602 {
00603 const unsigned int sys_num = this->sys_number();
00604
00605
00606 MeshBase::node_iterator node_it = mesh.nodes_begin();
00607 const MeshBase::node_iterator node_end = mesh.nodes_end();
00608
00609 for ( ; node_it != node_end; ++node_it)
00610 (*node_it)->invalidate_dofs(sys_num);
00611
00612
00613 MeshBase::element_iterator elem_it = mesh.active_elements_begin();
00614 const MeshBase::element_iterator elem_end = mesh.active_elements_end();
00615
00616 for ( ; elem_it != elem_end; ++elem_it)
00617 (*elem_it)->invalidate_dofs(sys_num);
00618 }
00619
00620
00621
00622 void DofMap::clear()
00623 {
00624
00625
00626
00627
00628
00629 _variables.clear();
00630 _first_df.clear();
00631 _end_df.clear();
00632 _var_first_local_df.clear();
00633 _send_list.clear();
00634 _n_nz.clear();
00635 _n_oz.clear();
00636
00637
00638 #ifdef LIBMESH_ENABLE_AMR
00639
00640 _dof_constraints.clear();
00641 _n_old_dfs = 0;
00642
00643 #endif
00644
00645 _matrices.clear();
00646
00647 _n_dfs = 0;
00648 }
00649
00650
00651
00652 void DofMap::distribute_dofs (MeshBase& mesh)
00653 {
00654
00655 parallel_only();
00656
00657
00658 START_LOG("distribute_dofs()", "DofMap");
00659
00660 libmesh_assert (mesh.is_prepared());
00661
00662 const unsigned int proc_id = libMesh::processor_id();
00663 const unsigned int n_proc = libMesh::n_processors();
00664
00665
00666 libmesh_assert (proc_id < n_proc);
00667
00668
00669 this->reinit(mesh);
00670
00671
00672
00673
00674 bool node_major_dofs = libMesh::on_command_line ("--node_major_dofs");
00675
00676
00677
00678 unsigned int next_free_dof = 0;
00679
00680
00681 _send_list.clear();
00682
00683
00684 if (node_major_dofs)
00685 this->distribute_local_dofs_node_major (next_free_dof, mesh);
00686 else
00687 this->distribute_local_dofs_var_major (next_free_dof, mesh);
00688
00689
00690 std::vector<unsigned int> dofs_on_proc(n_proc, 0);
00691 Parallel::allgather(next_free_dof, dofs_on_proc);
00692
00693
00694 _first_df.resize(n_proc);
00695 _end_df.resize (n_proc);
00696
00697
00698 _first_df[0] = 0;
00699 for (unsigned int i=1; i < n_proc; ++i)
00700 _first_df[i] = _end_df[i-1] = _first_df[i-1] + dofs_on_proc[i-1];
00701 _end_df[n_proc-1] = _first_df[n_proc-1] + dofs_on_proc[n_proc-1];
00702
00703
00704
00705 this->invalidate_dofs(mesh);
00706
00707 next_free_dof = _first_df[proc_id];
00708
00709
00710 if (node_major_dofs)
00711 this->distribute_local_dofs_node_major (next_free_dof, mesh);
00712 else
00713 this->distribute_local_dofs_var_major (next_free_dof, mesh);
00714
00715 libmesh_assert(next_free_dof == _end_df[proc_id]);
00716
00717
00718
00719
00720
00721
00722
00723 if (libMesh::n_processors() > 1)
00724 {
00725 this->set_nonlocal_dof_objects(mesh.nodes_begin(),
00726 mesh.nodes_end(),
00727 mesh, &DofMap::node_ptr);
00728
00729 this->set_nonlocal_dof_objects(mesh.elements_begin(),
00730 mesh.elements_end(),
00731 mesh, &DofMap::elem_ptr);
00732 }
00733
00734
00735 #ifdef LIBMESH_ENABLE_AMR
00736 _n_old_dfs = _n_dfs;
00737 #endif
00738 _n_dfs = _end_df[n_proc-1];
00739
00740 STOP_LOG("distribute_dofs()", "DofMap");
00741
00742
00743
00744
00745 this->add_neighbors_to_send_list(mesh);
00746
00747
00748
00749
00750
00751 }
00752
00753
00754 void DofMap::distribute_local_dofs_node_major(unsigned int &next_free_dof,
00755 MeshBase& mesh)
00756 {
00757 const unsigned int sys_num = this->sys_number();
00758 const unsigned int n_vars = this->n_variables();
00759
00760
00761
00762
00763
00764 _var_first_local_df.resize(n_vars+1);
00765 std::fill (_var_first_local_df.begin(),
00766 _var_first_local_df.end(),
00767 DofObject::invalid_id);
00768
00769
00770
00771 MeshBase::element_iterator elem_it = mesh.active_local_elements_begin();
00772 const MeshBase::element_iterator elem_end = mesh.active_local_elements_end();
00773
00774 for ( ; elem_it != elem_end; ++elem_it)
00775 {
00776
00777
00778 Elem* elem = *elem_it;
00779 const unsigned int n_nodes = elem->n_nodes();
00780
00781
00782 for (unsigned int n=0; n<n_nodes; n++)
00783 {
00784 Node* node = elem->get_node(n);
00785
00786 for (unsigned var=0; var<n_vars; var++)
00787 {
00788 if( (this->variable(var).type().family != SCALAR) &&
00789 (this->variable(var).active_on_subdomain(elem->subdomain_id())) )
00790 {
00791
00792
00793 if ((node->n_comp(sys_num,var) > 0) &&
00794 (node->processor_id() == libMesh::processor_id()) &&
00795 (node->dof_number(sys_num,var,0) ==
00796 DofObject::invalid_id))
00797 {
00798 node->set_dof_number(sys_num,
00799 var,
00800 0,
00801 next_free_dof);
00802 next_free_dof += node->n_comp(sys_num,var);
00803 }
00804 }
00805 }
00806 }
00807
00808
00809 for (unsigned var=0; var<n_vars; var++)
00810 if ( (this->variable(var).type().family != SCALAR) &&
00811 (this->variable(var).active_on_subdomain(elem->subdomain_id())) )
00812 if (elem->n_comp(sys_num,var) > 0)
00813 {
00814 libmesh_assert (elem->dof_number(sys_num,var,0) ==
00815 DofObject::invalid_id);
00816
00817 elem->set_dof_number(sys_num,
00818 var,
00819 0,
00820 next_free_dof);
00821
00822 next_free_dof += elem->n_comp(sys_num,var);
00823 }
00824 }
00825
00826
00827 this->_n_SCALAR_dofs = 0;
00828 for (unsigned var=0; var<n_vars; var++)
00829 {
00830 if( this->variable(var).type().family == SCALAR )
00831 {
00832 this->_n_SCALAR_dofs += this->variable(var).type().order;
00833 continue;
00834 }
00835 }
00836
00837
00838
00839 if ( libMesh::processor_id() == (libMesh::n_processors()-1) )
00840 next_free_dof += _n_SCALAR_dofs;
00841
00842 #ifdef DEBUG
00843
00844 MeshTools::libmesh_assert_valid_node_procids(mesh);
00845
00846 MeshBase::node_iterator node_it = mesh.local_nodes_begin();
00847 const MeshBase::node_iterator node_end = mesh.local_nodes_end();
00848 for (; node_it != node_end; ++node_it)
00849 {
00850 Node *obj = *node_it;
00851 libmesh_assert(obj);
00852 unsigned int n_variables = obj->n_vars(this->sys_number());
00853 for (unsigned int v=0; v != n_variables; ++v)
00854 {
00855 unsigned int n_comp =
00856 obj->n_comp(this->sys_number(), v);
00857 unsigned int first_dof = n_comp ?
00858 obj->dof_number(this->sys_number(), v, 0) : 0;
00859 libmesh_assert(first_dof != DofObject::invalid_id);
00860 }
00861 }
00862 #endif // DEBUG
00863 }
00864
00865
00866
00867 void DofMap::distribute_local_dofs_var_major(unsigned int &next_free_dof,
00868 MeshBase& mesh)
00869 {
00870 const unsigned int sys_num = this->sys_number();
00871 const unsigned int n_vars = this->n_variables();
00872
00873
00874
00875
00876
00877 _var_first_local_df.clear();
00878
00879
00880
00881 for (unsigned var=0; var<n_vars; var++)
00882 {
00883 _var_first_local_df.push_back(next_free_dof);
00884
00885 const System::Variable var_description = this->variable(var);
00886
00887
00888 if(var_description.type().family == SCALAR)
00889 continue;
00890
00891 MeshBase::element_iterator elem_it = mesh.active_local_elements_begin();
00892 const MeshBase::element_iterator elem_end = mesh.active_local_elements_end();
00893
00894 for ( ; elem_it != elem_end; ++elem_it)
00895 {
00896
00897
00898 Elem* elem = *elem_it;
00899
00900
00901
00902 if (!var_description.active_on_subdomain(elem->subdomain_id()))
00903 continue;
00904
00905 const unsigned int n_nodes = elem->n_nodes();
00906
00907
00908 for (unsigned int n=0; n<n_nodes; n++)
00909 {
00910 Node* node = elem->get_node(n);
00911
00912
00913
00914 if ((node->n_comp(sys_num,var) > 0) &&
00915 (node->processor_id() == libMesh::processor_id()) &&
00916 (node->dof_number(sys_num,var,0) ==
00917 DofObject::invalid_id))
00918 {
00919 node->set_dof_number(sys_num,
00920 var,
00921 0,
00922 next_free_dof);
00923 next_free_dof += node->n_comp(sys_num,var);
00924 }
00925 }
00926
00927
00928 if (elem->n_comp(sys_num,var) > 0)
00929 {
00930 libmesh_assert (elem->dof_number(sys_num,var,0) ==
00931 DofObject::invalid_id);
00932
00933 elem->set_dof_number(sys_num,
00934 var,
00935 0,
00936 next_free_dof);
00937
00938 next_free_dof += elem->n_comp(sys_num,var);
00939 }
00940 }
00941 }
00942
00943
00944 this->_n_SCALAR_dofs = 0;
00945 for (unsigned var=0; var<n_vars; var++)
00946 {
00947 if( this->variable(var).type().family == SCALAR )
00948 {
00949 this->_n_SCALAR_dofs += this->variable(var).type().order;
00950 continue;
00951 }
00952 }
00953
00954
00955
00956 if ( libMesh::processor_id() == (libMesh::n_processors()-1) )
00957 next_free_dof += _n_SCALAR_dofs;
00958
00959
00960 _var_first_local_df.push_back(next_free_dof);
00961
00962 #ifdef DEBUG
00963
00964 MeshTools::libmesh_assert_valid_node_procids(mesh);
00965
00966 MeshBase::node_iterator node_it = mesh.local_nodes_begin();
00967 const MeshBase::node_iterator node_end = mesh.local_nodes_end();
00968 for (; node_it != node_end; ++node_it)
00969 {
00970 Node *obj = *node_it;
00971 libmesh_assert(obj);
00972 unsigned int n_variables = obj->n_vars(this->sys_number());
00973 for (unsigned int v=0; v != n_variables; ++v)
00974 {
00975 unsigned int n_comp =
00976 obj->n_comp(this->sys_number(), v);
00977 unsigned int first_dof = n_comp ?
00978 obj->dof_number(this->sys_number(), v, 0) : 0;
00979 libmesh_assert(first_dof != DofObject::invalid_id);
00980 }
00981 }
00982 #endif // DEBUG
00983 }
00984
00985
00986
00987 void DofMap::add_neighbors_to_send_list(MeshBase& mesh)
00988 {
00989 START_LOG("add_neighbors_to_send_list()", "DofMap");
00990
00991
00992
00993
00994
00995
00996 MeshBase::const_element_iterator local_elem_it
00997 = mesh.active_local_elements_begin();
00998 const MeshBase::const_element_iterator local_elem_end
00999 = mesh.active_local_elements_end();
01000
01001 std::vector<bool> node_on_processor(mesh.max_node_id(), false);
01002 std::vector<unsigned int> di;
01003 std::vector<const Elem *> family;
01004
01005
01006
01007 for ( ; local_elem_it != local_elem_end; ++local_elem_it)
01008 {
01009 const Elem* elem = *local_elem_it;
01010
01011
01012 for (unsigned int n=0; n!=elem->n_nodes(); n++)
01013 node_on_processor[elem->node(n)] = true;
01014
01015
01016 for (unsigned int s=0; s<elem->n_neighbors(); s++)
01017 if (elem->neighbor(s) != NULL)
01018 {
01019 family.clear();
01020
01021
01022 #ifdef LIBMESH_ENABLE_AMR
01023 if (!elem->neighbor(s)->active())
01024 elem->neighbor(s)->active_family_tree_by_neighbor(family, elem);
01025 else
01026 #endif
01027 family.push_back(elem->neighbor(s));
01028
01029 for (unsigned int i=0; i!=family.size(); ++i)
01030
01031 if (family[i]->processor_id() != libMesh::processor_id())
01032 {
01033
01034 this->dof_indices (family[i], di);
01035
01036
01037 for (unsigned int j=0; j != di.size(); ++j)
01038 if (di[j] < this->first_dof() ||
01039 di[j] >= this->end_dof())
01040 _send_list.push_back(di[j]);
01041 }
01042 }
01043 }
01044
01045
01046
01047 MeshBase::const_element_iterator elem_it
01048 = mesh.active_elements_begin();
01049 const MeshBase::const_element_iterator elem_end
01050 = mesh.active_elements_end();
01051
01052 for ( ; elem_it != elem_end; ++elem_it)
01053 {
01054 const Elem* elem = *elem_it;
01055
01056
01057 if (elem->processor_id() == libMesh::processor_id())
01058 continue;
01059
01060
01061 bool add_elem_dofs = false;
01062
01063
01064
01065 for (unsigned int n=0; n!=elem->n_nodes(); n++)
01066 if (node_on_processor[elem->node(n)])
01067 add_elem_dofs = true;
01068
01069
01070
01071 if (add_elem_dofs)
01072 {
01073
01074 this->dof_indices (elem, di);
01075
01076
01077 for (unsigned int j=0; j != di.size(); ++j)
01078 if (di[j] < this->first_dof() ||
01079 di[j] >= this->end_dof())
01080 _send_list.push_back(di[j]);
01081 }
01082 }
01083
01084 STOP_LOG("add_neighbors_to_send_list()", "DofMap");
01085 }
01086
01087
01088
01089 void DofMap::prepare_send_list ()
01090 {
01091 START_LOG("prepare_send_list()", "DofMap");
01092
01093
01094
01095
01096 std::sort(_send_list.begin(), _send_list.end());
01097
01098
01099 std::vector<unsigned int>::iterator new_end =
01100 std::unique (_send_list.begin(), _send_list.end());
01101
01102
01103
01104 std::vector<unsigned int> (_send_list.begin(), new_end).swap (_send_list);
01105
01106 STOP_LOG("prepare_send_list()", "DofMap");
01107 }
01108
01109
01110
01111 bool DofMap::use_coupled_neighbor_dofs(const MeshBase& mesh) const
01112 {
01113
01114
01115 bool implicit_neighbor_dofs =
01116 libMesh::on_command_line ("--implicit_neighbor_dofs");
01117
01118
01119
01120
01121 {
01122 bool all_discontinuous_dofs = true;
01123
01124 for (unsigned int var=0; var<this->n_variables(); var++)
01125 if (FEBase::build (mesh.mesh_dimension(),
01126 this->variable_type(var))->get_continuity() != DISCONTINUOUS)
01127 all_discontinuous_dofs = false;
01128
01129 if (all_discontinuous_dofs)
01130 implicit_neighbor_dofs = true;
01131 }
01132
01133 return implicit_neighbor_dofs;
01134 }
01135
01136
01137
01138 void DofMap::compute_sparsity(const MeshBase& mesh)
01139 {
01140 libmesh_assert (mesh.is_prepared());
01141 libmesh_assert (this->n_variables());
01142
01143 START_LOG("compute_sparsity()", "DofMap");
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153 bool need_full_sparsity_pattern=false;
01154 std::vector<SparseMatrix<Number>* >::iterator
01155 pos = _matrices.begin(),
01156 end = _matrices.end();
01157
01158 for (; pos != end; ++pos)
01159 if ((*pos)->need_full_sparsity_pattern())
01160 need_full_sparsity_pattern = true;
01161
01162
01163
01164 bool implicit_neighbor_dofs = this->use_coupled_neighbor_dofs(mesh);
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 SparsityPattern::Build sp (mesh,
01175 *this,
01176 _dof_coupling,
01177 implicit_neighbor_dofs,
01178 need_full_sparsity_pattern);
01179
01180 Threads::parallel_reduce (ConstElemRange (mesh.active_elements_begin(),
01181 mesh.active_elements_end()), sp);
01182
01183 #ifndef NDEBUG
01184
01185 const unsigned int proc_id = mesh.processor_id();
01186 const unsigned int n_dofs_on_proc = this->n_dofs_on_processor(proc_id);
01187 #endif
01188 libmesh_assert (sp.sparsity_pattern.size() == n_dofs_on_proc);
01189
01190
01191
01192 _n_nz.swap(sp.n_nz);
01193 _n_oz.swap(sp.n_oz);
01194
01195 STOP_LOG("compute_sparsity()", "DofMap");
01196
01197
01198
01199
01200
01201 pos = _matrices.begin();
01202 end = _matrices.end();
01203
01204 for (; pos != end; ++pos)
01205 (*pos)->update_sparsity_pattern (sp.sparsity_pattern);
01206 }
01207
01208
01209
01210 void DofMap::extract_local_vector (const NumericVector<Number>& Ug,
01211 const std::vector<unsigned int>& dof_indices,
01212 DenseVectorBase<Number>& Ue) const
01213 {
01214 #ifdef LIBMESH_ENABLE_AMR
01215
01216
01217 libmesh_assert (dof_indices.size() == Ue.size());
01218 bool has_constrained_dofs = false;
01219
01220 for (unsigned int il=0; il<dof_indices.size(); il++)
01221 {
01222 const unsigned int ig = dof_indices[il];
01223
01224 if (this->is_constrained_dof (ig)) has_constrained_dofs = true;
01225
01226 libmesh_assert ((il >= Ug.first_local_index()) &&
01227 (il < Ug.last_local_index()));
01228
01229 Ue.el(il) = Ug(ig);
01230 }
01231
01232
01233
01234
01235 if (has_constrained_dofs)
01236 {
01237
01238 std::vector<unsigned int> constrained_dof_indices(dof_indices);
01239
01240 DenseMatrix<Number> C;
01241
01242 this->build_constraint_matrix (C, constrained_dof_indices);
01243
01244 libmesh_assert (dof_indices.size() == C.m());
01245 libmesh_assert (constrained_dof_indices.size() == C.n());
01246
01247
01248 Ue.zero();
01249
01250
01251 for (unsigned int i=0; i<dof_indices.size(); i++)
01252 for (unsigned int j=0; j<constrained_dof_indices.size(); j++)
01253 {
01254 const unsigned int jg = constrained_dof_indices[j];
01255
01256 libmesh_assert ((jg >= Ug.first_local_index()) &&
01257 (jg < Ug.last_local_index()));
01258
01259 Ue.el(i) += C(i,j)*Ug(jg);
01260 }
01261 }
01262
01263 #else
01264
01265
01266 libmesh_assert (dof_indices.size() == Ue.size());
01267
01268 for (unsigned int il=0; il<dof_indices.size(); il++)
01269 {
01270 const unsigned int ig = dof_indices[il];
01271
01272 libmesh_assert ((ig >= Ug.first_local_index()) && (ig < Ug.last_local_index()));
01273
01274 Ue.el(il) = Ug(ig);
01275 }
01276
01277 #endif
01278 }
01279
01280 void DofMap::dof_indices (const Elem* const elem,
01281 std::vector<unsigned int>& di,
01282 const unsigned int vn) const
01283 {
01284 START_LOG("dof_indices()", "DofMap");
01285
01286 libmesh_assert (elem != NULL);
01287
01288 const unsigned int n_nodes = elem->n_nodes();
01289 const ElemType type = elem->type();
01290 const unsigned int sys_num = this->sys_number();
01291 const unsigned int n_vars = this->n_variables();
01292 const unsigned int dim = elem->dim();
01293
01294
01295 di.clear();
01296
01297 #ifdef DEBUG
01298
01299 unsigned int tot_size = 0;
01300 #endif
01301
01302
01303
01304 std::vector<unsigned int> SCALAR_var_numbers;
01305 SCALAR_var_numbers.clear();
01306
01307
01308 for (unsigned int v=0; v<n_vars; v++)
01309 if ((v == vn) || (vn == libMesh::invalid_uint))
01310 {
01311 if(this->variable(v).type().family == SCALAR)
01312 {
01313
01314 SCALAR_var_numbers.push_back(v);
01315
01316 #ifdef DEBUG
01317 FEType fe_type = this->variable_type(v);
01318 tot_size += FEInterface::n_dofs(dim,
01319 fe_type,
01320 type);
01321 #endif
01322 }
01323 else
01324 if (this->variable(v).active_on_subdomain(elem->subdomain_id()))
01325 {
01326
01327
01328
01329 FEType fe_type = this->variable_type(v);
01330 fe_type.order = static_cast<Order>(fe_type.order +
01331 elem->p_level());
01332
01333 const bool extra_hanging_dofs =
01334 FEInterface::extra_hanging_dofs(fe_type);
01335
01336 #ifdef DEBUG
01337 tot_size += FEInterface::n_dofs(dim,
01338 fe_type,
01339 type);
01340 #endif
01341
01342
01343 for (unsigned int n=0; n<n_nodes; n++)
01344 {
01345 const Node* node = elem->get_node(n);
01346
01347
01348
01349
01350
01351 const unsigned int nc = FEInterface::n_dofs_at_node (dim,
01352 fe_type,
01353 type,
01354 n);
01355
01356
01357
01358
01359
01360 if (extra_hanging_dofs && !elem->is_vertex(n))
01361 {
01362 const int dof_offset = node->n_comp(sys_num,v) - nc;
01363
01364
01365
01366
01367 if (dof_offset < 0)
01368 {
01369 libmesh_assert(!elem->active());
01370 di.resize(di.size() + nc, DofObject::invalid_id);
01371 }
01372 else
01373 for (int i=node->n_comp(sys_num,v)-1; i>=dof_offset; i--)
01374 {
01375 libmesh_assert (node->dof_number(sys_num,v,i) !=
01376 DofObject::invalid_id);
01377 di.push_back(node->dof_number(sys_num,v,i));
01378 }
01379 }
01380
01381
01382
01383 else
01384 for (unsigned int i=0; i<nc; i++)
01385 {
01386 libmesh_assert (node->dof_number(sys_num,v,i) !=
01387 DofObject::invalid_id);
01388 di.push_back(node->dof_number(sys_num,v,i));
01389 }
01390 }
01391
01392
01393 const unsigned int nc = FEInterface::n_dofs_per_elem(dim,
01394 fe_type,
01395 type);
01396
01397
01398
01399 if (nc != 0)
01400 {
01401 if (elem->n_systems() > sys_num &&
01402 nc <= elem->n_comp(sys_num,v))
01403 {
01404 for (unsigned int i=0; i<nc; i++)
01405 {
01406 libmesh_assert (elem->dof_number(sys_num,v,i) !=
01407 DofObject::invalid_id);
01408
01409 di.push_back(elem->dof_number(sys_num,v,i));
01410 }
01411 }
01412 else
01413 {
01414 libmesh_assert(!elem->active() || fe_type.family == LAGRANGE);
01415 di.resize(di.size() + nc, DofObject::invalid_id);
01416 }
01417 }
01418 }
01419 }
01420
01421
01422 std::vector<unsigned int> di_new;
01423 std::vector<unsigned int>::iterator it = SCALAR_var_numbers.begin();
01424 std::vector<unsigned int>::const_iterator it_end = SCALAR_var_numbers.end();
01425 for( ; it != it_end; ++it)
01426 {
01427 this->SCALAR_dof_indices(di_new,*it);
01428 di.insert( di.end(), di_new.begin(), di_new.end());
01429 }
01430
01431 #ifdef DEBUG
01432 libmesh_assert (tot_size == di.size());
01433 #endif
01434
01435 STOP_LOG("dof_indices()", "DofMap");
01436 }
01437
01438 void DofMap::SCALAR_dof_indices (std::vector<unsigned int>& di,
01439 const unsigned int vn,
01440 const bool old_dofs) const
01441 {
01442 START_LOG("SCALAR_dof_indices()", "DofMap");
01443
01444 if(this->variable(vn).type().family != SCALAR)
01445 {
01446 std::cerr << "ERROR: SCALAR_dof_indices called for a non-SCALAR variable."
01447 << std::endl;
01448 }
01449
01450
01451 di.clear();
01452
01453
01454
01455 unsigned int first_SCALAR_dof_index = (old_dofs ? n_old_dofs() : n_dofs()) - n_SCALAR_dofs();
01456 std::map<unsigned int, unsigned int> SCALAR_first_dof_index;
01457 SCALAR_first_dof_index.clear();
01458
01459
01460
01461 for (unsigned int v=0; v<this->n_variables(); v++)
01462 if(this->variable(v).type().family == SCALAR)
01463 {
01464 unsigned int current_n_SCALAR_dofs = this->variable(v).type().order;
01465 SCALAR_first_dof_index.insert(
01466 std::pair<unsigned int, unsigned int>(v,first_SCALAR_dof_index) );
01467 first_SCALAR_dof_index += current_n_SCALAR_dofs;
01468 }
01469
01470
01471 std::map<unsigned int, unsigned int>::const_iterator iter =
01472 SCALAR_first_dof_index.find(vn);
01473
01474 #ifdef DEBUG
01475 libmesh_assert(iter != SCALAR_first_dof_index.end());
01476 #endif
01477
01478 unsigned int current_first_SCALAR_dof_index = iter->second;
01479
01480
01481 unsigned int current_n_SCALAR_dofs = this->variable(vn).type().order;
01482
01483 for(unsigned int j=0; j<current_n_SCALAR_dofs; j++)
01484 {
01485 unsigned int index = current_first_SCALAR_dof_index+j;
01486 di.push_back(index);
01487 }
01488
01489 STOP_LOG("SCALAR_dof_indices()", "DofMap");
01490 }
01491
01492
01493 #ifdef LIBMESH_ENABLE_AMR
01494
01495 void DofMap::old_dof_indices (const Elem* const elem,
01496 std::vector<unsigned int>& di,
01497 const unsigned int vn) const
01498 {
01499 START_LOG("old_dof_indices()", "DofMap");
01500
01501 libmesh_assert (elem != NULL);
01502 libmesh_assert (elem->old_dof_object != NULL);
01503
01504
01505 const unsigned int n_nodes = elem->n_nodes();
01506 const ElemType type = elem->type();
01507 const unsigned int sys_num = this->sys_number();
01508 const unsigned int n_vars = this->n_variables();
01509 const unsigned int dim = elem->dim();
01510
01511
01512 di.clear();
01513
01514 #ifdef DEBUG
01515
01516 unsigned int tot_size = 0;
01517 #endif
01518
01519
01520
01521 std::vector<unsigned int> SCALAR_var_numbers;
01522 SCALAR_var_numbers.clear();
01523
01524
01525 for (unsigned int v=0; v<n_vars; v++)
01526 if ((v == vn) || (vn == libMesh::invalid_uint))
01527 {
01528 if(this->variable(v).type().family == SCALAR)
01529 {
01530
01531 SCALAR_var_numbers.push_back(v);
01532
01533 #ifdef DEBUG
01534 FEType fe_type = this->variable_type(v);
01535 tot_size += FEInterface::n_dofs(dim,
01536 fe_type,
01537 type);
01538 #endif
01539 }
01540 else
01541 if (this->variable(v).active_on_subdomain(elem->subdomain_id()))
01542 {
01543
01544
01545
01546
01547
01548 int p_adjustment = 0;
01549 if (elem->p_refinement_flag() == Elem::JUST_REFINED)
01550 {
01551 libmesh_assert (elem->p_level() > 0);
01552 p_adjustment = -1;
01553 }
01554 else if (elem->p_refinement_flag() == Elem::JUST_COARSENED)
01555 {
01556 p_adjustment = 1;
01557 }
01558 FEType fe_type = this->variable_type(v);
01559 fe_type.order = static_cast<Order>(fe_type.order +
01560 elem->p_level() +
01561 p_adjustment);
01562
01563 const bool extra_hanging_dofs =
01564 FEInterface::extra_hanging_dofs(fe_type);
01565
01566 #ifdef DEBUG
01567 tot_size += FEInterface::n_dofs(dim,
01568 fe_type,
01569 type);
01570 #endif
01571
01572
01573 for (unsigned int n=0; n<n_nodes; n++)
01574 {
01575 const Node* node = elem->get_node(n);
01576
01577
01578
01579
01580
01581 const unsigned int nc = FEInterface::n_dofs_at_node (dim,
01582 fe_type,
01583 type,
01584 n);
01585 libmesh_assert (node->old_dof_object != NULL);
01586
01587
01588
01589
01590
01591 if (extra_hanging_dofs && !elem->is_vertex(n))
01592 {
01593 const int dof_offset =
01594 node->old_dof_object->n_comp(sys_num,v) - nc;
01595
01596
01597
01598
01599 if (dof_offset < 0)
01600 {
01601 libmesh_assert(!elem->active() || elem->refinement_flag() ==
01602 Elem::JUST_COARSENED);
01603 di.resize(di.size() + nc, DofObject::invalid_id);
01604 }
01605 else
01606 for (int i=node->old_dof_object->n_comp(sys_num,v)-1;
01607 i>=dof_offset; i--)
01608 {
01609 libmesh_assert (node->old_dof_object->dof_number(sys_num,v,i) !=
01610 DofObject::invalid_id);
01611 di.push_back(node->old_dof_object->dof_number(sys_num,v,i));
01612 }
01613 }
01614
01615
01616
01617 else
01618 for (unsigned int i=0; i<nc; i++)
01619 {
01620 libmesh_assert (node->old_dof_object->dof_number(sys_num,v,i) !=
01621 DofObject::invalid_id);
01622 di.push_back(node->old_dof_object->dof_number(sys_num,v,i));
01623 }
01624 }
01625
01626
01627 const unsigned int nc = FEInterface::n_dofs_per_elem(dim,
01628 fe_type,
01629 type);
01630
01631
01632
01633
01634 if (nc != 0)
01635 {
01636 if (elem->old_dof_object->n_systems() > sys_num &&
01637 nc <= elem->old_dof_object->n_comp(sys_num,v))
01638 {
01639 libmesh_assert (elem->old_dof_object != NULL);
01640
01641 for (unsigned int i=0; i<nc; i++)
01642 {
01643 libmesh_assert (elem->old_dof_object->dof_number(sys_num,v,i) !=
01644 DofObject::invalid_id);
01645
01646 di.push_back(elem->old_dof_object->dof_number(sys_num,v,i));
01647 }
01648 }
01649 else
01650 {
01651 libmesh_assert(!elem->active() || fe_type.family == LAGRANGE ||
01652 elem->refinement_flag() == Elem::JUST_COARSENED);
01653 di.resize(di.size() + nc, DofObject::invalid_id);
01654 }
01655 }
01656 }
01657 }
01658
01659
01660 std::vector<unsigned int> di_new;
01661 std::vector<unsigned int>::iterator it = SCALAR_var_numbers.begin();
01662 std::vector<unsigned int>::const_iterator it_end = SCALAR_var_numbers.end();
01663 for( ; it != it_end; ++it)
01664 {
01665 this->SCALAR_dof_indices(di_new,*it,true);
01666 di.insert( di.end(), di_new.begin(), di_new.end());
01667 }
01668
01669 #ifdef DEBUG
01670 libmesh_assert (tot_size == di.size());
01671 #endif
01672
01673 STOP_LOG("old_dof_indices()", "DofMap");
01674 }
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732 #endif // LIBMESH_ENABLE_AMR
01733
01734
01735 #if defined(LIBMESH_ENABLE_AMR) || defined(LIBMESH_ENABLE_PERIODIC)
01736
01737 void DofMap::find_connected_dofs (std::vector<unsigned int>& elem_dofs) const
01738 {
01739 typedef std::set<unsigned int> RCSet;
01740
01741
01742 RCSet dof_set (elem_dofs.begin(), elem_dofs.end());
01743
01744 bool done = true;
01745
01746
01747
01748
01749
01750
01751 for (unsigned int i=0; i<elem_dofs.size(); i++)
01752 if (this->is_constrained_dof(elem_dofs[i]))
01753 {
01754
01755 DofConstraints::const_iterator
01756 pos = _dof_constraints.find(elem_dofs[i]);
01757
01758 libmesh_assert (pos != _dof_constraints.end());
01759
01760 const DofConstraintRow& constraint_row = pos->second;
01761
01762
01763
01764
01765
01766 DofConstraintRow::const_iterator it = constraint_row.begin();
01767 DofConstraintRow::const_iterator it_end = constraint_row.end();
01768
01769
01770
01771
01772
01773 for ( ; it != it_end; ++it)
01774 if (!dof_set.count (it->first))
01775 {
01776 dof_set.insert (it->first);
01777 done = false;
01778 }
01779 }
01780
01781
01782
01783
01784 if (!done)
01785 {
01786
01787 elem_dofs.clear();
01788 elem_dofs.insert (elem_dofs.end(),
01789 dof_set.begin(), dof_set.end());
01790
01791
01792
01793
01794
01795 this->find_connected_dofs (elem_dofs);
01796
01797 }
01798 }
01799
01800 #endif // LIBMESH_ENABLE_AMR || LIBMESH_ENABLE_PERIODIC
01801
01802
01803
01804 #if defined(__GNUC__) && (__GNUC__ < 4) && !defined(__INTEL_COMPILER)
01805
01806 void SparsityPattern::_dummy_function(void)
01807 {
01808 }
01809
01810 #endif
01811
01812
01813
01814 void SparsityPattern::Build::operator()(const ConstElemRange &range)
01815 {
01816
01817
01818
01819
01820 const unsigned int proc_id = mesh.processor_id();
01821 const unsigned int n_dofs_on_proc = dof_map.n_dofs_on_processor(proc_id);
01822 const unsigned int first_dof_on_proc = dof_map.first_dof(proc_id);
01823 const unsigned int end_dof_on_proc = dof_map.end_dof(proc_id);
01824
01825 sparsity_pattern.resize(n_dofs_on_proc);
01826
01827
01828
01829
01830
01831 if ((dof_coupling == NULL) || (dof_coupling->empty()))
01832 {
01833 std::vector<unsigned int>
01834 element_dofs,
01835 neighbor_dofs,
01836 dofs_to_add;
01837
01838 std::vector<const Elem*> active_neighbors;
01839
01840 for (ConstElemRange::const_iterator elem_it = range.begin() ; elem_it != range.end(); ++elem_it)
01841 {
01842 const Elem* const elem = *elem_it;
01843
01844
01845 dof_map.dof_indices (elem, element_dofs);
01846 #if defined(LIBMESH_ENABLE_AMR) || defined(LIBMESH_ENABLE_PERIODIC)
01847 dof_map.find_connected_dofs (element_dofs);
01848 #endif
01849
01850
01851
01852 std::sort(element_dofs.begin(), element_dofs.end());
01853
01854 const unsigned int n_dofs_on_element = element_dofs.size();
01855
01856 for (unsigned int i=0; i<n_dofs_on_element; i++)
01857 {
01858 const unsigned int ig = element_dofs[i];
01859
01860
01861
01862 if ((ig >= first_dof_on_proc) &&
01863 (ig < end_dof_on_proc))
01864 {
01865
01866
01867
01868
01869 libmesh_assert (ig >= first_dof_on_proc);
01870 libmesh_assert ((ig - first_dof_on_proc) < sparsity_pattern.size());
01871
01872 SparsityPattern::Row &row = sparsity_pattern[ig - first_dof_on_proc];
01873
01874
01875
01876 if (row.empty())
01877 {
01878 row.insert(row.end(),
01879 element_dofs.begin(),
01880 element_dofs.end());
01881 }
01882 else
01883 {
01884
01885
01886 dofs_to_add.clear();
01887
01888
01889
01890 SparsityPattern::Row::iterator
01891 low = std::lower_bound (row.begin(), row.end(), element_dofs.front()),
01892 high = std::upper_bound (low, row.end(), element_dofs.back());
01893
01894 for (unsigned int j=0; j<n_dofs_on_element; j++)
01895 {
01896 const unsigned int jg = element_dofs[j];
01897
01898
01899 std::pair<SparsityPattern::Row::iterator,
01900 SparsityPattern::Row::iterator>
01901 pos = std::equal_range (low, high, jg);
01902
01903
01904 if (pos.first == pos.second)
01905 dofs_to_add.push_back(jg);
01906
01907
01908
01909
01910 low = pos.first;
01911 }
01912
01913
01914 if (!dofs_to_add.empty())
01915 {
01916 const unsigned int old_size = row.size();
01917
01918 row.insert (row.end(),
01919 dofs_to_add.begin(),
01920 dofs_to_add.end());
01921
01922 SparsityPattern::sort_row (row.begin(), row.begin()+old_size, row.end());
01923 }
01924 }
01925
01926
01927
01928 if (implicit_neighbor_dofs)
01929 for (unsigned int s=0; s<elem->n_sides(); s++)
01930 if (elem->neighbor(s) != NULL)
01931 {
01932 const Elem* const neighbor_0 = elem->neighbor(s);
01933 #ifdef LIBMESH_ENABLE_AMR
01934 neighbor_0->active_family_tree_by_neighbor(active_neighbors,elem);
01935 #else
01936 active_neighbors.clear();
01937 active_neighbors.push_back(neighbor_0);
01938 #endif
01939
01940 for (unsigned int a=0; a != active_neighbors.size(); ++a)
01941 {
01942 const Elem *neighbor = active_neighbors[a];
01943
01944 dof_map.dof_indices (neighbor, neighbor_dofs);
01945 #if defined(LIBMESH_ENABLE_AMR) || defined(LIBMESH_ENABLE_PERIODIC)
01946 dof_map.find_connected_dofs (neighbor_dofs);
01947 #endif
01948 const unsigned int n_dofs_on_neighbor = neighbor_dofs.size();
01949
01950 for (unsigned int j=0; j<n_dofs_on_neighbor; j++)
01951 {
01952 const unsigned int jg = neighbor_dofs[j];
01953
01954
01955 std::pair<SparsityPattern::Row::iterator,
01956 SparsityPattern::Row::iterator>
01957 pos = std::equal_range (row.begin(), row.end(), jg);
01958
01959
01960 if (pos.first == pos.second)
01961 row.insert (pos.first, jg);
01962 }
01963 }
01964 }
01965 }
01966 }
01967 }
01968 }
01969
01970
01971
01972
01973
01974 else
01975 {
01976 libmesh_assert (dof_coupling != NULL);
01977 libmesh_assert (dof_coupling->size() ==
01978 dof_map.n_variables());
01979
01980 const unsigned int n_var = dof_map.n_variables();
01981
01982 std::vector<unsigned int>
01983 element_dofs_i,
01984 element_dofs_j,
01985 dofs_to_add;
01986
01987
01988 for (ConstElemRange::const_iterator elem_it = range.begin() ; elem_it != range.end(); ++elem_it)
01989 for (unsigned int vi=0; vi<n_var; vi++)
01990 {
01991 const Elem* const elem = *elem_it;
01992
01993
01994 dof_map.dof_indices (elem, element_dofs_i, vi);
01995 #if defined(LIBMESH_ENABLE_AMR) || defined(LIBMESH_ENABLE_PERIODIC)
01996 dof_map.find_connected_dofs (element_dofs_i);
01997 #endif
01998
01999
02000
02001 std::sort(element_dofs_i.begin(), element_dofs_i.end());
02002 const unsigned int n_dofs_on_element_i = element_dofs_i.size();
02003
02004 for (unsigned int vj=0; vj<n_var; vj++)
02005 if ((*dof_coupling)(vi,vj))
02006 {
02007
02008
02009 if (vi != vj)
02010 {
02011 dof_map.dof_indices (elem, element_dofs_j, vj);
02012 #if defined(LIBMESH_ENABLE_AMR) || defined(LIBMESH_ENABLE_PERIODIC)
02013 dof_map.find_connected_dofs (element_dofs_j);
02014 #endif
02015
02016
02017
02018 std::sort (element_dofs_j.begin(), element_dofs_j.end());
02019 }
02020 else
02021 element_dofs_j = element_dofs_i;
02022
02023 const unsigned int n_dofs_on_element_j =
02024 element_dofs_j.size();
02025
02026 for (unsigned int i=0; i<n_dofs_on_element_i; i++)
02027 {
02028 const unsigned int ig = element_dofs_i[i];
02029
02030
02031
02032
02033
02034
02035
02036
02037 if ((ig >= first_dof_on_proc) &&
02038 (ig < end_dof_on_proc))
02039 {
02040
02041
02042
02043
02044 libmesh_assert (ig >= first_dof_on_proc);
02045 libmesh_assert (ig < (sparsity_pattern.size() +
02046 first_dof_on_proc));
02047
02048 SparsityPattern::Row &row = sparsity_pattern[ig - first_dof_on_proc];
02049
02050
02051
02052 if (row.empty())
02053 {
02054 row.insert(row.end(),
02055 element_dofs_j.begin(),
02056 element_dofs_j.end());
02057 }
02058 else
02059 {
02060
02061
02062 dofs_to_add.clear();
02063
02064
02065
02066 SparsityPattern::Row::iterator
02067 low = std::lower_bound (row.begin(), row.end(), element_dofs_j.front()),
02068 high = std::upper_bound (low, row.end(), element_dofs_j.back());
02069
02070 for (unsigned int j=0; j<n_dofs_on_element_j; j++)
02071 {
02072 const unsigned int jg = element_dofs_j[j];
02073
02074
02075 std::pair<SparsityPattern::Row::iterator,
02076 SparsityPattern::Row::iterator>
02077 pos = std::equal_range (low, high, jg);
02078
02079
02080 if (pos.first == pos.second)
02081 dofs_to_add.push_back(jg);
02082
02083
02084
02085
02086 low = pos.first;
02087 }
02088
02089
02090 if (!dofs_to_add.empty())
02091 {
02092 const unsigned int old_size = row.size();
02093
02094 row.insert (row.end(),
02095 dofs_to_add.begin(),
02096 dofs_to_add.end());
02097
02098 SparsityPattern::sort_row (row.begin(), row.begin()+old_size, row.end());
02099 }
02100 }
02101 }
02102 }
02103 }
02104 }
02105 }
02106
02107
02108
02109 n_nz.resize (n_dofs_on_proc);
02110 n_oz.resize (n_dofs_on_proc);
02111
02112
02113 std::fill(n_nz.begin(), n_nz.end(), 0);
02114 std::fill(n_oz.begin(), n_oz.end(), 0);
02115
02116 for (unsigned int i=0; i<n_dofs_on_proc; i++)
02117 {
02118
02119 const SparsityPattern::Row &row = sparsity_pattern[i];
02120
02121 for (unsigned int j=0; j<row.size(); j++)
02122 if ((row[j] < first_dof_on_proc) || (row[j] >= end_dof_on_proc))
02123 n_oz[i]++;
02124 else
02125 n_nz[i]++;
02126 }
02127 }
02128
02129
02130
02131 void SparsityPattern::Build::join (const SparsityPattern::Build &other)
02132 {
02133 const unsigned int proc_id = mesh.processor_id();
02134 const unsigned int n_global_dofs = dof_map.n_dofs();
02135 const unsigned int n_dofs_on_proc = dof_map.n_dofs_on_processor(proc_id);
02136 const unsigned int first_dof_on_proc = dof_map.first_dof(proc_id);
02137 const unsigned int end_dof_on_proc = dof_map.end_dof(proc_id);
02138
02139 libmesh_assert (sparsity_pattern.size() == other.sparsity_pattern.size());
02140 libmesh_assert (n_nz.size() == sparsity_pattern.size());
02141 libmesh_assert (n_oz.size() == sparsity_pattern.size());
02142
02143 for (unsigned int r=0; r<n_dofs_on_proc; r++)
02144 {
02145
02146
02147 n_nz[r] += other.n_nz[r]; n_nz[r] = std::min(n_nz[r], n_dofs_on_proc);
02148 n_oz[r] += other.n_oz[r]; n_oz[r] = std::min(n_oz[r], n_global_dofs-n_nz[r]);
02149
02150 if (need_full_sparsity_pattern)
02151 {
02152 SparsityPattern::Row &my_row = sparsity_pattern[r];
02153 const SparsityPattern::Row &their_row = other.sparsity_pattern[r];
02154
02155
02156 if (my_row.empty())
02157 my_row = their_row;
02158
02159
02160 else if (!their_row.empty())
02161 {
02162 my_row.insert (my_row.end(),
02163 their_row.begin(),
02164 their_row.end());
02165
02166
02167
02168
02169 std::sort (my_row.begin(), my_row.end());
02170
02171 my_row.erase(std::unique (my_row.begin(), my_row.end()), my_row.end());
02172 }
02173
02174
02175 n_nz[r] = n_oz[r] = 0;
02176
02177 for (unsigned int j=0; j<my_row.size(); j++)
02178 if ((my_row[j] < first_dof_on_proc) || (my_row[j] >= end_dof_on_proc))
02179 n_oz[r]++;
02180 else
02181 n_nz[r]++;
02182 }
02183 }
02184 }