Skip to content

Default block restriction #30300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions framework/doc/content/source/interfaces/BlockRestrictable.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ subset of the mesh domain corresponding to a subdomain. This interface provides
function that also supports a uniform way of handing reading in subdomain restrictions. Specifically,
every object may be restricted to one or more subdomains simultaneously. Subdomains may be specified
either as numeric IDs or strings (when supported by the Mesh format or named entities are used).
When the user sets `default_block` in the `[Problem]` block, the specified block restriction will be
automatically applied to all objects inheriting the BlockRestrictable interface. Users can still override
this behavior by explicitly specifying the `block` parameter within each object.
Finally, this interface handles queries about the set of subdomains that an object is restricted
to when no restrictions are supplied.
8 changes: 8 additions & 0 deletions framework/include/problems/FEProblemBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -2395,6 +2395,11 @@ class FEProblemBase : public SubProblem, public Restartable
*/
const std::vector<LinearSystemName> & getLinearSystemNames() const { return _linear_sys_names; }

/**
* @returns the default blocks (for block restriction)
*/
const std::vector<SubdomainName> getDefaultBlocks() const { return _default_blocks; };

protected:
/// Create extra tagged vectors and matrices
void createTagVectors();
Expand Down Expand Up @@ -2732,6 +2737,9 @@ class FEProblemBase : public SubProblem, public Restartable

std::vector<SolverParams> _solver_params;

/// Default blocks for block restriction
std::vector<SubdomainName> _default_blocks;

/// Determines whether and which subdomains are to be checked to ensure that they have an active kernel
CoverageCheckMode _kernel_coverage_check;
std::vector<SubdomainName> _kernel_coverage_blocks;
Expand Down
3 changes: 3 additions & 0 deletions framework/src/actions/AddVariableAction.C
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,9 @@ AddVariableAction::getSubdomainIDs()
std::set<SubdomainID> blocks;
std::vector<SubdomainName> block_param =
_moose_object_pars.get<std::vector<SubdomainName>>("block");
if (block_param.empty() && _problem->isParamSetByUser("default_block"))
block_param = _problem->getDefaultBlocks();

for (const auto & subdomain_name : block_param)
{
SubdomainID blk_id = _problem->mesh().getSubdomainID(subdomain_name);
Expand Down
11 changes: 11 additions & 0 deletions framework/src/interfaces/BlockRestrictable.C
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ BlockRestrictable::initializeBlockRestrictable(const MooseObject * moose_object)
.activeSubdomains();
}

// when 'default_block' is set at the [Problem] -> 'block and variable' input should come first
// before this
else if (_blk_feproblem->isParamSetByUser("default_block"))
{
_blocks = _blk_feproblem->getDefaultBlocks();
// Get the IDs from the supplied names
_vec_ids = _blk_mesh->getSubdomainIDs(_blocks);

_blk_ids.insert(_vec_ids.begin(), _vec_ids.end());
}

// Produce error if the object is not allowed to be both block and boundary restricted
if (!_blk_dual_restrictable && !_boundary_ids.empty() && !_boundary_ids.empty())
if (!_boundary_ids.empty() && _boundary_ids.find(Moose::ANY_BOUNDARY_ID) == _boundary_ids.end())
Expand Down
26 changes: 21 additions & 5 deletions framework/src/problems/FEProblemBase.C
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ FEProblemBase::validParams()
"be used (again, using the parameter '" +
list_param_name + "').";
};

params.addParam<std::vector<SubdomainName>>(
"default_block",
{},
"Default list of subdomains for block-restrictable objects such as kernels and materials.");

