@@ -380,13 +380,36 @@ StaticCondensation::backwards_substitution(const NumericVector<Number> & full_rh
380
380
NumericVector < Number > & full_sol )
381
381
{
382
382
std ::vector < dof_id_type > elem_dofs ; // only used to satisfy API
383
- std ::vector < dof_id_type > elem_interior_dofs ;
383
+ std ::vector < dof_id_type > elem_interior_dofs , elem_trace_dofs ;
384
384
std ::vector < Number > elem_interior_rhs_vec , elem_trace_sol_vec ;
385
385
EigenVector elem_interior_rhs , elem_trace_sol , elem_interior_sol ;
386
386
387
+ auto scalar_dofs_functor =
388
+ [& elem_interior_dofs , & elem_trace_dofs ](const Elem & elem ,
389
+ std ::vector < dof_id_type > & dof_indices ,
390
+ const std ::vector < dof_id_type > & scalar_dof_indices )
391
+ {
392
+ computeElemInteriorDofsScalar (elem_interior_dofs )(elem , dof_indices , scalar_dof_indices );
393
+ elem_trace_dofs .insert (
394
+ elem_trace_dofs .end (), scalar_dof_indices .begin (), scalar_dof_indices .end ());
395
+ };
396
+
397
+ auto field_dofs_functor =
398
+ [& elem_interior_dofs , & elem_trace_dofs ](const Elem & elem ,
399
+ const unsigned int node_num ,
400
+ std ::vector < dof_id_type > & dof_indices ,
401
+ const dof_id_type field_dof )
402
+ {
403
+ computeElemInteriorDofsField (elem_interior_dofs )(elem , node_num , dof_indices , field_dof );
404
+
405
+ if (node_num != invalid_uint && !elem .is_internal (node_num ))
406
+ elem_trace_dofs .push_back (field_dof );
407
+ };
408
+
387
409
for (auto elem : _mesh .active_local_element_ptr_range ())
388
410
{
389
411
elem_interior_dofs .clear ();
412
+ elem_trace_dofs .clear ();
390
413
auto & local_data = _elem_to_local_data [elem -> id ()];
391
414
392
415
const auto sub_id = elem -> subdomain_id ();
@@ -397,17 +420,12 @@ StaticCondensation::backwards_substitution(const NumericVector<Number> & full_rh
397
420
continue ;
398
421
399
422
for (const auto v : make_range (var_group .n_variables ()))
400
- _dof_map .dof_indices (elem ,
401
- elem_dofs ,
402
- v ,
403
- computeElemInteriorDofsScalar (elem_interior_dofs ),
404
- computeElemInteriorDofsField (elem_interior_dofs ),
405
- elem -> p_level ());
423
+ _dof_map .dof_indices (
424
+ elem , elem_dofs , v , scalar_dofs_functor , field_dofs_functor , elem -> p_level ());
406
425
}
407
426
408
427
set_local_vectors (full_rhs , elem_interior_dofs , elem_interior_rhs_vec , elem_interior_rhs );
409
- set_local_vectors (
410
- * _reduced_sol , local_data .reduced_space_indices , elem_trace_sol_vec , elem_trace_sol );
428
+ set_local_vectors (full_sol , elem_trace_dofs , elem_trace_sol_vec , elem_trace_sol );
411
429
412
430
elem_interior_sol =
413
431
local_data .AiiFactor .solve (elem_interior_rhs - local_data .Aib * elem_trace_sol );
@@ -424,7 +442,9 @@ StaticCondensation::solve(const NumericVector<Number> & full_rhs, NumericVector<
424
442
forward_elimination (full_rhs );
425
443
_reduced_sol = full_sol .get_subvector (_local_trace_dofs );
426
444
_reduced_solver -> solve (* _reduced_sys_mat , * _reduced_sol , * _reduced_rhs , 1e-5 , 300 );
427
- backwards_substitution (full_rhs , full_sol );
445
+ // Must restore to the full solution because during backwards substitution we will need to be able
446
+ // to read ghosted dofs and we don't support ghosting of subvectors
428
447
full_sol .restore_subvector (std ::move (_reduced_sol ), _local_trace_dofs );
448
+ backwards_substitution (full_rhs , full_sol );
429
449
}
430
450
}
0 commit comments