248 switch (cell->
dim()) {
250 return fe<1>(cell)->
n_dofs();
253 return fe<2>(cell)->
n_dofs();
256 return fe<3>(cell)->
n_dofs();
267 return fe<1>(cell)->dof(idof);
270 return fe<2>(cell)->dof(idof);
273 return fe<3>(cell)->dof(idof);
283 for (
unsigned int loc_el=0; loc_el<
el_ds_->
lsize(); ++loc_el)
289 for (
unsigned int gid=0; gid<
ghost_4_loc.size(); ++gid)
306 unsigned int n_node_dofs = 0;
310 node_dof_starts.push_back(n_node_dofs);
311 n_node_dofs +=
ds_->n_node_dofs(nid);
313 node_dof_starts.push_back(n_node_dofs);
320 for (
unsigned int loc_el=0; loc_el<
el_ds_->
lsize(); loc_el++)
324 for (
unsigned int n=0; n<cell->
dim()+1; n++)
332 for (
unsigned int gid=0; gid<
ghost_4_loc.size(); gid++)
337 for (
unsigned int n=0; n<cell->
dim()+1; n++)
361 unsigned int n_dofs_sum = 0;
362 for (
auto nd : n_dofs) n_dofs_sum += nd;
363 dofs.resize(n_dofs_sum);
371 unsigned int n_elems;
399 unsigned int dof_offset=0;
400 for (
unsigned int gid=0; gid<
ghost_proc_el[proc].size(); gid++)
404 for (
unsigned dof=0; dof<
n_dofs(cell); dof++)
408 for (
unsigned int idof = 0; idof<
n_dofs(cell); ++idof)
415 if (node_dofs[node_dof_starts[nid]+loc_node_dof_count[dof_nface_idx]] ==
INVALID_DOF)
416 node_dofs[node_dof_starts[nid]+loc_node_dof_count[dof_nface_idx]] = dofs[dof_offset+idof];
418 loc_node_dof_count[dof_nface_idx]++;
422 dof_offset +=
n_dofs(cell);
426 for (
unsigned int loc_el=0; loc_el <
el_ds_->
lsize(); loc_el++)
428 if (!update_cells[loc_el])
continue;
434 for (
unsigned int idof = 0; idof<
n_dofs(cell); ++idof)
444 loc_node_dof_count[dof_nface_idx]++;
455 OLD_ASSERT(
ds_ ==
nullptr,
"Attempt to distribute DOFs multiple times!");
462 unsigned int next_free_dof = 0;
466 node_dofs.resize(node_dof_starts[node_dof_starts.size()-1]);
471 for (
unsigned int loc_el=0; loc_el <
el_ds_->
lsize(); loc_el++)
477 for (
unsigned int idof = 0; idof<
n_dofs(cell); ++idof)
485 unsigned int node_dof_idx = node_dof_starts[nid]+loc_node_dof_count[dof_nface_idx];
487 switch (node_status[nid])
490 for (
int i=0; i<node_dof_starts[nid+1] - node_dof_starts[nid]; i++)
491 node_dofs[node_dof_starts[nid]+i] = next_free_dof++;
496 update_cells[loc_el] =
true;
500 loc_node_dof_count[dof_nface_idx]++;
502 else if (dof_dim == cell.
dim())
506 ASSERT(
false).error(
"Unsupported dof n_face.");
526 for (
unsigned int from_higher = 0; from_higher < 2; from_higher++)
530 if ((proc >
el_ds_->
myp()) == from_higher)
542 update_cells.clear();
544 node_dof_starts.clear();
552 ASSERT(
dof_indices.size() > 0).error(
"Attempt to create sequential dof handler from uninitialized or already sequential object!");
561 for (
unsigned int loc_el=0; loc_el<
el_ds_->
lsize(); ++loc_el)
567 cell_starts_loc[i+1] += cell_starts_loc[i];
571 for (
unsigned int loc_el=0; loc_el<
el_ds_->
lsize(); ++loc_el)
574 for (
unsigned int idof=0; idof<
n_dofs(cell); idof++)
588 cell_starts_loc.size(),
594 dof_indices_loc.size(),
607 unsigned int ndofs = 0;
611 for (
unsigned int k=0; k<ndofs; k++)
617 for (
unsigned int k=0; k<ndofs; k++)
628 unsigned int ndofs = 0;
632 for (
unsigned int k=0; k<ndofs; k++)
638 for (
unsigned int k=0; k<ndofs; k++)
659 for (
unsigned int iedg=0; iedg<
mesh_->
n_edges(); iedg++)
661 bool is_edge_local =
false;
663 for (
int sid=0; sid<edg->
n_sides; sid++)
666 is_edge_local =
true;
684 for (
unsigned int loc_el=0; loc_el<
el_ds_->
lsize(); loc_el++)
688 for (
unsigned int nid=0; nid<cell->
n_nodes(); nid++)
692 if (node_is_local[nid])
700 bool has_local_node =
false;
702 for (
unsigned int nid=0; nid<cell->n_nodes(); nid++)
705 has_local_node =
true;
#define MPI_Recv(buf, count, datatype, source, tag, comm, status)
void receive_ghost_dofs(unsigned int proc, std::vector< LongIdx > &dofs)
Obtain dof numbers on ghost elements from other processor.
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
unsigned int size() const
get global size
virtual ~DOFHandlerBase()
Destructor.
void create_sequential()
Communicate local dof indices to all processors.
void init_cell_starts()
Initialize vector of starting indices for elements.
Declaration of class which handles the ordering of degrees of freedom (dof) and mappings between loca...
LongIdx * el_4_loc
Local element index -> global element index.
unsigned int n_nodes() const
unsigned int get_loc_dof_indices(const ElementAccessor< 3 > &cell, std::vector< LongIdx > &indices) const override
Returns the indices of dofs associated to the cell on the local process.
LongIdx * get_row_4_el() const
std::vector< LongIdx > cell_starts_seq
Starting indices for element dofs (sequential version).
const std::vector< MeshObject > & objects(unsigned int dim) const
Distribution * el_ds_
Distribution of elements.
unsigned int dim
Association to n-face of given dimension (point, line, triangle, tetrahedron.
void distribute_dofs(std::shared_ptr< DiscreteSpace > ds, bool sequential=false)
Distributes degrees of freedom on the mesh needed for the given discrete space.
#define MPI_Send(buf, count, datatype, dest, tag, comm)
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
int el_index(int loc_el) const
Returns the global index of local element.
#define MPI_Allgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, comm)
void update_local_dofs(unsigned int proc, const std::vector< bool > &update_cells, const std::vector< LongIdx > &dofs, const std::vector< LongIdx > &node_dof_starts, std::vector< LongIdx > &node_dofs)
Update dofs on local elements from ghost element dofs.
ElementAccessor< 3 > element() const
unsigned int proc() const
Distribution * dof_ds_
Distribution of dofs associated to local process.
unsigned int lsize_
Number of dofs associated to local process.
virtual ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
unsigned int n_face_idx
Index of n-face to which the dof is associated.
unsigned int n_dofs(ElementAccessor< 3 > cell) const
Return number of dofs on given cell.
map< unsigned int, vector< LongIdx > > ghost_proc_el
Arrays of ghost cells for each neighbouring processor.
std::vector< LongIdx > dof_indices_seq
Dof numbers on mesh elements (sequential version).
void send_ghost_dofs(unsigned int proc)
Send dof numbers to other processor.
const unsigned int * get_lsizes_array()
get local sizes array
void init_node_status(std::vector< short int > &node_status)
Initialize node_status.
std::vector< LongIdx > cell_starts
Starting indices for element dofs (parallel version).
unsigned int n_vb_neighbours() const
ElementAccessor< 3 > element()
static const int VALID_NODE
unsigned int get_dof_indices(const ElementAccessor< 3 > &cell, std::vector< LongIdx > &indices) const override
Returns the global indices of dofs associated to the cell.
bool is_local(unsigned int idx) const
identify local index
const unsigned int * get_starts_array() const
get local starts array
Mesh * mesh_
Pointer to the mesh to which the dof handler is associated.
std::vector< LongIdx > dof_indices
Dof numbers on local and ghost elements (parallel version).
vector< LongIdx > nb_4_loc
Local neighbour index -> global neighbour index.
unsigned int max_elem_dofs_
Max. number of dofs per element.
vector< LongIdx > ghost_4_loc
Indices of ghost cells (neighbouring with local elements).
virtual Range< ElementAccessor< 3 > > elements_range() const
Returns range of bulk elements.
unsigned int n_nodes() const
void init_node_dof_starts(std::vector< LongIdx > &node_dof_starts)
Initialize auxiliary vector of starting indices of nodal dofs.
static const int ASSIGNED_NODE
Distribution * get_el_ds() const
void make_elem_partitioning()
Prepare parallel distribution of elements, edges and neighbours.
static const int INVALID_NODE
unsigned int myp() const
get my processor
Support classes for parallel programing.
#define MPI_Allreduce(sendbuf, recvbuf, count, datatype, op, comm)
vector< Neighbour > vb_neighbours_
#define MPI_STATUS_IGNORE
vector< LongIdx > edg_4_loc
Local edge index -> global edge index.
virtual unsigned int n_elements(bool boundary=false) const
Returns count of boundary or bulk elements.
unsigned int loffset_
Index of the first dof on the local process.
static const int INVALID_DOF
const Dof & cell_dof(ElementAccessor< 3 > cell, unsigned int idof) const
Return dof on a given cell.
set< unsigned int > ghost_proc
Processors of ghost elements.
~DOFHandlerMultiDim() override
Destructor.
vector< LongIdx > node_4_loc
Indices of local nodes in mesh tree.
std::vector< Edge > edges
Vector of MH edges, this should not be part of the geometrical mesh.
std::shared_ptr< DiscreteSpace > ds_
Pointer to the discrete space for which the handler distributes dofs.
Abstract class for description of finite elements.
unsigned int n_global_dofs_
Number of global dofs assigned by the handler.
unsigned int n_edges() const
bool el_is_local(int index) const
DOFHandlerMultiDim(Mesh &_mesh, bool make_elem_part=true)
Constructor.
const std::vector< unsigned int > & obj_4_el() const
Distribution * distr() const
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
LongIdx * get_el_4_loc() const
LongIdx * row_4_el
Global element index -> index according to partitioning.
SideIter side(const unsigned int i) const
Implementation of range helper class.
std::size_t hash() const override
unsigned int lsize(int proc) const
get local size