Пример #1
0
//-----------------------------------------------------------------------------
Graph GraphBuilder::local_graph(const Mesh& mesh, const GenericDofMap& dofmap0,
                                                  const GenericDofMap& dofmap1)
{
  Timer timer("Build local sparsity graph from dofmaps");

  // Create empty graph
  const std::size_t n = dofmap0.global_dimension();
  Graph graph(n);

  // Build graph
  for (CellIterator cell(mesh); !cell.end(); ++cell)
  {
    const ArrayView<const dolfin::la_index> dofs0
      = dofmap0.cell_dofs(cell->index());
    const ArrayView<const dolfin::la_index> dofs1
      = dofmap1.cell_dofs(cell->index());
    //std::vector<dolfin::la_index>::const_iterator node0, node1;
    for (auto node0 = dofs0.begin(); node0 != dofs0.end(); ++node0)
      for (auto node1 = dofs1.begin(); node1 != dofs1.end(); ++node1)
        if (*node0 != *node1)
          graph[*node0].insert(*node1);
  }

  return graph;
}
Пример #2
0
//----------------------------------------------------------------------------
void LocalSolver::solve_local(GenericVector& x, const GenericVector& b,
                              const GenericDofMap& dofmap_b) const
{
  dolfin_assert(_a);
  dolfin_assert(_a->rank() == 2);

  // Extract mesh
  dolfin_assert(_a->function_space(0)->mesh());
  const Mesh& mesh = *_a->function_space(0)->mesh();

  // Check whether to use cache for factorizations
  const bool use_cache
    = _cholesky_cache.empty() and _lu_cache.empty() ? false : true;

  // Create UFC object
  UFC ufc_a(*_a);

  // Get cell integral
  std::shared_ptr<ufc::cell_integral> integral_a = ufc_a.default_cell_integral;
  dolfin_assert(integral_a);

  // Get dofmaps
  std::array<std::shared_ptr<const GenericDofMap>, 2> dofmaps_a
    = {{_a->function_space(0)->dofmap(), _a->function_space(1)->dofmap()}};
  dolfin_assert(dofmaps_a[0] and dofmaps_a[1]);

  // Check dimensions
  dolfin_assert(dofmaps_a[0]->global_dimension()
                == dofmaps_a[1]->global_dimension());
  dolfin_assert(dofmaps_a[0]->global_dimension()
                == dofmap_b.global_dimension());

  // Eigen data structures for local tensors
  Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> A_e;
  Eigen::VectorXd b_e, x_e;

  // Eigen factorizations
  Eigen::PartialPivLU<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
                                    Eigen::RowMajor>> lu;
  Eigen::LLT<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
                           Eigen::RowMajor>> cholesky;

  // Assemble LHS over cells and solve
  Progress p("Performing local (cell-wise) solve", mesh.num_cells());
  ufc::cell ufc_cell;
  std::vector<double> vertex_coordinates;
  for (CellIterator cell(mesh); !cell.end(); ++cell)
  {
    // Get cell dofmaps
    const ArrayView<const dolfin::la_index> dofs_L
      = dofmap_b.cell_dofs(cell->index());
    const ArrayView<const dolfin::la_index> dofs_a0
      = dofmaps_a[0]->cell_dofs(cell->index());

    // Check dimensions
    dolfin_assert(dofs_L.size() == dofs_a0.size());

    // Copy global RHS data into local RHS
    b_e.resize(dofs_L.size());
    b.get_local(b_e.data(), dofs_L.size(), dofs_L.data());

    // Solve local problem
    if (!use_cache)
    {
      // Update to current cell
      cell->get_vertex_coordinates(vertex_coordinates);
      cell->get_cell_data(ufc_cell);

      // Update LHS UFC object
      ufc_a.update(*cell, vertex_coordinates, ufc_cell,
                   integral_a->enabled_coefficients());

      // Resize A_e and tabulate on for cell
      const std::size_t dim = dofmaps_a[0]->num_element_dofs(cell->index());
      dolfin_assert(dim == dofmaps_a[1]->num_element_dofs(cell->index()));
      A_e.resize(dim, dim);
      integral_a->tabulate_tensor(A_e.data(), ufc_a.w(),
                                  vertex_coordinates.data(),
                                  ufc_cell.orientation);
      // Solve local problem
      if (_solver_type == SolverType::Cholesky)
      {
        cholesky.compute(A_e);
        x_e = cholesky.solve(b_e);
      }
      else
      {
        lu.compute(A_e);
        x_e = lu.solve(b_e);
      }
    }
    else
    {
      if (_solver_type == SolverType::Cholesky)
        x_e = _cholesky_cache[cell->index()].solve(b_e);
      else
        x_e = _lu_cache[cell->index()].solve(b_e);
    }

    // Set solution in global vector
    x.set_local(x_e.data(), dofs_a0.size(), dofs_a0.data());

    p++;
  }

  // Finalise vector
  x.apply("insert");
}