249 using Iterator =
typename DoFHandler<dim>::active_cell_iterator;
253 const auto cell_worker = [&](
const Iterator &t_cell, Scratch &scratch_data, CopyData ©_data) {
254 scratch_data.fe_values.reinit(t_cell);
255 const auto &fe_v = scratch_data.fe_values;
256 copy_data.cell_index = t_cell->active_cell_index();
259 const auto &JxW = fe_v.get_JxW_values();
260 const auto &q_points = fe_v.get_quadrature_points();
261 const auto &q_indices = fe_v.quadrature_point_indices();
263 auto &solution = scratch_data.solution;
264 auto &solution_grad = scratch_data.solution_grad;
265 auto &solution_hess = scratch_data.solution_hess;
266 fe_v.get_function_values(solution_global, solution);
267 fe_v.get_function_gradients(solution_global, solution_grad);
268 fe_v.get_function_hessians(solution_global, solution_hess);
270 double local_indicator = 0.;
271 for (
const auto &q_index : q_indices) {
272 const auto &x_q = q_points[q_index];
273 const std::vector<double>
nothing = {};
274 model.cell_indicator(local_indicator, x_q,
275 i_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index]));
276 copy_data.value += JxW[q_index] * local_indicator;
279 const auto face_worker = [&](
const Iterator &t_cell,
const uint &f,
const uint &sf,
const Iterator &t_ncell,
280 const uint &nf,
const unsigned int &nsf, Scratch &scratch_data,
281 CopyData ©_data) {
282 scratch_data.fe_interface_values.reinit(t_cell, f, sf, t_ncell, nf, nsf);
283 const auto &fe_iv = scratch_data.fe_interface_values;
284 const auto &fe_iv_s = scratch_data.fe_interface_values.get_fe_face_values(0);
285 const auto &fe_iv_n = scratch_data.fe_interface_values.get_fe_face_values(1);
287 copy_data.face_data.emplace_back();
288 auto ©_data_face = copy_data.face_data.emplace_back();
289 copy_data_face.cell_indices[0] = t_cell->active_cell_index();
290 copy_data_face.cell_indices[1] = t_ncell->active_cell_index();
291 copy_data_face.values[0] = 0;
292 copy_data_face.values[1] = 0;
294 const auto &JxW = fe_iv.get_JxW_values();
295 const auto &q_points = fe_iv.get_quadrature_points();
296 const auto &q_indices = fe_iv.quadrature_point_indices();
297 const std::vector<Tensor<1, dim>> &normals = fe_iv.get_normal_vectors();
299 auto &solution_s = scratch_data.solution_interface[0];
300 auto &solution_n = scratch_data.solution_interface[1];
301 auto &solution_grad_s = scratch_data.solution_grad_interface[0];
302 auto &solution_grad_n = scratch_data.solution_grad_interface[1];
303 auto &solution_hess_s = scratch_data.solution_hess_interface[0];
304 auto &solution_hess_n = scratch_data.solution_hess_interface[1];
305 fe_iv_s.get_function_values(solution_global, solution_s);
306 fe_iv_n.get_function_values(solution_global, solution_n);
307 fe_iv_s.get_function_gradients(solution_global, solution_grad_s);
308 fe_iv_n.get_function_gradients(solution_global, solution_grad_n);
309 fe_iv_s.get_function_hessians(solution_global, solution_hess_s);
310 fe_iv_n.get_function_hessians(solution_global, solution_hess_n);
312 array<double, 2> local_indicator{};
313 for (
const auto &q_index : q_indices) {
314 const auto &x_q = q_points[q_index];
315 std::vector<double>
nothing = {};
316 model.face_indicator(local_indicator, normals[q_index], x_q,
317 i_tie(solution_s[q_index], solution_grad_s[q_index], solution_hess_s[q_index]),
318 i_tie(solution_n[q_index], solution_grad_n[q_index], solution_hess_n[q_index]));
320 copy_data_face.values[0] += JxW[q_index] * local_indicator[0] * (1. + t_cell->at_boundary());
321 copy_data_face.values[1] += JxW[q_index] * local_indicator[1] * (1. + t_ncell->at_boundary());
324 const auto copier = [&](
const CopyData &c) {
325 for (
auto &cdf : c.face_data)
326 for (
uint j = 0; j < 2; ++j)
327 indicator[cdf.cell_indices[j]] += cdf.values[j];
328 indicator[c.cell_index] += c.value;
333 MeshWorker::AssembleFlags flags = MeshWorker::assemble_own_cells | MeshWorker::assemble_own_interior_faces_once;
392 using Iterator =
typename DoFHandler<dim>::active_cell_iterator;
398 std::array<
NumberType, Components::count_extractors()> __extracted_data{{}};
399 if constexpr (Components::count_extractors() > 0)
400 this->
extract(__extracted_data, solution_global, variables,
true,
false,
true);
401 const auto &extracted_data = __extracted_data;
403 const auto cell_worker = [&](
const Iterator &cell, Scratch &scratch_data, CopyData ©_data) {
404 scratch_data.fe_values.reinit(cell);
405 const auto &fe_v = scratch_data.fe_values;
406 const uint n_dofs = fe_v.get_fe().n_dofs_per_cell();
408 copy_data.reinit(cell, n_dofs);
409 const auto &JxW = fe_v.get_JxW_values();
410 const auto &q_points = fe_v.get_quadrature_points();
411 const auto &q_indices = fe_v.quadrature_point_indices();
413 auto &solution = scratch_data.solution;
414 auto &solution_grad = scratch_data.solution_grad;
415 auto &solution_hess = scratch_data.solution_hess;
416 auto &solution_dot = scratch_data.solution_dot;
417 fe_v.get_function_values(solution_global, solution);
418 fe_v.get_function_gradients(solution_global, solution_grad);
419 fe_v.get_function_hessians(solution_global, solution_hess);
420 fe_v.get_function_values(solution_global_dot, solution_dot);
422 array<Tensor<1, dim, NumberType>, Components::count_fe_functions()> flux{};
423 array<
NumberType, Components::count_fe_functions()> source{};
425 for (
const auto &q_index : q_indices) {
426 const auto &x_q = q_points[q_index];
429 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
432 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
433 model.mass(
mass, x_q, solution[q_index], solution_dot[q_index]);
435 for (
uint i = 0; i < n_dofs; ++i) {
436 const auto component_i =
fe.system_to_component_index(i).first;
437 copy_data.cell_residual(i) += JxW[q_index] * weight *
438 (-scalar_product(fe_v.shape_grad_component(i, q_index, component_i),
440 + fe_v.shape_value_component(i, q_index, component_i) *
441 source[component_i]);
442 copy_data.cell_residual(i) += weight_mass * JxW[q_index] *
443 fe_v.shape_value_component(i, q_index, component_i) *
448 const auto boundary_worker = [&](
const Iterator &cell,
const uint &face_no, Scratch &scratch_data,
449 CopyData ©_data) {
450 scratch_data.fe_interface_values.reinit(cell, face_no);
451 const auto &fe_fv = scratch_data.fe_interface_values.get_fe_face_values(0);
452 const uint n_dofs = fe_fv.get_fe().n_dofs_per_cell();
454 const auto &JxW = fe_fv.get_JxW_values();
455 const auto &q_points = fe_fv.get_quadrature_points();
456 const auto &q_indices = fe_fv.quadrature_point_indices();
457 const std::vector<Tensor<1, dim>> &normals = fe_fv.get_normal_vectors();
459 auto &solution = scratch_data.solution_interface[0];
460 auto &solution_grad = scratch_data.solution_grad_interface[0];
461 auto &solution_hess = scratch_data.solution_hess_interface[0];
462 fe_fv.get_function_values(solution_global, solution);
463 fe_fv.get_function_gradients(solution_global, solution_grad);
464 fe_fv.get_function_hessians(solution_global, solution_hess);
466 array<Tensor<1, dim, NumberType>, Components::count_fe_functions()> numflux{};
467 for (
const auto &q_index : q_indices) {
468 const auto &x_q = q_points[q_index];
469 model.boundary_numflux(
470 numflux, normals[q_index], x_q,
471 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
473 for (
uint i = 0; i < n_dofs; ++i) {
474 const auto component_i =
fe.system_to_component_index(i).first;
475 copy_data.cell_residual(i) +=
476 weight * JxW[q_index] *
477 (fe_fv.shape_value_component(i, q_index, component_i) *
478 scalar_product(numflux[component_i], normals[q_index]));
482 const auto face_worker = [&](
const Iterator &cell,
const uint &f,
const unsigned int &sf,
const Iterator &ncell,
483 const unsigned int &nf,
const unsigned int &nsf, Scratch &scratch_data,
484 CopyData ©_data) {
485 scratch_data.fe_interface_values.reinit(cell, f, sf, ncell, nf, nsf);
486 const auto &fe_iv = scratch_data.fe_interface_values;
487 const auto &fe_iv_s = scratch_data.fe_interface_values.get_fe_face_values(0);
488 const auto &fe_iv_n = scratch_data.fe_interface_values.get_fe_face_values(1);
489 const uint n_dofs = fe_iv.n_current_interface_dofs();
491 copy_data.face_data.emplace_back();
492 auto ©_data_face = copy_data.face_data.back();
493 copy_data_face.reinit(fe_iv);
495 const auto &JxW = fe_iv.get_JxW_values();
496 const auto &q_points = fe_iv.get_quadrature_points();
497 const auto &q_indices = fe_iv.quadrature_point_indices();
498 const std::vector<Tensor<1, dim>> &normals = fe_iv.get_normal_vectors();
500 auto &solution_s = scratch_data.solution_interface[0];
501 auto &solution_n = scratch_data.solution_interface[1];
502 auto &solution_grad_s = scratch_data.solution_grad_interface[0];
503 auto &solution_grad_n = scratch_data.solution_grad_interface[1];
504 auto &solution_hess_s = scratch_data.solution_hess_interface[0];
505 auto &solution_hess_n = scratch_data.solution_hess_interface[1];
506 fe_iv_s.get_function_values(solution_global, solution_s);
507 fe_iv_n.get_function_values(solution_global, solution_n);
508 fe_iv_s.get_function_gradients(solution_global, solution_grad_s);
509 fe_iv_n.get_function_gradients(solution_global, solution_grad_n);
510 fe_iv_s.get_function_hessians(solution_global, solution_hess_s);
511 fe_iv_n.get_function_hessians(solution_global, solution_hess_n);
513 array<Tensor<1, dim, NumberType>, Components::count_fe_functions()> numflux{};
514 for (
const auto &q_index : q_indices) {
515 const auto &x_q = q_points[q_index];
516 model.numflux(numflux, normals[q_index], x_q,
517 fe_tie(solution_s[q_index], solution_grad_s[q_index], solution_hess_s[q_index],
518 extracted_data, variables),
519 fe_tie(solution_n[q_index], solution_grad_n[q_index], solution_hess_n[q_index],
520 extracted_data, variables));
522 for (
uint i = 0; i < n_dofs; ++i) {
523 const auto &cd_i = fe_iv.interface_dof_to_dof_indices(i);
524 const auto component_i = cd_i[0] == numbers::invalid_unsigned_int
525 ?
fe.system_to_component_index(cd_i[1]).first
526 :
fe.system_to_component_index(cd_i[0]).first;
527 copy_data_face.cell_residual(i) +=
528 weight * JxW[q_index] *
529 (fe_iv.jump_in_shape_values(i, q_index, component_i) *
530 scalar_product(numflux[component_i],
535 const auto copier = [&](
const CopyData &c) {
536 constraints.distribute_local_to_global(c.cell_residual, c.local_dof_indices,
residual);
537 for (
auto &cdf : c.face_data)
538 constraints.distribute_local_to_global(cdf.cell_residual, cdf.joint_dof_indices,
residual);
543 MeshWorker::AssembleFlags flags = MeshWorker::assemble_own_cells | MeshWorker::assemble_boundary_faces |
544 MeshWorker::assemble_own_interior_faces_once;
612 using Iterator =
typename DoFHandler<dim>::active_cell_iterator;
618 std::array<
NumberType, Components::count_extractors()> __extracted_data{{}};
619 if constexpr (Components::count_extractors() > 0) {
620 this->
extract(__extracted_data, solution_global, variables,
true,
true,
true);
624 const auto &extracted_data = __extracted_data;
626 const auto cell_worker = [&](
const Iterator &cell, Scratch &scratch_data, CopyData ©_data) {
627 scratch_data.fe_values.reinit(cell);
628 const auto &fe_v = scratch_data.fe_values;
629 const uint n_dofs = fe_v.get_fe().n_dofs_per_cell();
631 copy_data.reinit(cell, n_dofs, Components::count_extractors());
632 const auto &JxW = fe_v.get_JxW_values();
633 const auto &q_points = fe_v.get_quadrature_points();
634 const auto &q_indices = fe_v.quadrature_point_indices();
636 auto &solution = scratch_data.solution;
637 auto &solution_dot = scratch_data.solution_dot;
638 auto &solution_grad = scratch_data.solution_grad;
639 auto &solution_hess = scratch_data.solution_hess;
641 fe_v.get_function_values(solution_global, solution);
642 fe_v.get_function_values(solution_global_dot, solution_dot);
643 fe_v.get_function_gradients(solution_global, solution_grad);
644 fe_v.get_function_hessians(solution_global, solution_hess);
658 for (
const auto &q_index : q_indices) {
659 const auto &x_q = q_points[q_index];
660 model.template jacobian_flux<0, 0>(
662 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
663 model.template jacobian_source<0, 0>(
665 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
666 model.template jacobian_flux_grad<1>(
668 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
669 model.template jacobian_source_grad<1>(
671 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
672 model.template jacobian_flux_hess<2>(
674 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
675 model.template jacobian_source_hess<2>(
677 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
678 if constexpr (Components::count_extractors() > 0) {
679 model.template jacobian_flux_extr<3>(
681 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
682 model.template jacobian_source_extr<3>(
684 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
689 for (
uint i = 0; i < n_dofs; ++i) {
690 const auto component_i =
fe.system_to_component_index(i).first;
691 for (
uint j = 0; j < n_dofs; ++j) {
692 const auto component_j =
fe.system_to_component_index(j).first;
694 copy_data.cell_jacobian(i, j) += weight * JxW[q_index] *
695 fe_v.shape_value_component(j, q_index, component_j) *
696 (-scalar_product(fe_v.shape_grad_component(i, q_index, component_i),
697 j_flux(component_i, component_j))
698 + fe_v.shape_value_component(i, q_index, component_i) *
699 j_source(component_i, component_j));
701 copy_data.cell_jacobian(i, j) +=
702 weight * JxW[q_index] *
703 scalar_product(fe_v.shape_grad_component(j, q_index, component_j),
704 -scalar_product(fe_v.shape_grad_component(i, q_index, component_i),
705 j_grad_flux(component_i, component_j))
706 + fe_v.shape_value_component(i, q_index, component_i) *
707 j_grad_source(component_i, component_j));
709 copy_data.cell_jacobian(i, j) +=
710 weight * JxW[q_index] *
711 scalar_product(fe_v.shape_hessian_component(j, q_index, component_j),
712 -scalar_product(fe_v.shape_grad_component(i, q_index, component_i),
713 j_hess_flux(component_i, component_j)) +
714 fe_v.shape_value_component(i, q_index, component_i) *
715 j_hess_source(component_i, component_j));
717 copy_data.cell_jacobian(i, j) +=
718 JxW[q_index] * fe_v.shape_value_component(j, q_index, component_j) *
719 fe_v.shape_value_component(i, q_index, component_i) *
720 (alpha * j_mass_dot(component_i, component_j) + beta * j_mass(component_i, component_j));
723 if constexpr (Components::count_extractors() > 0)
724 for (
uint e = 0; e < Components::count_extractors(); ++e)
725 copy_data.extractor_cell_jacobian(i, e) +=
726 weight * JxW[q_index] *
727 (-scalar_product(fe_v.shape_grad_component(i, q_index, component_i),
728 j_extr_flux(component_i, e))
729 + fe_v.shape_value_component(i, q_index, component_i) *
730 j_extr_source(component_i, e));
734 const auto boundary_worker = [&](
const Iterator &cell,
const uint &face_no, Scratch &scratch_data,
735 CopyData ©_data) {
736 scratch_data.fe_interface_values.reinit(cell, face_no);
737 const auto &fe_fv = scratch_data.fe_interface_values.get_fe_face_values(0);
738 const uint n_dofs = fe_fv.get_fe().n_dofs_per_cell();
740 const auto &JxW = fe_fv.get_JxW_values();
741 const auto &q_points = fe_fv.get_quadrature_points();
742 const auto &q_indices = fe_fv.quadrature_point_indices();
743 const std::vector<Tensor<1, dim>> &normals = fe_fv.get_normal_vectors();
745 auto &solution = scratch_data.solution_interface[0];
746 auto &solution_grad = scratch_data.solution_grad_interface[0];
747 auto &solution_hess = scratch_data.solution_hess_interface[0];
748 fe_fv.get_function_values(solution_global, solution);
749 fe_fv.get_function_gradients(solution_global, solution_grad);
750 fe_fv.get_function_hessians(solution_global, solution_hess);
754 j_grad_boundary_numflux;
756 j_hess_boundary_numflux;
758 j_extr_boundary_numflux;
759 for (
const auto &q_index : q_indices) {
760 const auto &x_q = q_points[q_index];
761 model.template jacobian_boundary_numflux<0, 0>(
762 j_boundary_numflux, normals[q_index], x_q,
763 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
764 model.template jacobian_boundary_numflux_grad<1>(
765 j_grad_boundary_numflux, normals[q_index], x_q,
766 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
767 model.template jacobian_boundary_numflux_hess<2>(
768 j_hess_boundary_numflux, normals[q_index], x_q,
769 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
770 if constexpr (Components::count_extractors() > 0) {
771 model.template jacobian_boundary_numflux_extr<3>(
772 j_extr_boundary_numflux, normals[q_index], x_q,
773 fe_tie(solution[q_index], solution_grad[q_index], solution_hess[q_index], extracted_data, variables));
776 for (
uint i = 0; i < n_dofs; ++i) {
777 const auto component_i =
fe.system_to_component_index(i).first;
778 for (
uint j = 0; j < n_dofs; ++j) {
779 const auto component_j =
fe.system_to_component_index(j).first;
781 copy_data.cell_jacobian(i, j) +=
782 weight * JxW[q_index] * fe_fv.shape_value_component(j, q_index, component_j) *
783 (fe_fv.shape_value_component(i, q_index, component_i) *
784 scalar_product(j_boundary_numflux(component_i, component_j),
787 copy_data.cell_jacobian(i, j) +=
788 weight * JxW[q_index] *
789 scalar_product(fe_fv.shape_grad_component(j, q_index, component_j),
790 fe_fv.shape_value_component(i, q_index, component_i) *
791 scalar_product(j_grad_boundary_numflux(component_i, component_j),
794 copy_data.cell_jacobian(i, j) +=
795 weight * JxW[q_index] *
796 scalar_product(fe_fv.shape_hessian_component(j, q_index, component_j),
797 fe_fv.shape_value_component(i, q_index, component_i) *
798 scalar_product(j_hess_boundary_numflux(component_i, component_j),
802 if constexpr (Components::count_extractors() > 0)
803 for (
uint e = 0; e < Components::count_extractors(); ++e)
804 copy_data.extractor_cell_jacobian(i, e) +=
805 weight * JxW[q_index] *
806 (fe_fv.shape_value_component(i, q_index, component_i) *
807 scalar_product(j_extr_boundary_numflux(component_i, e),
812 const auto face_worker = [&](
const Iterator &cell,
const uint &f,
const uint &sf,
const Iterator &ncell,
813 const uint &nf,
const uint &nsf, Scratch &scratch_data, CopyData ©_data) {
814 scratch_data.fe_interface_values.reinit(cell, f, sf, ncell, nf, nsf);
815 const auto &fe_iv = scratch_data.fe_interface_values;
816 const auto &fe_iv_s = scratch_data.fe_interface_values.get_fe_face_values(0);
817 const auto &fe_iv_n = scratch_data.fe_interface_values.get_fe_face_values(1);
818 const uint n_dofs = fe_iv.n_current_interface_dofs();
820 copy_data.face_data.emplace_back();
821 auto ©_data_face = copy_data.face_data.back();
822 copy_data_face.reinit(fe_iv, Components::count_extractors());
824 const auto &JxW = fe_iv.get_JxW_values();
825 const auto &q_points = fe_iv.get_quadrature_points();
826 const auto &q_indices = fe_iv.quadrature_point_indices();
827 const std::vector<Tensor<1, dim>> &normals = fe_iv.get_normal_vectors();
829 auto &solution_s = scratch_data.solution_interface[0];
830 auto &solution_n = scratch_data.solution_interface[1];
831 auto &solution_grad_s = scratch_data.solution_grad_interface[0];
832 auto &solution_grad_n = scratch_data.solution_grad_interface[1];
833 auto &solution_hess_s = scratch_data.solution_hess_interface[0];
834 auto &solution_hess_n = scratch_data.solution_hess_interface[1];
835 fe_iv_s.get_function_values(solution_global, solution_s);
836 fe_iv_n.get_function_values(solution_global, solution_n);
837 fe_iv_s.get_function_gradients(solution_global, solution_grad_s);
838 fe_iv_n.get_function_gradients(solution_global, solution_grad_n);
839 fe_iv_s.get_function_hessians(solution_global, solution_hess_s);
840 fe_iv_n.get_function_hessians(solution_global, solution_hess_n);
842 array<SimpleMatrix<Tensor<1, dim, NumberType>, Components::count_fe_functions()>, 2> j_numflux;
843 array<SimpleMatrix<Tensor<1, dim, Tensor<1, dim, NumberType>>, Components::count_fe_functions()>, 2>
845 array<SimpleMatrix<Tensor<1, dim, Tensor<2, dim, NumberType>>, Components::count_fe_functions()>, 2>
847 array<SimpleMatrix<Tensor<1, dim, NumberType>, Components::count_fe_functions(),
848 Components::count_extractors()>,
851 for (
const auto &q_index : q_indices) {
852 const auto &x_q = q_points[q_index];
853 model.template jacobian_numflux<0, 0>(j_numflux, normals[q_index], x_q,
854 fe_tie(solution_s[q_index], solution_grad_s[q_index],
855 solution_hess_s[q_index], extracted_data, variables),
856 fe_tie(solution_n[q_index], solution_grad_n[q_index],
857 solution_hess_n[q_index], extracted_data, variables));
858 model.template jacobian_numflux_grad<1>(j_grad_numflux, normals[q_index], x_q,
859 fe_tie(solution_s[q_index], solution_grad_s[q_index],
860 solution_hess_s[q_index], extracted_data, variables),
861 fe_tie(solution_n[q_index], solution_grad_n[q_index],
862 solution_hess_n[q_index], extracted_data, variables));
863 model.template jacobian_numflux_hess<2>(j_hess_numflux, normals[q_index], x_q,
864 fe_tie(solution_s[q_index], solution_grad_s[q_index],
865 solution_hess_s[q_index], extracted_data, variables),
866 fe_tie(solution_n[q_index], solution_grad_n[q_index],
867 solution_hess_n[q_index], extracted_data, variables));
868 if constexpr (Components::count_extractors() > 0) {
869 model.template jacobian_numflux_extr<3>(j_extr_numflux, normals[q_index], x_q,
870 fe_tie(solution_s[q_index], solution_grad_s[q_index],
871 solution_hess_s[q_index], extracted_data, variables),
872 fe_tie(solution_n[q_index], solution_grad_n[q_index],
873 solution_hess_n[q_index], extracted_data, variables));
876 for (
uint i = 0; i < n_dofs; ++i) {
877 const auto &cd_i = fe_iv.interface_dof_to_dof_indices(i);
878 const uint face_no_i = cd_i[0] == numbers::invalid_unsigned_int ? 1 : 0;
879 const auto &component_i =
fe.system_to_component_index(cd_i[face_no_i]).first;
880 for (
uint j = 0; j < n_dofs; ++j) {
881 const auto &cd_j = fe_iv.interface_dof_to_dof_indices(j);
882 const uint face_no_j = cd_j[0] == numbers::invalid_unsigned_int ? 1 : 0;
883 const auto &component_j =
fe.system_to_component_index(cd_j[face_no_j]).first;
885 copy_data_face.cell_jacobian(i, j) +=
886 weight * JxW[q_index] *
887 fe_iv.get_fe_face_values(face_no_j).shape_value_component(cd_j[face_no_j], q_index,
889 (fe_iv.jump_in_shape_values(i, q_index, component_i) *
890 scalar_product(j_numflux[face_no_j](component_i, component_j),
893 copy_data_face.cell_jacobian(i, j) +=
894 weight * JxW[q_index] *
895 scalar_product(fe_iv.get_fe_face_values(face_no_j).shape_grad_component(
896 cd_j[face_no_j], q_index, component_j),
897 fe_iv.jump_in_shape_values(i, q_index, component_i) *
898 scalar_product(j_grad_numflux[face_no_j](component_i, component_j),
901 copy_data_face.cell_jacobian(i, j) +=
902 weight * JxW[q_index] *
904 fe_iv.get_fe_face_values(face_no_j).shape_hessian_component(cd_j[face_no_j], q_index,
906 fe_iv.jump_in_shape_values(i, q_index, component_i) *
907 scalar_product(j_hess_numflux[face_no_j](component_i, component_j),
911 if constexpr (Components::count_extractors() > 0)
912 for (
uint e = 0; e < Components::count_extractors(); ++e)
913 copy_data_face.extractor_cell_jacobian(i, e) +=
914 weight * JxW[q_index] *
915 (fe_iv.jump_in_shape_values(i, q_index, component_i) *
916 scalar_product(j_extr_numflux[face_no_i](component_i, e),
921 const auto copier = [&](
const CopyData &c) {
922 constraints.distribute_local_to_global(c.cell_jacobian, c.local_dof_indices,
jacobian);
923 for (
auto &cdf : c.face_data) {
924 constraints.distribute_local_to_global(cdf.cell_jacobian, cdf.joint_dof_indices,
jacobian);
925 if constexpr (Components::count_extractors() > 0) {
926 FullMatrix<NumberType> extractor_dependence(cdf.joint_dof_indices.size(),
extractor_dof_indices.size());
928 constraints.distribute_local_to_global(extractor_dependence, cdf.joint_dof_indices,
extractor_dof_indices,
932 if constexpr (Components::count_extractors() > 0) {
933 FullMatrix<NumberType> extractor_dependence(c.local_dof_indices.size(),
extractor_dof_indices.size());
935 constraints.distribute_local_to_global(extractor_dependence, c.local_dof_indices,
extractor_dof_indices,
942 MeshWorker::AssembleFlags flags = MeshWorker::assemble_own_cells | MeshWorker::assemble_boundary_faces |
943 MeshWorker::assemble_own_interior_faces_once;