Example #1
0
//-----------------------------------------------------------------------------
void AssemblerBase::check(const Form& a)
{
    dolfin_assert(a.ufc_form());

    // Check the form
    a.check();

    // Extract mesh and coefficients
    const Mesh& mesh = a.mesh();
    const std::vector<std::shared_ptr<const GenericFunction>>
            coefficients = a.coefficients();

    // Check that we get the correct number of coefficients
    if (coefficients.size() != a.num_coefficients())
    {
        dolfin_error("AssemblerBase.cpp",
                     "assemble form",
                     "Incorrect number of coefficients (got %d but expecting %d)",
                     coefficients.size(), a.num_coefficients());
    }

    // Check that all coefficients have valid value dimensions
    for (std::size_t i = 0; i < coefficients.size(); ++i)
    {
        if (!coefficients[i])
        {
            dolfin_error("AssemblerBase.cpp",
                         "assemble form",
                         "Coefficient number %d (\"%s\") has not been set",
                         i, a.coefficient_name(i).c_str());
        }

        // unique_ptr deletes its object when it exits its scope
        std::unique_ptr<ufc::finite_element>
        fe(a.ufc_form()->create_finite_element(i + a.rank()));

        // Checks out-commented since they only work for Functions, not
        // Expressions
        const std::size_t r = coefficients[i]->value_rank();
        const std::size_t fe_r = fe->value_rank();
        if (fe_r != r)
        {
            dolfin_error("AssemblerBase.cpp",
                         "assemble form",
                         "Invalid value rank for coefficient %d (got %d but expecting %d). \
You might have forgotten to specify the value rank correctly in an Expression subclass", i, r, fe_r);
        }

        for (std::size_t j = 0; j < r; ++j)
        {
            const std::size_t dim = coefficients[i]->value_dimension(j);
            const std::size_t fe_dim = fe->value_dimension(j);
            if (dim != fe_dim)
            {
                dolfin_error("AssemblerBase.cpp",
                             "assemble form",
                             "Invalid value dimension %d for coefficient %d (got %d but expecting %d). \
You might have forgotten to specify the value dimension correctly in an Expression subclass", j, i, dim, fe_dim);
            }
        }
Example #2
0
//----------------------------------------------------------------------------
void Assembler::assemble(GenericTensor& A, const Form& a)
{
  // All assembler functions above end up calling this function, which
  // in turn calls the assembler functions below to assemble over
  // cells, exterior and interior facets.

  // Check whether we should call the multi-core assembler
  #ifdef HAS_OPENMP
  const std::size_t num_threads = parameters["num_threads"];
  if (num_threads > 0)
  {
    OpenMpAssembler assembler;
    assembler.add_values = add_values;
    assembler.finalize_tensor = finalize_tensor;
    assembler.keep_diagonal = keep_diagonal;
    assembler.assemble(A, a);
    return;
  }
  #endif

  // Get cell domains
  std::shared_ptr<const MeshFunction<std::size_t>>
    cell_domains = a.cell_domains();

  // Get exterior facet domains
  std::shared_ptr<const MeshFunction<std::size_t>> exterior_facet_domains
      = a.exterior_facet_domains();

  // Get interior facet domains
  std::shared_ptr<const MeshFunction<std::size_t>> interior_facet_domains
      = a.interior_facet_domains();

  // Get vertex domains
  std::shared_ptr<const MeshFunction<std::size_t>> vertex_domains
    = a.vertex_domains();

  // Check form
  AssemblerBase::check(a);

  // Create data structure for local assembly data
  UFC ufc(a);

  // Update off-process coefficients
  const std::vector<std::shared_ptr<const GenericFunction>>
    coefficients = a.coefficients();

  // Initialize global tensor
  init_global_tensor(A, a);

  // Assemble over cells
  assemble_cells(A, a, ufc, cell_domains, NULL);

  // Assemble over exterior facets
  assemble_exterior_facets(A, a, ufc, exterior_facet_domains, NULL);

  // Assemble over interior facets
  assemble_interior_facets(A, a, ufc, interior_facet_domains,
                           cell_domains, NULL);

  // Assemble over vertices
  assemble_vertices(A, a, ufc, vertex_domains);

  // Finalize assembly of global tensor
  if (finalize_tensor)
    A.apply("add");
}