//------------------------------------------------------------------------------ void LocalAssembler::assemble_exterior_facet(Eigen::MatrixXd& A, UFC& ufc, const std::vector<double>& vertex_coordinates, const ufc::cell& ufc_cell, const Cell& cell, const Facet& facet, const std::size_t local_facet, const MeshFunction<std::size_t>* domains) { // Skip if there are no exterior facet integrals if (!ufc.form.has_exterior_facet_integrals()) return; // Extract default exterior facet integral ufc::exterior_facet_integral* integral = ufc.default_exterior_facet_integral.get(); // Get integral for sub domain (if any) if (domains && !domains->empty()) integral = ufc.get_exterior_facet_integral((*domains)[facet]); // Skip integral if zero if (!integral) return; // Update to current cell ufc.update(cell, vertex_coordinates, ufc_cell, integral->enabled_coefficients()); // Tabulate exterior facet tensor integral->tabulate_tensor(ufc.A.data(), ufc.w(), vertex_coordinates.data(), local_facet, ufc_cell.orientation); // Stuff a_ufc.A into A const std::size_t M = A.rows(); const std::size_t N = A.cols(); for (std::size_t i = 0; i < M; i++) for (std::size_t j = 0; j < N; j++) A(i, j) += ufc.A[N*i + j]; }
//----------------------------------------------------------------------------- void Assembler::assemble_exterior_facets( GenericTensor& A, const Form& a, UFC& ufc, std::shared_ptr<const MeshFunction<std::size_t>> domains, std::vector<double>* values) { // Skip assembly if there are no exterior facet integrals if (!ufc.form.has_exterior_facet_integrals()) return; // Set timer Timer timer("Assemble exterior facets"); // Extract mesh const Mesh& mesh = a.mesh(); // Form rank const std::size_t form_rank = ufc.form.rank(); // Collect pointers to dof maps std::vector<const GenericDofMap*> dofmaps; for (std::size_t i = 0; i < form_rank; ++i) dofmaps.push_back(a.function_space(i)->dofmap().get()); // Vector to hold dof map for a cell std::vector<ArrayView<const dolfin::la_index>> dofs(form_rank); // Exterior facet integral const ufc::exterior_facet_integral* integral = ufc.default_exterior_facet_integral.get(); // Check whether integral is domain-dependent bool use_domains = domains && !domains->empty(); // Compute facets and facet - cell connectivity if not already computed const std::size_t D = mesh.topology().dim(); mesh.init(D - 1); mesh.init(D - 1, D); dolfin_assert(mesh.ordered()); // Assemble over exterior facets (the cells of the boundary) ufc::cell ufc_cell; std::vector<double> coordinate_dofs; Progress p(AssemblerBase::progress_message(A.rank(), "exterior facets"), mesh.num_facets()); for (FacetIterator facet(mesh); !facet.end(); ++facet) { // Only consider exterior facets if (!facet->exterior()) { p++; continue; } // Get integral for sub domain (if any) if (use_domains) integral = ufc.get_exterior_facet_integral((*domains)[*facet]); // Skip integral if zero if (!integral) continue; // Get mesh cell to which mesh facet belongs (pick first, there is // only one) dolfin_assert(facet->num_entities(D) == 1); Cell mesh_cell(mesh, facet->entities(D)[0]); // Check that cell is not a ghost dolfin_assert(!mesh_cell.is_ghost()); // Get local index of facet with respect to the cell const std::size_t local_facet = mesh_cell.index(*facet); // Update UFC cell mesh_cell.get_cell_data(ufc_cell, local_facet); mesh_cell.get_coordinate_dofs(coordinate_dofs); // Update UFC object ufc.update(mesh_cell, coordinate_dofs, ufc_cell, integral->enabled_coefficients()); // Get local-to-global dof maps for cell for (std::size_t i = 0; i < form_rank; ++i) dofs[i] = dofmaps[i]->cell_dofs(mesh_cell.index()); // Tabulate exterior facet tensor integral->tabulate_tensor(ufc.A.data(), ufc.w(), coordinate_dofs.data(), local_facet, ufc_cell.orientation); // Add entries to global tensor A.add_local(ufc.A.data(), dofs); p++; } }