62 template <
int dim0,
int dim1,
int spacedim>
63 std::pair<std::vector<Point<spacedim>>, std::vector<unsigned int>>
69 const bool tria_is_parallel)
71 const auto & immersed_fe = immersed_dh.
get_fe();
72 std::vector<Point<spacedim>> points_over_local_cells;
74 std::vector<unsigned int> used_cells_ids;
80 unsigned int cell_id = 0;
83 bool use_cell =
false;
86 const auto bbox = cell->bounding_box();
87 std::vector<std::pair<
92 boost::geometry::index::intersects(bbox),
93 std::back_inserter(out_vals));
98 for (
const auto &bbox_it : out_vals)
99 if (bbox_it.second->is_locally_owned())
102 used_cells_ids.emplace_back(cell_id);
114 const std::vector<Point<spacedim>> &x_points =
115 fe_v.get_quadrature_points();
118 points_over_local_cells.insert(points_over_local_cells.end(),
125 return {std::move(points_over_local_cells), std::move(used_cells_ids)};
135 template <
int dim0,
int dim1,
int spacedim>
136 std::pair<std::vector<unsigned int>, std::vector<unsigned int>>
158 for (
unsigned int i = 0, j = 0; i < gtl0.size(); ++i)
162 for (
unsigned int i = 0, j = 0; i < gtl1.size(); ++i)
221 ExcMessage(
"This function can only work if dim1 <= dim0"));
227 const bool tria_is_parallel =
230 const auto &space_fe = space_dh.
get_fe();
231 const auto &immersed_fe = immersed_dh.
get_fe();
234 std::vector<types::global_dof_index> dofs(immersed_fe.dofs_per_cell);
235 std::vector<types::global_dof_index> odofs(space_fe.dofs_per_cell);
243 (immersed_comps.
size() == 0 ?
251 std::vector<unsigned int> space_gtl(space_fe.n_components(),
253 std::vector<unsigned int> immersed_gtl(immersed_fe.n_components(),
256 for (
unsigned int i = 0, j = 0; i < space_gtl.size(); ++i)
260 for (
unsigned int i = 0, j = 0; i < immersed_gtl.size(); ++i)
262 immersed_gtl[i] = j++;
264 const unsigned int n_q_points = quad.
size();
265 const unsigned int n_active_c =
269 cache, immersed_dh, quad, immersed_mapping, tria_is_parallel);
271 const auto &points_over_local_cells = std::get<0>(qpoints_cells_data);
272 const auto &used_cells_ids = std::get<1>(qpoints_cells_data);
298 const auto &all_cells = std::get<0>(cpm);
299 const auto &maps = std::get<2>(cpm);
302 std::set<typename Triangulation<dim0, spacedim>::active_cell_iterator>>
303 cell_sets(n_active_c);
305 for (
unsigned int i = 0; i < maps.size(); ++i)
311 unsigned int cell_id;
312 for (
const unsigned int idx : maps[i])
315 if (tria_is_parallel)
316 cell_id = used_cells_ids[idx / n_q_points];
318 cell_id = idx / n_q_points;
320 if (last_id != cell_id)
322 cell_sets[cell_id].insert(all_cells[i]);
334 cell->get_dof_indices(dofs);
337 const auto &cells = cell_sets[i];
339 for (
const auto &cell_c : cells)
345 if (ocell->is_locally_owned())
347 ocell->get_dof_indices(odofs);
352 odofs, dofs, sparsity);
361 template <
int dim0,
int dim1,
int spacedim,
typename Matrix>
389 template <
int dim0,
int dim1,
int spacedim,
typename Matrix>
405 ExcMessage(
"This function can only work if dim1 <= dim0"));
411 const bool tria_is_parallel =
415 const auto &space_fe = space_dh.
get_fe();
416 const auto &immersed_fe = immersed_dh.
get_fe();
419 std::vector<types::global_dof_index> dofs(immersed_fe.dofs_per_cell);
420 std::vector<types::global_dof_index> odofs(space_fe.dofs_per_cell);
428 (immersed_comps.
size() == 0 ?
435 std::vector<unsigned int> space_gtl(space_fe.n_components(),
437 std::vector<unsigned int> immersed_gtl(immersed_fe.n_components(),
440 for (
unsigned int i = 0, j = 0; i < space_gtl.size(); ++i)
444 for (
unsigned int i = 0, j = 0; i < immersed_gtl.size(); ++i)
446 immersed_gtl[i] = j++;
449 space_dh.
get_fe().dofs_per_cell, immersed_dh.
get_fe().dofs_per_cell);
457 const unsigned int n_q_points = quad.
size();
458 const unsigned int n_active_c =
462 cache, immersed_dh, quad, immersed_mapping, tria_is_parallel);
464 const auto &points_over_local_cells = std::get<0>(used_cells_data);
465 const auto &used_cells_ids = std::get<1>(used_cells_data);
470 const auto &all_cells = std::get<0>(cpm);
471 const auto &all_qpoints = std::get<1>(cpm);
472 const auto &all_maps = std::get<2>(cpm);
475 std::vector<typename Triangulation<dim0, spacedim>::active_cell_iterator>>
476 cell_container(n_active_c);
477 std::vector<std::vector<std::vector<Point<dim0>>>> qpoints_container(
479 std::vector<std::vector<std::vector<unsigned int>>> maps_container(
484 for (
unsigned int o = 0; o < all_cells.size(); ++o)
486 for (
unsigned int j = 0; j < all_maps[o].size(); ++j)
491 unsigned int cell_id;
492 if (tria_is_parallel)
493 cell_id = used_cells_ids[all_maps[o][j] / n_q_points];
495 cell_id = all_maps[o][j] / n_q_points;
497 const unsigned int n_pt = all_maps[o][j] % n_q_points;
500 if (cell_container[cell_id].empty())
502 cell_container[cell_id].emplace_back(all_cells[o]);
503 qpoints_container[cell_id].emplace_back(
505 maps_container[cell_id].emplace_back(
506 std::vector<unsigned int>{n_pt});
510 else if (cell_container[cell_id].back() == all_cells[o])
512 qpoints_container[cell_id].back().emplace_back(
514 maps_container[cell_id].back().emplace_back(n_pt);
519 const auto cell_p = std::find(cell_container[cell_id].
begin(),
520 cell_container[cell_id].
end() - 1,
523 if (cell_p == cell_container[cell_id].
end() - 1)
525 cell_container[cell_id].emplace_back(all_cells[o]);
526 qpoints_container[cell_id].emplace_back(
528 maps_container[cell_id].emplace_back(
529 std::vector<unsigned int>{n_pt});
533 const unsigned int pos =
534 cell_p - cell_container[cell_id].begin();
535 qpoints_container[cell_id][pos].emplace_back(
537 maps_container[cell_id][pos].emplace_back(n_pt);
545 endc = immersed_dh.
end();
547 for (
unsigned int j = 0; cell != endc; ++cell, ++j)
551 cell->get_dof_indices(dofs);
554 const auto &cells = cell_container[j];
555 const auto &qpoints = qpoints_container[j];
556 const auto &maps = maps_container[j];
558 for (
unsigned int c = 0; c < cells.size(); ++c)
562 *cells[c], &space_dh);
564 if (ocell->is_locally_owned())
566 const std::vector<Point<dim0>> & qps = qpoints[c];
567 const std::vector<unsigned int> &ids = maps[c];
574 ocell->get_dof_indices(odofs);
579 for (
unsigned int i = 0; i < space_dh.
get_fe().dofs_per_cell;
583 space_dh.
get_fe().system_to_component_index(i).first;
585 for (
unsigned int j = 0;
586 j < immersed_dh.
get_fe().dofs_per_cell;
589 const auto comp_j = immersed_dh.
get_fe()
590 .system_to_component_index(j)
592 if (space_gtl[comp_i] == immersed_gtl[comp_j])
593 for (
unsigned int oq = 0;
594 oq < o_fe_v.n_quadrature_points;
598 const unsigned int q = ids[oq];
601 (fe_v.shape_value(j, q) *
602 o_fe_v.shape_value(i, oq) * fe_v.JxW(q));
638 ExcMessage(
"When epsilon is zero, you can only "
639 "call this function with dim1 <= dim0."));
654 const bool zero_is_distributed =
657 const bool one_is_distributed =
670 const bool outer_loop_on_zero =
671 (zero_is_distributed && !one_is_distributed) ||
675 const auto &fe0 = dh0.
get_fe();
676 const auto &fe1 = dh1.
get_fe();
679 std::vector<types::global_dof_index> dofs0(fe0.dofs_per_cell);
680 std::vector<types::global_dof_index> dofs1(fe1.dofs_per_cell);
682 if (outer_loop_on_zero)
688 std::vector<std::pair<
694 if (cell0->is_locally_owned())
696 intersection.resize(0);
700 boost::geometry::index::query(tree1,
701 boost::geometry::index::intersects(
703 std::back_inserter(intersection));
704 if (!intersection.empty())
706 cell0->get_dof_indices(dofs0);
707 for (
const auto &entry : intersection)
710 *entry.second, &dh1);
711 cell1->get_dof_indices(dofs1);
724 std::vector<std::pair<
730 if (cell1->is_locally_owned())
732 intersection.resize(0);
736 boost::geometry::index::query(tree0,
737 boost::geometry::index::intersects(
739 std::back_inserter(intersection));
740 if (!intersection.empty())
742 cell1->get_dof_indices(dofs1);
743 for (
const auto &entry : intersection)
746 *entry.second, &dh0);
747 cell0->get_dof_indices(dofs0);
759 template <
int dim0,
int dim1,
int spacedim,
typename Matrix>
778 ExcMessage(
"When epsilon is zero, you can only "
779 "call this function with dim1 <= dim0."));
795 const bool zero_is_distributed =
798 const bool one_is_distributed =
811 const bool outer_loop_on_zero =
812 (zero_is_distributed && !one_is_distributed) ||
816 const auto &fe0 = dh0.
get_fe();
817 const auto &fe1 = dh1.
get_fe();
832 std::vector<types::global_dof_index> dofs0(fe0.dofs_per_cell);
833 std::vector<types::global_dof_index> dofs1(fe1.dofs_per_cell);
842 const auto >l0 = p.first;
843 const auto >l1 = p.second;
846 std::vector<double> kernel_values(quadrature1.
size());
848 auto assemble_one_pair = [&]() {
850 for (
unsigned int q0 = 0; q0 < quadrature0.
size(); ++q0)
853 kernel.
value_list(fev1.get_quadrature_points(), kernel_values);
854 for (
unsigned int j = 0; j < fe1.dofs_per_cell; ++j)
856 const auto comp_j = fe1.system_to_component_index(j).first;
860 typename Matrix::value_type sum_q1 = {};
861 for (
unsigned int q1 = 0; q1 < quadrature1.
size(); ++q1)
863 fev1.shape_value(j, q1) * kernel_values[q1] * fev1.JxW(q1);
864 sum_q1 *= fev0.JxW(q0);
869 for (
unsigned int i = 0; i < fe0.dofs_per_cell; ++i)
871 const auto comp_i = fe0.system_to_component_index(i).first;
873 gtl1[comp_j] == gtl0[comp_i])
874 cell_matrix(i, j) += fev0.shape_value(i, q0) * sum_q1;
885 if (outer_loop_on_zero)
891 std::vector<std::pair<
897 if (cell0->is_locally_owned())
899 intersection.resize(0);
903 boost::geometry::index::query(tree1,
904 boost::geometry::index::intersects(
906 std::back_inserter(intersection));
907 if (!intersection.empty())
909 cell0->get_dof_indices(dofs0);
911 for (
const auto &entry : intersection)
914 *entry.second, &dh1);
915 cell1->get_dof_indices(dofs1);
927 std::vector<std::pair<
933 if (cell1->is_locally_owned())
935 intersection.resize(0);
939 boost::geometry::index::query(tree0,
940 boost::geometry::index::intersects(
942 std::back_inserter(intersection));
943 if (!intersection.empty())
945 cell1->get_dof_indices(dofs1);
947 for (
const auto &entry : intersection)
950 *entry.second, &dh0);
951 cell0->get_dof_indices(dofs0);
960 #include "coupling.inst"