MooseEnum kernel_coverage_check_modes("FALSE TRUE OFF ON SKIP_LIST ONLY_LIST", "TRUE");
params.addParam<MooseEnum>("kernel_coverage_check",
kernel_coverage_check_modes,
Expand Down Expand Up @@ -446,16 +452,27 @@ FEProblemBase::FEProblemBase(const InputParameters & parameters)
_previous_nl_solution_required(getParam<bool>("previous_nl_solution_required")),
_has_nonlocal_coupling(false),
_calculate_jacobian_in_uo(false),
_default_blocks(getParam<std::vector<SubdomainName>>("default_block")),
_kernel_coverage_check(
getParam<MooseEnum>("kernel_coverage_check").getEnum<CoverageCheckMode>()),
_kernel_coverage_blocks(getParam<std::vector<SubdomainName>>("kernel_coverage_block_list")),
isParamSetByUser("kernel_coverage_check") || !isParamSetByUser("default_block")
? getParam<MooseEnum>("kernel_coverage_check").getEnum<CoverageCheckMode>()
: CoverageCheckMode::ONLY_LIST),
_kernel_coverage_blocks(isParamSetByUser("kernel_coverage_check") ||
!isParamSetByUser("default_block")
? getParam<std::vector<SubdomainName>>("kernel_coverage_block_list")
: _default_blocks),
_boundary_restricted_node_integrity_check(
getParam<bool>("boundary_restricted_node_integrity_check")),
_boundary_restricted_elem_integrity_check(
getParam<bool>("boundary_restricted_elem_integrity_check")),
_material_coverage_check(
getParam<MooseEnum>("material_coverage_check").getEnum<CoverageCheckMode>()),
_material_coverage_blocks(getParam<std::vector<SubdomainName>>("material_coverage_block_list")),
isParamSetByUser("material_coverage_check") || !isParamSetByUser("default_block")
? getParam<MooseEnum>("material_coverage_check").getEnum<CoverageCheckMode>()
: CoverageCheckMode::ONLY_LIST),
_material_coverage_blocks(
isParamSetByUser("material_coverage_check") || !isParamSetByUser("default_block")
? getParam<std::vector<SubdomainName>>("material_coverage_block_list")
: _default_blocks),
_fv_bcs_integrity_check(getParam<bool>("fv_bcs_integrity_check")),
_material_dependency_check(getParam<bool>("material_dependency_check")),
_uo_aux_state_check(getParam<bool>("check_uo_aux_state")),
Expand Down Expand Up @@ -2674,7 +2691,6 @@ FEProblemBase::duplicateVariableCheck(const std::string & var_name,
bool is_aux,
const std::set<SubdomainID> * const active_subdomains)
{

std::set<SubdomainID> subdomainIDs;
if (active_subdomains->size() == 0)
{
Expand Down
5 changes: 4 additions & 1 deletion framework/src/systems/SystemBase.C
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,10 @@ SystemBase::addVariable(const std::string & var_type,
// Convert the std::vector parameter provided by the user into a std::set for use by libMesh's
// System::add_variable method
std::set<SubdomainID> blocks;
const auto & block_param = parameters.get<std::vector<SubdomainName>>("block");
auto block_param = parameters.get<std::vector<SubdomainName>>("block");
if (block_param.empty() && _fe_problem.isParamValid("default_block"))
block_param = _fe_problem.getDefaultBlocks();

for (const auto & subdomain_name : block_param)
{
SubdomainID blk_id = _mesh.getSubdomainID(subdomain_name);
Expand Down
54 changes: 54 additions & 0 deletions modules/doc/content/framework_development/sanity_checking.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,57 @@ pair of parameters used in testing can be used to disable the kernel coverage ch
solve = false
[]
```

By default, MOOSE assumes the computational domain to be the entire mesh. However, some simulations set up using subdomain modifiers or lower-dimensional blocks (such as mortar contact) describe the computational domain of the underlying problem on a subset of the mesh.

In such cases, the common approach is to either:

- Disable kernel coverage checks entirely by setting:

```
[Problem]
kernel_coverage_check = false
[]
```

- Restrict the kernel coverage check to specific blocks by setting:

```
[Problem]
kernel_coverage_check = ONLY_LIST
kernel_coverage_block_list = 'block1 block2 block4'
[]
```

In addition, when certain material properties are block restricted to the computational domain, users must also manually set:

```
[Problem]
material_coverage_check = ONLY_LIST
material_coverage_block_list = 'block1 block2 block4'
[]
```
to skip the material coverage check outside the computational domain.

This manual setup is not only repetitive but also error-prone, especially when the same block list needs to be specified in multiple places.

To simplify this process, MOOSE provides a convenient parameter called `default_block` under the \[`Problem`\] block. This allows users to specify the default computational domain and inform MOOSE to skip coverage checks outside the computational domain.

Setting `default_block` will automatically:

- Enable kernel coverage check with `ONLY_LIST` mode and assign the specified blocks to `kernel_coverage_block_list`

- Enable material coverage check with `ONLY_LIST` mode and assign the specified blocks to `material_coverage_block_list`

This provides a more user-friendly and centralized way to handle simulations with a preferred, non-default computational domain.

Example Usage for `default_block`:

```
# Perform kernel and material coverage checks only for block 0, 1, and 3,
# while excluding block 2 as an inactive region.

[Problem]
default_block = '0 1 3'
[]
```
123 changes: 123 additions & 0 deletions test/tests/default_block_check/diffusion_with_null_material.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
[Problem]
default_block = '0 1 3'
[]

[Mesh]
[gmg]
type = GeneratedMeshGenerator
dim = 2
nx = 48
ny = 32
xmin = 0
xmax = 3
ymin = 0
ymax = 2
[]
[block_left]
type = SubdomainBoundingBoxGenerator
input = gmg
block_id = 0
block_name = material_left
bottom_left = '0 0 0'
top_right = '1.25 2.0 0'
[]
[block_right]
type = SubdomainBoundingBoxGenerator
input = block_left
block_id = 1
block_name = material_right
bottom_left = '1.75 0 0'
top_right = '3.0 2.0 0'
[]
[block_middle]
type = SubdomainBoundingBoxGenerator
input = block_right
block_id = 2
block_name = material_null
bottom_left = '1.25 0 0'
top_right = '1.75 2.0 0'
[]
[block_middle_new]
type = SubdomainBoundingBoxGenerator
input = block_middle
block_id = 3
block_name = material_middle
bottom_left = '1.25 1.0 0'
top_right = '1.75 2.0 0'
[]
use_displaced_mesh = false
[]

[Variables]
[diff]
order = FIRST
[]
[]

[Kernels]
[diffusion]
type = MatDiffusion
variable = diff
diffusivity = 'k'
[]
[]

[Materials]
[material_left_cond]
block = 0
type = GenericConstantMaterial
prop_names = 'k'
prop_values = 26.0
[]
[material_right_cond]
block = 1
type = GenericConstantMaterial
prop_names = 'k'
prop_values = 35.0
[]
[material_middle_cond]
block = 3
type = GenericConstantMaterial
prop_names = 'k'
prop_values = 10.0
[]
[]

[BCs]
[left]
type = DirichletBC
variable = diff
boundary = left
value = 10
[]

[right]
type = DirichletBC
variable = diff
boundary = right
value = 0
[]
[]

[Executioner]
type = Transient
solve_type = NEWTON
petsc_options_iname = '-pc_type'
petsc_options_value = 'lu'
dt = 1
end_time = 1
[]

[Postprocessors]
[T3]
type = ElementAverageValue
variable = diff
block = '3'
execute_on = 'INITIAL TIMESTEP_END'
[]
[]

[Outputs]
exodus = true
csv = true
[]
Loading