@@ -2622,6 +2622,207 @@ void DofMap::heterogeneously_constrain_element_matrix_and_vector (DenseMatrix<Nu
26222622}
26232623
26242624
2625+ void DofMap ::heterogeneously_constrain_element_jacobian_and_residual
2626+ (DenseMatrix < Number > & matrix ,
2627+ DenseVector < Number > & rhs ,
2628+ std ::vector < dof_id_type > & elem_dofs ,
2629+ NumericVector < Number > & solution_local ) const
2630+ {
2631+ libmesh_assert_equal_to (elem_dofs .size (), matrix .m ());
2632+ libmesh_assert_equal_to (elem_dofs .size (), matrix .n ());
2633+ libmesh_assert_equal_to (elem_dofs .size (), rhs .size ());
2634+
2635+ libmesh_assert (solution_local .type () == SERIAL ||
2636+ solution_local .type () == GHOSTED );
2637+
2638+ // check for easy return
2639+ if (this -> _dof_constraints .empty ())
2640+ return ;
2641+
2642+ // The constrained matrix is built up as C^T K C.
2643+ // The constrained RHS is built up as C^T F
2644+ // Asymmetric residual terms are added if we do not have x = Cx+h
2645+ DenseMatrix < Number > C ;
2646+ DenseVector < Number > H ;
2647+
2648+ this -> build_constraint_matrix_and_vector (C , H , elem_dofs );
2649+
2650+ LOG_SCOPE ("hetero_cnstrn_elem_jac_res ()", "DofMap ");
2651+
2652+ // It is possible that the matrix is not constrained at all.
2653+ if ((C .m () != matrix .m ()) ||
2654+ (C .n () != elem_dofs .size ()))
2655+ return ;
2656+
2657+ // Compute the matrix-vector product C^T F
2658+ DenseVector < Number > old_rhs (rhs );
2659+ C .vector_mult_transpose (rhs , old_rhs );
2660+
2661+ // Compute the matrix-matrix-matrix product C^T K C
2662+ matrix .left_multiply_transpose (C );
2663+ matrix .right_multiply (C );
2664+
2665+ libmesh_assert_equal_to (matrix .m (), matrix .n ());
2666+ libmesh_assert_equal_to (matrix .m (), elem_dofs .size ());
2667+ libmesh_assert_equal_to (matrix .n (), elem_dofs .size ());
2668+
2669+ for (unsigned int i = 0 ,
2670+ n_elem_dofs = cast_int < unsigned int > (elem_dofs .size ());
2671+ i != n_elem_dofs ; i ++ )
2672+ {
2673+ const dof_id_type dof_id = elem_dofs [i ];
2674+
2675+ const DofConstraints ::const_iterator
2676+ pos = _dof_constraints .find (dof_id );
2677+
2678+ if (pos != _dof_constraints .end ())
2679+ {
2680+ for (auto j : make_range (matrix .n ()))
2681+ matrix (i ,j ) = 0. ;
2682+
2683+ // If the DOF is constrained
2684+ matrix (i ,i ) = 1. ;
2685+
2686+ // This will put a nonsymmetric entry in the constraint
2687+ // row to ensure that the linear system produces the
2688+ // correct value for the constrained DOF.
2689+ const DofConstraintRow & constraint_row = pos -> second ;
2690+
2691+ for (const auto & item : constraint_row )
2692+ for (unsigned int j = 0 ; j != n_elem_dofs ; j ++ )
2693+ if (elem_dofs [j ] == item .first )
2694+ matrix (i ,j ) = - item .second ;
2695+
2696+ const DofConstraintValueMap ::const_iterator valpos =
2697+ _primal_constraint_values .find (dof_id );
2698+
2699+ Number & rhs_val = rhs (i );
2700+ rhs_val = (valpos == _primal_constraint_values .end ()) ?
2701+ 0 : - valpos -> second ;
2702+ for (const auto & [constraining_dof , coef ] : constraint_row )
2703+ rhs_val -= coef * solution_local (constraining_dof );
2704+ rhs_val += solution_local (dof_id );
2705+ }
2706+ }
2707+ }
2708+
2709+
2710+ void DofMap ::heterogeneously_constrain_element_residual
2711+ (DenseVector < Number > & rhs ,
2712+ std ::vector < dof_id_type > & elem_dofs ,
2713+ NumericVector < Number > & solution_local ) const
2714+ {
2715+ libmesh_assert_equal_to (elem_dofs .size (), rhs .size ());
2716+
2717+ libmesh_assert (solution_local .type () == SERIAL ||
2718+ solution_local .type () == GHOSTED );
2719+
2720+ // check for easy return
2721+ if (this -> _dof_constraints .empty ())
2722+ return ;
2723+
2724+ // The constrained RHS is built up as C^T F
2725+ // Asymmetric residual terms are added if we do not have x = Cx+h
2726+ DenseMatrix < Number > C ;
2727+ DenseVector < Number > H ;
2728+
2729+ this -> build_constraint_matrix_and_vector (C , H , elem_dofs );
2730+
2731+ LOG_SCOPE ("hetero_cnstrn_elem_res ()", "DofMap ");
2732+
2733+ // It is possible that the element is not constrained at all.
2734+ if ((C .m () != rhs .size ()) ||
2735+ (C .n () != elem_dofs .size ()))
2736+ return ;
2737+
2738+ // Compute the matrix-vector product C^T F
2739+ DenseVector < Number > old_rhs (rhs );
2740+ C .vector_mult_transpose (rhs , old_rhs );
2741+
2742+ for (unsigned int i = 0 ,
2743+ n_elem_dofs = cast_int < unsigned int > (elem_dofs .size ());
2744+ i != n_elem_dofs ; i ++ )
2745+ {
2746+ const dof_id_type dof_id = elem_dofs [i ];
2747+
2748+ const DofConstraints ::const_iterator
2749+ pos = _dof_constraints .find (dof_id );
2750+
2751+ if (pos != _dof_constraints .end ())
2752+ {
2753+ // This will put a nonsymmetric entry in the constraint
2754+ // row to ensure that the linear system produces the
2755+ // correct value for the constrained DOF.
2756+ const DofConstraintRow & constraint_row = pos -> second ;
2757+
2758+ const DofConstraintValueMap ::const_iterator valpos =
2759+ _primal_constraint_values .find (dof_id );
2760+
2761+ Number & rhs_val = rhs (i );
2762+ rhs_val = (valpos == _primal_constraint_values .end ()) ?
2763+ 0 : - valpos -> second ;
2764+ for (const auto & [constraining_dof , coef ] : constraint_row )
2765+ rhs_val -= coef * solution_local (constraining_dof );
2766+ rhs_val += solution_local (dof_id );
2767+ }
2768+ }
2769+ }
2770+
2771+
2772+ void DofMap ::constrain_element_residual
2773+ (DenseVector < Number > & rhs ,
2774+ std ::vector < dof_id_type > & elem_dofs ,
2775+ NumericVector < Number > & solution_local ) const
2776+ {
2777+ libmesh_assert_equal_to (elem_dofs .size (), rhs .size ());
2778+
2779+ libmesh_assert (solution_local .type () == SERIAL ||
2780+ solution_local .type () == GHOSTED );
2781+
2782+ // check for easy return
2783+ if (this -> _dof_constraints .empty ())
2784+ return ;
2785+
2786+ // The constrained RHS is built up as C^T F
2787+ DenseMatrix < Number > C ;
2788+
2789+ this -> build_constraint_matrix (C , elem_dofs );
2790+
2791+ LOG_SCOPE ("cnstrn_elem_residual ()", "DofMap ");
2792+
2793+ // It is possible that the matrix is not constrained at all.
2794+ if (C .n () != elem_dofs .size ())
2795+ return ;
2796+
2797+ // Compute the matrix-vector product C^T F
2798+ DenseVector < Number > old_rhs (rhs );
2799+ C .vector_mult_transpose (rhs , old_rhs );
2800+
2801+ for (unsigned int i = 0 ,
2802+ n_elem_dofs = cast_int < unsigned int > (elem_dofs .size ());
2803+ i != n_elem_dofs ; i ++ )
2804+ {
2805+ const dof_id_type dof_id = elem_dofs [i ];
2806+
2807+ const DofConstraints ::const_iterator
2808+ pos = _dof_constraints .find (dof_id );
2809+
2810+ if (pos != _dof_constraints .end ())
2811+ {
2812+ // This will put a nonsymmetric entry in the constraint
2813+ // row to ensure that the linear system produces the
2814+ // correct value for the constrained DOF.
2815+ const DofConstraintRow & constraint_row = pos -> second ;
2816+
2817+ Number & rhs_val = rhs (i );
2818+ rhs_val = 0 ;
2819+ for (const auto & [constraining_dof , coef ] : constraint_row )
2820+ rhs_val -= coef * solution_local (constraining_dof );
2821+ rhs_val += solution_local (dof_id );
2822+ }
2823+ }
2824+ }
2825+
26252826
26262827void DofMap ::heterogeneously_constrain_element_vector (const DenseMatrix < Number > & matrix ,
26272828 DenseVector < Number > & rhs ,
0 commit comments