diff --git a/framework/include/problems/FEProblemBase.h b/framework/include/problems/FEProblemBase.h index 2d6f452c3d1d..0e9e469caa87 100644 --- a/framework/include/problems/FEProblemBase.h +++ b/framework/include/problems/FEProblemBase.h @@ -2588,7 +2588,10 @@ class FEProblemBase : public SubProblem, public Restartable void meshChangedHelper(bool intermediate_change = false); /// Helper to check for duplicate variable names across systems or within a single system - bool duplicateVariableCheck(const std::string & var_name, const FEType & type, bool is_aux); + bool duplicateVariableCheck(const std::string & var_name, + const FEType & type, + bool is_aux, + const std::set * const active_subdomains); void computeUserObjectsInternal(const ExecFlagType & type, const Moose::AuxGroup & group, diff --git a/framework/src/problems/FEProblemBase.C b/framework/src/problems/FEProblemBase.C index 861d59b89b6f..a8f98a4eead0 100644 --- a/framework/src/problems/FEProblemBase.C +++ b/framework/src/problems/FEProblemBase.C @@ -249,6 +249,7 @@ FEProblemBase::validParams() "List of subdomains for material coverage check. The meaning of this list is controlled by " "the parameter 'material_coverage_check' (whether this is the list of subdomains to be " "checked, not to be checked or not taken into account)."); + params.addParam("fv_bcs_integrity_check", true, "Set to false to disable checking of overlapping Dirichlet and Flux BCs " @@ -2519,8 +2520,19 @@ FEProblemBase::getSampler(const std::string & name, const THREAD_ID tid) bool FEProblemBase::duplicateVariableCheck(const std::string & var_name, const FEType & type, - bool is_aux) + bool is_aux, + const std::set * const active_subdomains) { + + std::set subdomainIDs; + if (active_subdomains->size() == 0) + { + const auto subdomains = _mesh.meshSubdomains(); + subdomainIDs.insert(subdomains.begin(), subdomains.end()); + } + else + subdomainIDs.insert(active_subdomains->begin(), active_subdomains->end()); + for (auto & sys : _solver_systems) { SystemBase * curr_sys_ptr = sys.get(); @@ -2530,7 +2542,7 @@ FEProblemBase::duplicateVariableCheck(const std::string & var_name, { curr_sys_ptr = _aux.get(); other_sys_ptr = sys.get(); - error_prefix = "Aux"; + error_prefix = "aux"; } if (other_sys_ptr->hasVariable(var_name)) @@ -2541,11 +2553,74 @@ FEProblemBase::duplicateVariableCheck(const std::string & var_name, { const Variable & var = curr_sys_ptr->system().variable(curr_sys_ptr->system().variable_number(var_name)); + + // variable type if (var.type() != type) - mooseError(error_prefix, - "Variable with name '", + { + const auto stringifyType = [](FEType t) + { return Moose::stringify(t.family) + " of order " + Moose::stringify(t.order); }; + + mooseError("Mismatching types are specified for ", + error_prefix, + "variable with name '", var_name, - "' already exists but is of a differing type!"); + "': '", + stringifyType(var.type()), + "' and '", + stringifyType(type), + "'"); + } + + // block-restriction + if (!(active_subdomains->size() == 0 && var.active_subdomains().size() == 0)) + { + const auto varActiveSubdomains = var.active_subdomains(); + std::set varSubdomainIDs; + if (varActiveSubdomains.size() == 0) + { + const auto subdomains = _mesh.meshSubdomains(); + varSubdomainIDs.insert(subdomains.begin(), subdomains.end()); + } + else + varSubdomainIDs.insert(varActiveSubdomains.begin(), varActiveSubdomains.end()); + + // Is subdomainIDs a subset of varSubdomainIDs? With this we allow the case that the newly + // requested block restriction is only a subset of the existing one. + const auto isSubset = std::includes(varSubdomainIDs.begin(), + varSubdomainIDs.end(), + subdomainIDs.begin(), + subdomainIDs.end()); + + if (!isSubset) + { + // helper function: make a string from a set of subdomain ids + const auto stringifySubdomains = [this](std::set subdomainIDs) + { + std::stringstream s; + for (auto const i : subdomainIDs) + { + // do we need to insert a comma? + if (s.tellp() != 0) + s << ", "; + + // insert subdomain name and id -or- only the id (if no name is given) + const auto subdomainName = _mesh.getSubdomainName(i); + if (subdomainName.empty()) + s << i; + else + s << subdomainName << " (" << i << ")"; + } + return s.str(); + }; + + const std::string msg = "Mismatching block-restrictions are specified for " + + error_prefix + "variable with name '" + var_name + "': {" + + stringifySubdomains(varSubdomainIDs) + "} and {" + + stringifySubdomains(subdomainIDs) + "}"; + + mooseError(msg); + } + } return true; } @@ -2564,7 +2639,12 @@ FEProblemBase::addVariable(const std::string & var_type, auto fe_type = FEType(Utility::string_to_enum(params.get("order")), Utility::string_to_enum(params.get("family"))); - if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ false)) + const auto active_subdomains_vector = + _mesh.getSubdomainIDs(params.get>("block")); + const std::set active_subdomains(active_subdomains_vector.begin(), + active_subdomains_vector.end()); + + if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ false, &active_subdomains)) return; params.set("_fe_problem_base") = this; @@ -2840,7 +2920,12 @@ FEProblemBase::addAuxVariable(const std::string & var_type, auto fe_type = FEType(Utility::string_to_enum(params.get("order")), Utility::string_to_enum(params.get("family"))); - if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ true)) + const auto active_subdomains_vector = + _mesh.getSubdomainIDs(params.get>("block")); + const std::set active_subdomains(active_subdomains_vector.begin(), + active_subdomains_vector.end()); + + if (duplicateVariableCheck(var_name, fe_type, /* is_aux = */ true, &active_subdomains)) return; params.set("_fe_problem_base") = this; @@ -2862,7 +2947,7 @@ FEProblemBase::addAuxVariable(const std::string & var_name, mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead"); - if (duplicateVariableCheck(var_name, type, /* is_aux = */ true)) + if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains)) return; std::string var_type; @@ -2901,7 +2986,7 @@ FEProblemBase::addAuxArrayVariable(const std::string & var_name, mooseDeprecated("Please use the addAuxVariable(var_type, var_name, params) API instead"); - if (duplicateVariableCheck(var_name, type, /* is_aux = */ true)) + if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains)) return; InputParameters params = _factory.getValidParams("ArrayMooseVariable"); @@ -2935,7 +3020,7 @@ FEProblemBase::addAuxScalarVariable(const std::string & var_name, _max_scalar_order = order; FEType type(order, SCALAR); - if (duplicateVariableCheck(var_name, type, /* is_aux = */ true)) + if (duplicateVariableCheck(var_name, type, /* is_aux = */ true, active_subdomains)) return; InputParameters params = _factory.getValidParams("MooseVariableScalar"); diff --git a/modules/contact/examples/2d_indenter/indenter_rz_fine.i b/modules/contact/examples/2d_indenter/indenter_rz_fine.i index 19ab23782df4..9a409bbdf4f3 100644 --- a/modules/contact/examples/2d_indenter/indenter_rz_fine.i +++ b/modules/contact/examples/2d_indenter/indenter_rz_fine.i @@ -55,7 +55,6 @@ [Modules/TensorMechanics/Master] [all] - add_variables = true strain = FINITE block = '1 2' use_automatic_differentiation = false diff --git a/modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-fretting-wear-test-action.i b/modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-fretting-wear-test-action.i index 2340979702d7..4f7c93729d03 100644 --- a/modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-fretting-wear-test-action.i +++ b/modules/contact/test/tests/mortar_aux_kernels/block-dynamics-aux-fretting-wear-test-action.i @@ -42,12 +42,12 @@ offset = -0.045 [Modules/TensorMechanics/DynamicMaster] [all] - add_variables = true hht_alpha = 0.0 newmark_beta = 0.25 newmark_gamma = 0.5 mass_damping_coefficient = 0.0 stiffness_damping_coefficient = 1.0 + accelerations = 'accel_x accel_y' generate_output = 'stress_xx stress_yy' block = '1 2' strain = FINITE @@ -87,6 +87,22 @@ offset = -0.045 [gap_vel] block = 'normal_secondary_subdomain' [] + [vel_x] + order = FIRST + family = LAGRANGE + [] + [vel_y] + order = FIRST + family = LAGRANGE + [] + [accel_x] + order = FIRST + family = LAGRANGE + [] + [accel_y] + order = FIRST + family = LAGRANGE + [] [] [AuxKernels] diff --git a/modules/porous_flow/test/tests/actions/block_restricted.i b/modules/porous_flow/test/tests/actions/block_restricted.i index 1875ec00a1a8..5611b3d13e62 100644 --- a/modules/porous_flow/test/tests/actions/block_restricted.i +++ b/modules/porous_flow/test/tests/actions/block_restricted.i @@ -11,7 +11,6 @@ PorousFlowDictatorName = 'dictator' material_coverage_check = false [] - [Mesh] active_block_names = 'BaseMesh Box1' [BaseMesh] @@ -50,17 +49,33 @@ PorousFlowDictatorName = 'dictator' [Physics] [SolidMechanics] [QuasiStatic] - [./all] + [all] strain = SMALL incremental = true - add_variables = true block = ${Mesh/active_block_names} - generate_output = 'stress_xx stress_yy stress_zz' [] [] [] [] +[AuxVariables] + [stress_xx] + order = CONSTANT + family = MONOMIAL + block = 'BaseMesh' + [] + [stress_yy] + order = CONSTANT + family = MONOMIAL + block = 'BaseMesh' + [] + [stress_zz] + order = CONSTANT + family = MONOMIAL + block = 'BaseMesh' + [] +[] + [PorousFlowFullySaturated] coupling_type = HydroMechanical porepressure = porepressure @@ -74,6 +89,12 @@ PorousFlowDictatorName = 'dictator' [] [Variables] + [disp_x] + [] + [disp_y] + [] + [disp_z] + [] [porepressure] order = SECOND family = LAGRANGE @@ -137,7 +158,7 @@ PorousFlowDictatorName = 'dictator' [] [FluidProperties] - [./simple_fluid] + [simple_fluid] type = SimpleFluidProperties bulk_modulus = 2E3 density0 = 1000 @@ -190,7 +211,7 @@ PorousFlowDictatorName = 'dictator' poissons_ratio = 0.15 [] - [./stress] + [stress] type = ComputeMultipleInelasticStress inelastic_models = '' perform_finite_strain_rotations = false diff --git a/modules/porous_flow/test/tests/actions/gold/block_restricted_out.e b/modules/porous_flow/test/tests/actions/gold/block_restricted_out.e index c97a2b87a27b..cf12239fffcb 100644 Binary files a/modules/porous_flow/test/tests/actions/gold/block_restricted_out.e and b/modules/porous_flow/test/tests/actions/gold/block_restricted_out.e differ diff --git a/modules/solid_mechanics/src/actions/LineElementAction.C b/modules/solid_mechanics/src/actions/LineElementAction.C index 7a7cbcc313ad..e3aa1fb30f70 100644 --- a/modules/solid_mechanics/src/actions/LineElementAction.C +++ b/modules/solid_mechanics/src/actions/LineElementAction.C @@ -477,7 +477,8 @@ LineElementAction::actAddVariables() for (const auto & disp : _displacements) { // Create displacement variables - _problem->addVariable("MooseVariable", disp, params); + if (!_problem->hasVariable(disp)) + _problem->addVariable("MooseVariable", disp, params); } // Add rotation variables if line element is a beam. @@ -486,7 +487,8 @@ LineElementAction::actAddVariables() for (const auto & rot : _rotations) { // Create rotation variables - _problem->addVariable("MooseVariable", rot, params); + if (!_problem->hasVariable(rot)) + _problem->addVariable("MooseVariable", rot, params); } } } diff --git a/modules/solid_mechanics/test/tests/gravity/block-gravity-kinetic-energy.i b/modules/solid_mechanics/test/tests/gravity/block-gravity-kinetic-energy.i index 1b7ad73672e8..8622101192d3 100644 --- a/modules/solid_mechanics/test/tests/gravity/block-gravity-kinetic-energy.i +++ b/modules/solid_mechanics/test/tests/gravity/block-gravity-kinetic-energy.i @@ -24,6 +24,22 @@ offset = 1.0 [] [AuxVariables] + [vel_x] + order = FIRST + family = LAGRANGE + [] + [vel_y] + order = FIRST + family = LAGRANGE + [] + [accel_x] + order = FIRST + family = LAGRANGE + [] + [accel_y] + order = FIRST + family = LAGRANGE + [] [pid] order = CONSTANT family = MONOMIAL @@ -62,13 +78,13 @@ offset = 1.0 [Physics/SolidMechanics/Dynamic] [all] - add_variables = true hht_alpha = 0.0 beta = 0.25 gamma = 0.5 mass_damping_coefficient = 0.0 stiffness_damping_coefficient = 0.0 displacements = 'disp_x disp_y' + accelerations = 'accel_x accel_y' generate_output = 'stress_xx stress_yy' block = '1 2' strain = FINITE @@ -129,10 +145,8 @@ offset = 1.0 dt = 0.01 dtmin = .05 solve_type = 'PJFNK' - petsc_options = '-snes_converged_reason -ksp_converged_reason -pc_svd_monitor ' - '-snes_linesearch_monitor' - petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -mat_mffd_err ' - '-ksp_gmres_restart' + petsc_options = '-snes_converged_reason -ksp_converged_reason -pc_svd_monitor -snes_linesearch_monitor' + petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -mat_mffd_err -ksp_gmres_restart' petsc_options_value = 'lu NONZERO 1e-15 1e-5 100' l_max_its = 100 nl_max_its = 20 diff --git a/test/tests/misc/check_error/add_aux_variable_multiple_subdomain_test.i b/test/tests/misc/check_error/add_aux_variable_multiple_subdomain_test.i new file mode 100644 index 000000000000..1b90460d69ad --- /dev/null +++ b/test/tests/misc/check_error/add_aux_variable_multiple_subdomain_test.i @@ -0,0 +1,81 @@ +[Problem] + type = FEProblem +[] + +[Mesh] + [BaseMesh] + type = GeneratedMeshGenerator + dim = 2 + nx = 2 + ny = 2 + xmin = -2 + xmax = +2 + ymin = -1 + ymax = +1 + [] + [Box1] + type = SubdomainBoundingBoxGenerator + input = "BaseMesh" + block_id = 2 + location = "INSIDE" + bottom_left = "-2 -1 0" + top_right = "0 0 0" + [] +[] + +[Variables] + [u] + order = FIRST + family = LAGRANGE + [] +[] + +[AuxVariables] + [q] + family = MONOMIAL + order = third + block = 2 + [] +[] + +[Kernels] + [diff] + type = Diffusion + variable = u + [] +[] + +[BCs] + [left] + type = DirichletBC + variable = u + boundary = 3 + value = 0 + [] + [right] + type = DirichletBC + variable = u + boundary = 1 + value = 1 + [] +[] + +[Executioner] + type = Steady + + solve_type = 'PJFNK' +[] + +[Outputs] + file_base = out +[] + +# Request AuxVariable "q" again. This time without block restriction. +# This would widen the scope of "q" by means of block-restriction. This is not allowed. +# Note: If this block were above [AuxVariables/q], no error would occour. +[MoreAuxVariables] + [q] + family = MONOMIAL + order = third + [] +[] diff --git a/test/tests/misc/check_error/tests b/test/tests/misc/check_error/tests index d17faca7be7c..7d356a1b1070 100644 --- a/test/tests/misc/check_error/tests +++ b/test/tests/misc/check_error/tests @@ -34,7 +34,7 @@ [add_aux_variable_multiple_test] type = 'RunException' input = 'add_aux_variable_multiple_test.i' - expect_err = "AuxVariable with name 'q' already exists but is of a differing type!" + expect_err = "Mismatching types are specified for auxvariable with name 'q': 'MONOMIAL of order 3' and 'MONOMIAL of order 0'" requirement = 'The system shall report an error when multiple AuxVariables are added to the system with conflicting types.' issues = '#1222' @@ -44,12 +44,21 @@ type = 'RunException' input = 'add_aux_variable_multiple_test.i' cli_args = 'Variables/q/family=SCALAR MoreAuxVariables/q/family=SCALAR' - expect_err = "AuxVariable with name 'q' already exists but is of a differing type!" + expect_err = "Mismatching types are specified for auxvariable with name 'q': 'MONOMIAL of order 3' and 'SCALAR of order 0'" requirement = 'The system shall report an error when multiple Scalar AuxVariables are added to the system with conflicting types.' issues = '#9313' [] + [add_aux_variable_multiple_subdomain_test] + type = 'RunException' + input = 'add_aux_variable_multiple_subdomain_test.i' + expect_err = "Mismatching block-restrictions are specified for auxvariable with name 'q': \{2\} and \{0, 2\}" + + requirement = 'The system shall report an error when multiple AuxVariables are added to the system with conflicting block-restriction.' + issues = '#28568' + [] + [bad_bc_test] type = 'RunException' input = 'bad_bc_test.i'