//----------------------------------------------------------------------------- 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; }
Probe::Probe(const Array<double>& x, const FunctionSpace& V) : _element(V.element()), _num_evals(0) { const Mesh& mesh = *V.mesh(); std::size_t gdim = mesh.geometry().dim(); // Find the cell that contains probe const Point point(gdim, x.data()); unsigned int cell_id = mesh.bounding_box_tree()->compute_first_entity_collision(point); // If the cell is on this process, then create an instance // of the Probe class. Otherwise raise a dolfin_error. if (cell_id != std::numeric_limits<unsigned int>::max()) { // Store position of probe for (std::size_t i = 0; i < 3; i++) _x[i] = (i < gdim ? x[i] : 0.0); // Compute in tensor (one for scalar function, . . .) _value_size_loc = 1; for (std::size_t i = 0; i < _element->value_rank(); i++) _value_size_loc *= _element->value_dimension(i); _probes.resize(_value_size_loc); // Create cell that contains point dolfin_cell.reset(new Cell(mesh, cell_id)); dolfin_cell->get_cell_data(ufc_cell); coefficients.resize(_element->space_dimension()); // Cell vertices dolfin_cell->get_vertex_coordinates(vertex_coordinates); // Create work vector for basis basis_matrix.resize(_value_size_loc); for (std::size_t i = 0; i < _value_size_loc; ++i) basis_matrix[i].resize(_element->space_dimension()); std::vector<double> basis(_value_size_loc); const int cell_orientation = 0; for (std::size_t i = 0; i < _element->space_dimension(); ++i) { _element->evaluate_basis(i, &basis[0], &x[0], vertex_coordinates.data(), cell_orientation); for (std::size_t j = 0; j < _value_size_loc; ++j) basis_matrix[j][i] = basis[j]; } } else { dolfin_error("Probe.cpp","set probe","Probe is not found on processor"); } }
//----------------------------------------------------------------------------- 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; }
StatisticsProbes::StatisticsProbes(const Array<double>& x, const FunctionSpace& V, bool segregated) { const std::size_t Nd = V.mesh()->geometry().dim(); const std::size_t N = x.size() / Nd; Array<double> _x(Nd); total_number_probes = N; _num_evals = 0; _value_size = 1; for (std::size_t i = 0; i < V.element()->value_rank(); i++) _value_size *= V.element()->value_dimension(i); if (segregated) { assert(V.element()->value_rank() == 0); _value_size *= V.element()->geometric_dimension(); } // Symmetric statistics. Velocity: u, v, w, uu, vv, ww, uv, uw, vw _value_size = _value_size*(_value_size+3)/2.; for (std::size_t i=0; i<N; i++) { for (std::size_t j=0; j<Nd; j++) _x[j] = x[i*Nd + j]; try { StatisticsProbe* probe = new StatisticsProbe(_x, V, segregated); std::pair<std::size_t, StatisticsProbe*> newprobe = std::make_pair(i, &(*probe)); _allprobes.push_back(newprobe); } catch (std::exception &e) { // do-nothing } } //cout << local_size() << " of " << N << " probes found on processor " << MPI::process_number() << endl; }
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); } } }
//----------------------------------------------------------------------------- void Extrapolation::add_cell_equations(Eigen::MatrixXd& A, Eigen::VectorXd& b, const Cell& cell0, const Cell& cell1, const std::vector<double>& coordinate_dofs0, const std::vector<double>& coordinate_dofs1, const ufc::cell& c0, const ufc::cell& c1, const FunctionSpace& V, const FunctionSpace& W, const Function& v, std::map<std::size_t, std::size_t>& dof2row) { // Extract coefficients for v on patch cell dolfin_assert(V.element()); std::vector<double> dof_values(V.element()->space_dimension()); v.restrict(&dof_values[0], *V.element(), cell1, coordinate_dofs1.data(), c1); // Create basis function dolfin_assert(W.element()); BasisFunction phi(0, W.element(), coordinate_dofs0); // Iterate over given local dofs for V on patch cell for (auto const &it : dof2row) { const std::size_t i = it.first; const std::size_t row = it.second; // Iterate over basis functions for W on center cell for (std::size_t j = 0; j < W.element()->space_dimension(); ++j) { // Create basis function phi.update_index(j); // Evaluate dof on basis function const double dof_value = V.element()->evaluate_dof(i, phi, coordinate_dofs1.data(), c1.orientation, c1); // Insert dof_value into matrix A(row, j) = dof_value; } // Insert coefficient into vector b[row] = dof_values[i]; } }
//----------------------------------------------------------------------------- void Extrapolation::add_cell_equations(arma::Mat<double>& A, arma::Col<double>& b, const Cell& cell0, const Cell& cell1, const ufc::cell& c0, const ufc::cell& c1, const FunctionSpace& V, const FunctionSpace& W, const Function& v, std::map<std::size_t, std::size_t>& dof2row) { // Extract coefficents for v on patch cell dolfin_assert(V.element()); std::vector<double> dof_values(V.element()->space_dimension()); v.restrict(&dof_values[0], *V.element(), cell1, c1); // Iterate over given local dofs for V on patch cell dolfin_assert(W.element()); for (std::map<std::size_t, std::size_t>::iterator it = dof2row.begin(); it!= dof2row.end(); it++) { const std::size_t i = it->first; const std::size_t row = it->second; // Iterate over basis functions for W on center cell for (std::size_t j = 0; j < W.element()->space_dimension(); ++j) { // Create basis function const BasisFunction phi(j, *W.element(), c0); // Evaluate dof on basis function const int cell_orientation = 0; const double dof_value = V.element()->evaluate_dof(i, phi, &c1.vertex_coordinates[0], cell_orientation, c1); // Insert dof_value into matrix A(row, j) = dof_value; } // Insert coefficient into vector b[row] = dof_values[i]; } }
//----------------------------------------------------------------------------- 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 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()); }