//----------------------------------------------------------------------------- std::map<std::size_t, std::size_t> Extrapolation::compute_unique_dofs(const Cell& cell, const FunctionSpace& V, std::size_t& row, std::set<std::size_t>& unique_dofs) { dolfin_assert(V.dofmap()); const ArrayView<const dolfin::la_index> dofs = V.dofmap()->cell_dofs(cell.index()); // Data structure for current cell std::map<std::size_t, std::size_t> dof2row; for (std::size_t i = 0; i < V.dofmap()->num_element_dofs(cell.index()); ++i) { // Ignore if this degree of freedom is already considered if (unique_dofs.find(dofs[i]) != unique_dofs.end()) continue; // Put global index into unique_dofs unique_dofs.insert(dofs[i]); // Map local dof index to current matrix row-index dof2row[i] = row; // Increase row index row++; } return dof2row; }
//----------------------------------------------------------------------------- DirichletBC::LocalData::LocalData(const FunctionSpace& V) : w(V.dofmap()->max_element_dofs(), 0.0), facet_dofs(V.dofmap()->num_facet_dofs(), 0), coordinates(boost::extents[V.dofmap()->max_element_dofs()][V.mesh()->geometry().dim()]) { // Do nothing }
void Prolongation(const FunctionSpace& V, const Array<double>& Gx, const Array<double>& Gy, const Array<double>& Gz, double * dataX, double * dataY, double * dataZ) { const Mesh mesh = *V.mesh(); const GenericDofMap& dofmap_u = *V.dofmap(); const int n = mesh.num_cells(); const int m = mesh.num_edges(); std::vector<int> edge2dof; edge2dof.reserve(m); Cell* dolfin_cell; for (int i = 0; i < n; ++i) { dolfin_cell = new Cell(mesh, i); std::vector<int> cellDOF = dofmap_u.cell_dofs(i); const uint* edgeVALUES = dolfin_cell->entities(1); for (int j = 0; j < cellDOF.size(); ++j) { edge2dof[edgeVALUES[j]]=cellDOF[j]; } } Edge* dolfin_edge; int k = -1; for (int i = 0; i < m; ++i) { k = k + 1; dolfin_edge = new Edge(mesh, i); dataX[k] =Gx[dolfin_edge->index()]/2; dataY[k] =Gy[dolfin_edge->index()]/2; dataZ[k] =Gz[dolfin_edge->index()]/2; k = k + 1; dataX[k] =Gx[dolfin_edge->index()]/2; dataY[k] =Gy[dolfin_edge->index()]/2; dataZ[k] =Gz[dolfin_edge->index()]/2; } }
//----------------------------------------------------------------------------- SubSpace::SubSpace(const FunctionSpace& V, const std::vector<std::size_t>& component) : FunctionSpace(V.mesh(), V.element(), V.dofmap()) { // Extract subspace and assign std::shared_ptr<FunctionSpace> _function_space(V.extract_sub_space(component)); *static_cast<FunctionSpace*>(this) = *_function_space; }
//----------------------------------------------------------------------------- SubSpace::SubSpace(const FunctionSpace& V, std::size_t component, std::size_t sub_component) : FunctionSpace(V.mesh(), V.element(), V.dofmap()) { // Create array std::vector<std::size_t> c = {{component, sub_component}}; // Extract subspace and assign std::shared_ptr<FunctionSpace> _function_space(V.extract_sub_space(c)); *static_cast<FunctionSpace*>(this) = *_function_space; }
void Gradient(const FunctionSpace& V, const Array<int>& Mapping, double * column, double * row, double * data) { const Mesh mesh = *V.mesh(); const GenericDofMap& dofmap_u = *V.dofmap(); const int n = mesh.num_cells(); const int m = mesh.num_edges(); std::vector<int> edge2dof; edge2dof.reserve(m); Cell* dolfin_cell; for (int i = 0; i < n; ++i) { dolfin_cell = new Cell(mesh, i); std::vector<int> cellDOF = dofmap_u.cell_dofs(i); const uint* edgeVALUES = dolfin_cell->entities(1); for (int j = 0; j < cellDOF.size(); ++j) { edge2dof[edgeVALUES[j]]=cellDOF[j]; } } Edge* dolfin_edge; int k = -1; for (int i = 0; i < m; ++i) { dolfin_edge = new Edge(mesh, i); const uint* edgeVERTICES = dolfin_edge->entities(0); k = k+1; row[k]=edge2dof[dolfin_edge->index()]; column[k]=Mapping[edgeVERTICES[0]]; data[k]=-1; k = k+1; row[k]=edge2dof[dolfin_edge->index()]; column[k]=Mapping[edgeVERTICES[1]]; data[k]=1; } }
void extract_dof_component_map(std::map<std::size_t, std::size_t>& dof_component_map, const FunctionSpace& VV, int* component) { // Extract sub dofmaps recursively and store dof to component map boost::unordered_map<std::size_t, std::size_t> collapsed_map; boost::unordered_map<std::size_t, std::size_t>::iterator map_it; std::vector<std::size_t> comp(1); if (VV.element()->num_sub_elements() == 0) { boost::shared_ptr<GenericDofMap> dummy = VV.dofmap()->collapse(collapsed_map, *VV.mesh()); (*component)++; for (map_it =collapsed_map.begin(); map_it!=collapsed_map.end(); ++map_it) dof_component_map[map_it->second] = (*component); } else { for (std::size_t i=0; i<VV.element()->num_sub_elements(); i++) { comp[0] = i; boost::shared_ptr<FunctionSpace> Vs = VV.extract_sub_space(comp); extract_dof_component_map(dof_component_map, *Vs, component); } } }
//----------------------------------------------------------------------------- std::vector<dolfin::la_index> dolfin::vertex_to_dof_map(const FunctionSpace& space) { // Get the mesh dolfin_assert(space.mesh()); dolfin_assert(space.dofmap()); const Mesh& mesh = *space.mesh(); const GenericDofMap& dofmap = *space.dofmap(); if (dofmap.is_view()) { dolfin_error("fem_utils.cpp", "tabulate vertex to dof map", "Cannot tabulate vertex_to_dof_map for a subspace"); } // Initialize vertex to cell connections const std::size_t top_dim = mesh.topology().dim(); mesh.init(0, top_dim); // Num dofs per vertex const std::size_t dofs_per_vertex = dofmap.num_entity_dofs(0); const std::size_t vert_per_cell = mesh.topology()(top_dim, 0).size(0); if (vert_per_cell*dofs_per_vertex != dofmap.max_element_dofs()) { dolfin_error("DofMap.cpp", "tabulate dof to vertex map", "Can only tabulate dofs on vertices"); } // Allocate data for tabulating local to local map std::vector<std::size_t> local_to_local_map(dofs_per_vertex); // Create return data structure std::vector<dolfin::la_index> return_map(dofs_per_vertex*mesh.num_entities(0)); // Iterate over vertices std::size_t local_vertex_ind = 0; for (VertexIterator vertex(mesh, "all"); !vertex.end(); ++vertex) { // Get the first cell connected to the vertex const Cell cell(mesh, vertex->entities(top_dim)[0]); // Find local vertex number #ifdef DEBUG bool vertex_found = false; #endif for (std::size_t i = 0; i < cell.num_entities(0); i++) { if (cell.entities(0)[i] == vertex->index()) { local_vertex_ind = i; #ifdef DEBUG vertex_found = true; #endif break; } } dolfin_assert(vertex_found); // Get all cell dofs const ArrayView<const dolfin::la_index> cell_dofs = dofmap.cell_dofs(cell.index()); // Tabulate local to local map of dofs on local vertex dofmap.tabulate_entity_dofs(local_to_local_map, 0, local_vertex_ind); // Fill local dofs for the vertex for (std::size_t local_dof = 0; local_dof < dofs_per_vertex; local_dof++) { const dolfin::la_index global_dof = cell_dofs[local_to_local_map[local_dof]]; return_map[dofs_per_vertex*vertex->index() + local_dof] = global_dof; } } // Return the map return return_map; }
void ProlongationP(const FunctionSpace& V, const Array<int>& Mapping, const Array<double>& X, const Array<double>& Y, const Array<double>& Z, double * dataX, double * dataY, double * dataZ) { const Mesh mesh = *V.mesh(); const GenericDofMap& dofmap_u = *V.dofmap(); const int n = mesh.num_cells(); const int m = mesh.num_edges(); const int dim = mesh.geometry().dim(); // std::vector<double> coord = mesh.coordinates(); // /* // even are the x coords... // odd are the y coords... // */ // std::vector<double> X; // std::vector<double> Y; // std::vector<double> Z; // for (int i = 0; i < coord.size()/dim; ++i) // { // if (dim == 2) { // std::cout << 2*i << std::endl; // X.push_back(coord[2*i]); // Y.push_back(coord[2*i+1]); // } // else { // std::cout << 3*i << std::endl; // X.push_back(coord[3*i]); // Y.push_back(coord[3*i+1]); // Z.push_back(coord[3*i+2]); // } // } std::vector<double> tangent; std::vector<double> Ntangent; tangent.reserve(dim); Ntangent.reserve(dim); Edge* dolfin_edge; int k = -1; for (int i = 0; i < m; ++i) { k = k + 1; dolfin_edge = new Edge(mesh, i); const uint* edgeVERTICES = dolfin_edge->entities(0); tangent[0] = (X[edgeVERTICES[1]]-X[edgeVERTICES[0]]); tangent[1] = (Y[edgeVERTICES[1]]-Y[edgeVERTICES[0]]); if (dim == 3) { tangent[2] = Z[edgeVERTICES[1]]-Z[edgeVERTICES[0]]; } for (int j = 0; j < dim; ++j) { if (dim == 3) { if (tangent[0] == 0 && tangent[1] == 0 && tangent[2] == 0){ Ntangent[j] =0; } else { Ntangent[j] = tangent[j]/(sqrt(pow(tangent[0],2.0)+pow(tangent[1],2.0)+pow(tangent[2],2.0))); } } else { if (tangent[0] == 0 && tangent[1] == 0){ Ntangent[j] =0; } else { Ntangent[j] = tangent[j]/(sqrt(pow(tangent[0],2.0)+pow(tangent[1],2.0))); } } } double len = sqrt(pow(tangent[0],2.0)+pow(tangent[1],2.0)); // std::cout << len << " , " << dolfin_edge->length() << std::endl; dataX[k]=0.5*dolfin_edge->length()*Ntangent[0]; dataY[k]=0.5*dolfin_edge->length()*Ntangent[1]; if (dim == 3) { dataZ[k]=0.5*dolfin_edge->length()*Ntangent[2]; } k = k + 1; dataX[k]=0.5*dolfin_edge->length()*Ntangent[0]; dataY[k]=0.5*dolfin_edge->length()*Ntangent[1]; if (dim == 3) { dataZ[k]=0.5*dolfin_edge->length()*Ntangent[2]; } } }
void ProlongationGrad(const FunctionSpace& V, double * dataX, double * dataY, double * dataZ, double * data, double * row, double * column) { const Mesh mesh = *V.mesh(); const GenericDofMap& dofmap_u = *V.dofmap(); const int n = mesh.num_cells(); const int m = mesh.num_edges(); const int dim = mesh.geometry().dim(); std::vector<double> coord = mesh.coordinates(); /* even are the x coords... odd are the y coords... */ std::vector<double> X; std::vector<double> Y; std::vector<double> Z; for (int i = 0; i < coord.size()/dim; ++i) { if (dim == 2) { // std::cout << 2*i << std::endl; X.push_back(coord[2*i]); Y.push_back(coord[2*i+1]); } else { // std::cout << 3*i << std::endl; X.push_back(coord[3*i]); Y.push_back(coord[3*i+1]); Z.push_back(coord[3*i+2]); } } std::vector<double> tangent; std::vector<double> Ntangent; tangent.reserve(dim); Ntangent.reserve(dim); Edge* dolfin_edge; int k = -1; for (int i = 0; i < m; ++i) { k = k + 1; dolfin_edge = new Edge(mesh, i); const uint* edgeVERTICES = dolfin_edge->entities(0); tangent[0] = (X[edgeVERTICES[1]]-X[edgeVERTICES[0]]); tangent[1] = (Y[edgeVERTICES[1]]-Y[edgeVERTICES[0]]); if (dim == 3) { tangent[2] = Z[edgeVERTICES[1]]-Z[edgeVERTICES[0]]; } for (int j = 0; j < dim; ++j) { if (dim == 3) { if (tangent[0] == 0 && tangent[1] == 0 && tangent[2] == 0){ Ntangent[j] =0; } else { Ntangent[j] = tangent[j]/(sqrt(pow(tangent[0],2.0)+pow(tangent[1],2.0)+pow(tangent[2],2.0))); } } else { if (tangent[0] == 0 && tangent[1] == 0){ Ntangent[j] =0; } else { Ntangent[j] = tangent[j]/(sqrt(pow(tangent[0],2.0)+pow(tangent[1],2.0))); } } } // double len = sqrt(pow(tangent[0],2.0)+pow(tangent[1],2.0)); // std::cout << len << " , " << dolfin_edge->length() << std::endl; dataX[k]=0.5*dolfin_edge->length()*Ntangent[0]; dataY[k]=0.5*dolfin_edge->length()*Ntangent[1]; if (dim == 3) { dataZ[k]=0.5*dolfin_edge->length()*Ntangent[2]; } data[k] = -1; row[k] = i; column[k] = edgeVERTICES[0]; // std::cout << dataX[k] << std::endl; k = k + 1; dataX[k]=0.5*dolfin_edge->length()*Ntangent[0]; dataY[k]=0.5*dolfin_edge->length()*Ntangent[1]; if (dim == 3) { dataZ[k]=0.5*dolfin_edge->length()*Ntangent[2]; } data[k] = 1; row[k] = i; column[k] = edgeVERTICES[1]; // std::cout << dataX[k] << std::endl; } }
//----------------------------------------------------------------------------- void Extrapolation::compute_coefficients( std::vector<std::vector<double>>& coefficients, const Function& v, const FunctionSpace& V, const FunctionSpace& W, const Cell& cell0, const std::vector<double>& coordinate_dofs0, const ufc::cell& c0, const ArrayView<const dolfin::la_index>& dofs, std::size_t& offset) { // Call recursively for mixed elements dolfin_assert(V.element()); const std::size_t num_sub_spaces = V.element()->num_sub_elements(); if (num_sub_spaces > 0) { for (std::size_t k = 0; k < num_sub_spaces; k++) { compute_coefficients(coefficients, v[k], *V[k], *W[k], cell0, coordinate_dofs0, c0, dofs, offset); } return; } // Build data structures for keeping track of unique dofs std::map<std::size_t, std::map<std::size_t, std::size_t>> cell2dof2row; std::set<std::size_t> unique_dofs; build_unique_dofs(unique_dofs, cell2dof2row, cell0, V); // Compute size of linear system dolfin_assert(W.element()); const std::size_t N = W.element()->space_dimension(); const std::size_t M = unique_dofs.size(); // Check size of system if (M < N) { dolfin_error("Extrapolation.cpp", "compute extrapolation", "Not enough degrees of freedom on local patch to build extrapolation"); } // Create matrix and vector for linear system Eigen::MatrixXd A(M, N); Eigen::VectorXd b(M); // Add equations on cell and neighboring cells dolfin_assert(V.mesh()); ufc::cell c1; std::vector<double> coordinate_dofs1; // Get unique set of surrounding cells (including cell0) std::set<std::size_t> cell_set; for (VertexIterator vtx(cell0); !vtx.end(); ++vtx) { for (CellIterator cell1(*vtx); !cell1.end(); ++cell1) cell_set.insert(cell1->index()); } for (auto cell_it : cell_set) { if (cell2dof2row[cell_it].empty()) continue; Cell cell1(cell0.mesh(), cell_it); cell1.get_coordinate_dofs(coordinate_dofs1); cell1.get_cell_data(c1); add_cell_equations(A, b, cell0, cell1, coordinate_dofs0, coordinate_dofs1, c0, c1, V, W, v, cell2dof2row[cell_it]); } // Solve least squares system const Eigen::VectorXd x = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b); // Insert resulting coefficients into global coefficient vector dolfin_assert(W.dofmap()); for (std::size_t i = 0; i < W.dofmap()->num_element_dofs(cell0.index()); ++i) coefficients[dofs[i + offset]].push_back(x[i]); // Increase offset offset += W.dofmap()->num_element_dofs(cell0.index()); }
//----------------------------------------------------------------------------- void XMLFunctionData::build_dof_map(std::vector<std::vector<la_index>>& dof_map, const FunctionSpace& V) { // Get mesh and dofmap dolfin_assert(V.mesh()); dolfin_assert(V.dofmap()); const Mesh& mesh = *V.mesh(); const GenericDofMap& dofmap = *V.dofmap(); // Get local-to-global map std::vector<std::size_t> local_to_global_dof; dofmap.tabulate_local_to_global_dofs(local_to_global_dof); // Get global number of cells const std::size_t num_cells = MPI::sum(mesh.mpi_comm(), mesh.num_cells()); std::vector<dolfin::la_index> local_dofmap; if (MPI::size(mesh.mpi_comm()) > 1) { // Check that local-to-global cell numbering is available const std::size_t D = mesh.topology().dim(); dolfin_assert(mesh.topology().have_global_indices(D)); // Build dof map data with global cell indices std::vector<la_index> cell_dofs_global; for (CellIterator cell(mesh); !cell.end(); ++cell) { const std::size_t local_cell_index = cell->index(); const std::size_t global_cell_index = cell->global_index(); auto cell_dofs = dofmap.cell_dofs(local_cell_index); local_dofmap.push_back(global_cell_index); local_dofmap.push_back(cell_dofs.size()); cell_dofs_global.resize(cell_dofs.size()); for(Eigen::Index i = 0; i < cell_dofs.size(); ++i) cell_dofs_global[i] = local_to_global_dof[cell_dofs[i]]; // Insert global dof indices local_dofmap.insert(local_dofmap.end(), cell_dofs_global.data(), cell_dofs_global.data() + cell_dofs_global.size()); } } else { // Build dof map data for (CellIterator cell(mesh); !cell.end(); ++cell) { const std::size_t local_cell_index = cell->index(); local_dofmap.push_back(local_cell_index); local_dofmap.push_back(dofmap.cell_dofs(local_cell_index).size()); auto dmap = dofmap.cell_dofs(local_cell_index); local_dofmap.insert(local_dofmap.end(), dmap.data(), dmap.data() + dmap.size()); } } // Gather dof map data on root process std::vector<dolfin::la_index> gathered_dofmap; MPI::gather(mesh.mpi_comm(), local_dofmap, gathered_dofmap); // Build global dofmap on root process if (MPI::rank(mesh.mpi_comm()) == 0) { dof_map.resize(num_cells); for (std::size_t i = 0; i < gathered_dofmap.size(); ) { const std::size_t global_cell_index = gathered_dofmap[i++]; const std::size_t num_dofs = gathered_dofmap[i++]; for (std::size_t j = 0; j < num_dofs; ++j) dof_map[global_cell_index].push_back(gathered_dofmap[i++]); } } }
//----------------------------------------------------------------------------- void XMLFunctionData::build_dof_map(std::vector<std::vector<uint> >& dof_map, const FunctionSpace& V) { // Get mesh and dofmap dolfin_assert(V.mesh()); dolfin_assert(V.dofmap()); const Mesh& mesh = *V.mesh(); const GenericDofMap& dofmap = *V.dofmap(); const uint num_cells = MPI::sum(mesh.num_cells()); std::vector<std::vector<std::vector<uint > > > gathered_dofmap; std::vector<std::vector<uint > > local_dofmap(mesh.num_cells()); if (MPI::num_processes() > 1) { // Get local-to-global cell numbering dolfin_assert(mesh.parallel_data().have_global_entity_indices(mesh.topology().dim())); const MeshFunction<uint>& global_cell_indices = mesh.parallel_data().global_entity_indices(mesh.topology().dim()); // Build dof map data with global cell indices for (CellIterator cell(mesh); !cell.end(); ++cell) { const uint local_cell_index = cell->index(); const uint global_cell_index = global_cell_indices[*cell]; local_dofmap[local_cell_index] = dofmap.cell_dofs(local_cell_index); local_dofmap[local_cell_index].push_back(global_cell_index); } } else { // Build dof map data for (CellIterator cell(mesh); !cell.end(); ++cell) { const uint local_cell_index = cell->index(); local_dofmap[local_cell_index] = dofmap.cell_dofs(local_cell_index); local_dofmap[local_cell_index].push_back(local_cell_index); } } // Gather dof map data on root process MPI::gather(local_dofmap, gathered_dofmap); // Build global dofmap on root process if (MPI::process_number() == 0) { dof_map.resize(num_cells); // Loop of dof map from each process std::vector<std::vector<std::vector<uint > > > ::const_iterator proc_dofmap; for (proc_dofmap = gathered_dofmap.begin(); proc_dofmap != gathered_dofmap.end(); ++proc_dofmap) { std::vector<std::vector<uint> >::const_iterator cell_dofmap; for (cell_dofmap = proc_dofmap->begin(); cell_dofmap != proc_dofmap->end(); ++cell_dofmap) { const std::vector<uint>& cell_dofs = *cell_dofmap; const uint global_cell_index = cell_dofs.back(); dolfin_assert(global_cell_index < dof_map.size()); dof_map[global_cell_index] = *cell_dofmap; dof_map[global_cell_index].pop_back(); } } } }
//----------------------------------------------------------------------------- void XMLFunctionData::build_global_to_cell_dof( std::vector<std::vector<std::pair<uint, uint> > >& global_dof_to_cell_dof, const FunctionSpace& V) { // Get mesh and dofmap dolfin_assert(V.mesh()); dolfin_assert(V.dofmap()); const Mesh& mesh = *V.mesh(); const GenericDofMap& dofmap = *V.dofmap(); std::vector<std::vector<std::vector<uint > > > gathered_dofmap; std::vector<std::vector<uint > > local_dofmap(mesh.num_cells()); if (MPI::num_processes() > 1) { // Get local-to-global cell numbering dolfin_assert(mesh.parallel_data().have_global_entity_indices(mesh.topology().dim())); const MeshFunction<uint>& global_cell_indices = mesh.parallel_data().global_entity_indices(mesh.topology().dim()); // Build dof map data with global cell indices for (CellIterator cell(mesh); !cell.end(); ++cell) { const uint local_cell_index = cell->index(); const uint global_cell_index = global_cell_indices[*cell]; local_dofmap[local_cell_index] = dofmap.cell_dofs(local_cell_index); local_dofmap[local_cell_index].push_back(global_cell_index); } } else { // Build dof map data for (CellIterator cell(mesh); !cell.end(); ++cell) { const uint local_cell_index = cell->index(); local_dofmap[local_cell_index] = dofmap.cell_dofs(local_cell_index); local_dofmap[local_cell_index].push_back(local_cell_index); } } // Gather dof map data on root process MPI::gather(local_dofmap, gathered_dofmap); // Build global dof - (global cell, local dof) map on root process if (MPI::process_number() == 0) { global_dof_to_cell_dof.resize(dofmap.global_dimension()); std::vector<std::vector<std::vector<uint > > > ::const_iterator proc_dofmap; for (proc_dofmap = gathered_dofmap.begin(); proc_dofmap != gathered_dofmap.end(); ++proc_dofmap) { std::vector<std::vector<uint> >::const_iterator cell_dofmap; for (cell_dofmap = proc_dofmap->begin(); cell_dofmap != proc_dofmap->end(); ++cell_dofmap) { const std::vector<uint>& cell_dofs = *cell_dofmap; const uint global_cell_index = cell_dofs.back(); for (uint i = 0; i < cell_dofs.size() - 1; ++i) global_dof_to_cell_dof[cell_dofs[i]].push_back(std::make_pair(global_cell_index, i)); } } } }
//----------------------------------------------------------------------------- void Extrapolation::compute_coefficients(std::vector<std::vector<double> >& coefficients, const Function& v, const FunctionSpace& V, const FunctionSpace& W, const Cell& cell0, const ufc::cell& c0, const std::vector<dolfin::la_index>& dofs, std::size_t& offset) { // Call recursively for mixed elements dolfin_assert(V.element()); const std::size_t num_sub_spaces = V.element()->num_sub_elements(); if (num_sub_spaces > 0) { for (std::size_t k = 0; k < num_sub_spaces; k++) { compute_coefficients(coefficients, v[k], *V[k], *W[k], cell0, c0, dofs, offset); } return; } // Build data structures for keeping track of unique dofs std::map<std::size_t, std::map<std::size_t, std::size_t> > cell2dof2row; std::set<std::size_t> unique_dofs; build_unique_dofs(unique_dofs, cell2dof2row, cell0, c0, V); // Compute size of linear system dolfin_assert(W.element()); const std::size_t N = W.element()->space_dimension(); const std::size_t M = unique_dofs.size(); // Check size of system if (M < N) { dolfin_error("Extrapolation.cpp", "compute extrapolation", "Not enough degrees of freedom on local patch to build extrapolation"); } // Create matrix and vector for linear system arma::mat A(M, N); arma::vec b(M); // Add equations on cell and neighboring cells add_cell_equations(A, b, cell0, cell0, c0, c0, V, W, v, cell2dof2row[cell0.index()]); dolfin_assert(V.mesh()); UFCCell c1(*V.mesh()); for (CellIterator cell1(cell0); !cell1.end(); ++cell1) { if (cell2dof2row[cell1->index()].empty()) continue; c1.update(*cell1); add_cell_equations(A, b, cell0, *cell1, c0, c1, V, W, v, cell2dof2row[cell1->index()]); } // Solve least squares system arma::Col<double> x = arma::solve(A, b); // Insert resulting coefficients into global coefficient vector dolfin_assert(W.dofmap()); for (std::size_t i = 0; i < W.dofmap()->cell_dimension(cell0.index()); ++i) coefficients[dofs[i + offset]].push_back(x[i]); // Increase offset offset += W.dofmap()->cell_dimension(cell0.index()); }
// Base case for all divergence computations. // Compute divergence of vector field u. void cr_divergence_matrix(GenericMatrix& M, GenericMatrix& A, const FunctionSpace& DGscalar, const FunctionSpace& CRvector) { std::shared_ptr<const GenericDofMap> CR1_dofmap = CRvector.dofmap(), DG0_dofmap = DGscalar.dofmap(); // Figure out about the local dofs of DG0 std::pair<std::size_t, std::size_t> first_last_dof = DG0_dofmap->ownership_range(); std::size_t first_dof = first_last_dof.first; std::size_t last_dof = first_last_dof.second; std::size_t n_local_dofs = last_dof - first_dof; // Get topological dimension so that we know what Facet is const Mesh mesh = *DGscalar.mesh(); std::size_t tdim = mesh.topology().dim(); std::size_t gdim = mesh.geometry().dim(); std::vector<std::size_t> columns; std::vector<double> values; // Fill the values for(CellIterator cell(mesh); !cell.end(); ++cell) { auto dg_dofs = DG0_dofmap->cell_dofs(cell->index()); // There is only one DG0 dof per cell dolfin::la_index cell_dof = dg_dofs[0]; Point cell_mp = cell->midpoint(); double cell_volume = cell->volume(); std::size_t local_facet_index = 0; auto cr_dofs = CR1_dofmap->cell_dofs(cell->index()); for(FacetIterator facet(*cell); !facet.end(); ++facet) { double facet_measure=0; if(tdim == 2) facet_measure = Edge(mesh, facet->index()).length(); else if(tdim == 3) facet_measure = Face(mesh, facet->index()).area(); // Tdim 1 will not happen because CR is not defined there Point facet_normal = facet->normal(); // Flip the normal if it is not outer already Point facet_mp = facet->midpoint(); double sign = (facet_normal.dot(facet_mp - cell_mp) > 0.0) ? 1.0 : -1.0; facet_normal *= (sign*facet_measure/cell_volume); // Dofs of CR on the facet, local order std::vector<std::size_t> facet_dofs; CR1_dofmap->tabulate_facet_dofs(facet_dofs, local_facet_index); for (std::size_t j = 0 ; j < facet_dofs.size(); j++) { columns.push_back(cr_dofs[facet_dofs[j]]); values.push_back(facet_normal[j]); } local_facet_index += 1; } M.setrow(cell_dof, columns, values); columns.clear(); values.clear(); } M.apply("insert"); //std::shared_ptr<GenericMatrix> Cp = MatMatMult(M, A); //return Cp; }