Open jmeier opened 3 months ago
I doubt that anyone has attempted this before, so I'm not very surprised that you've run into an issue. Based on your investigation, I believe the answer to
Is it possible to move 2D elements to an inactive domain, if the mesh consists also of 3D elements?
is no
Thanks for your answer! In the corresponding discussion #28201, Guillaume motivated to create this issue and wrote:
We'll have to change the code a little bit because we should allow this.
I really hope that this can be solved with little effort.
It seems that the error I am experiencing is not primarily related to assigning shell elements to an inactive subdomain. I am therefore closing this issue as resolved. Below I have attached a test model which shows the moving of volume and shell elements with a TimedSubdomainModifier without generating an error.
If you want me to submit this test as a regression test for the TimedSubdomainModifier, please let me know.
``` [GlobalParams] displacements = 'disp_x disp_y disp_z' use_displaced_mesh = false [] Box1_inactive_name = 'Box1_inactive' Box1Hull_LowerDElements_inactive_name = 'Box1Hull_LowerDElements_inactive' inactive_domain_block_names = '${Box1_inactive_name} ${Box1Hull_LowerDElements_inactive_name}' [Problem] solve = true kernel_coverage_check = SKIP_LIST kernel_coverage_block_list = '${inactive_domain_block_names}' material_coverage_check = SKIP_LIST material_coverage_block_list = '${inactive_domain_block_names}' [] [Mesh] [BaseMesh] type = GeneratedMeshGenerator subdomain_name = 'BaseMesh' elem_type = 'HEX8' dim = 3 nx = 6 ny = 6 nz = 2 xmin = -3 xmax = +3 ymin = -3 ymax = +3 zmin = -2 zmax = +2 [] [Box1] type = SubdomainBoundingBoxGenerator block_name = 'Box1' input = "BaseMesh" block_id = 1 location = "INSIDE" bottom_left = "-1.0 -1.0 -0" top_right = "+1.0 +1.0 +2" [] [Box1Hull_Sideset] type = SideSetsAroundSubdomainGenerator input = 'Box1' block = 'Box1' include_only_external_sides = true new_boundary = 'Box1Hull_Sideset' [] [Box1Hull_LowerDElements] type = LowerDBlockFromSidesetGenerator input = 'Box1Hull_Sideset' sidesets = 'Box1Hull_Sideset' new_block_name = 'Box1Hull_LowerDElements' [] add_subdomain_names = ${inactive_domain_block_names} [] [Physics] [SolidMechanics] [QuasiStatic] [all] strain = SMALL incremental = true add_variables = true generate_output = 'stress_xx stress_yy stress_zz' block = 'BaseMesh Box1' [] [] [] [] # ===== Kernels for Shell-Elements [Kernels] [shell_disp_x] type = ADStressDivergenceShell block = 'Box1Hull_LowerDElements' component = 0 variable = disp_x through_thickness_order = SECOND [] [shell_disp_y] type = ADStressDivergenceShell block = 'Box1Hull_LowerDElements' component = 1 variable = disp_y through_thickness_order = SECOND [] [shell_disp_z] type = ADStressDivergenceShell block = 'Box1Hull_LowerDElements' component = 2 variable = disp_z through_thickness_order = SECOND [] [shell_rot_x] type = ADStressDivergenceShell block = 'Box1Hull_LowerDElements' component = 3 variable = rot_x through_thickness_order = SECOND [] [shell_rot_y] type = ADStressDivergenceShell block = 'Box1Hull_LowerDElements' component = 4 variable = rot_y through_thickness_order = SECOND [] [] # ===== Dummy-Kernels for Inactive Domain ===== [Kernels] [./donothing1] type = MatDiffusion block = '${inactive_domain_block_names}' variable = disp_z diffusivity = 1e-7 [] [./donothing2] type = MatDiffusion block = '${inactive_domain_block_names}' variable = disp_x diffusivity = 1e-7 [] [./donothing3] type = MatDiffusion block = '${inactive_domain_block_names}' variable = disp_y diffusivity = 1e-7 [] [] [Variables] [./rot_x] order = FIRST family = LAGRANGE block = 'Box1Hull_LowerDElements' [] [./rot_y] order = FIRST family = LAGRANGE block = 'Box1Hull_LowerDElements' [] [] [AuxVariables] [dummy] type = MooseVariableFVReal [] [] # fix the lower model boundary in y and z direction [BCs] [./back_fix_y] type = DirichletBC variable = disp_y boundary = 'back' value = 0.0 [] [./back_fix_z] type = DirichletBC variable = disp_z boundary = 'back' value = 0.0 [] [] # fix the left mdoel boundary in x direction [BCs] [./left_fix_x] type = DirichletBC variable = disp_x boundary = 'left' value = 0.0 [] [] # put some pressure on the right model boundary [BCs] [./right_Dirichlet] type = FunctionDirichletBC variable = disp_x boundary = 'right' function = right_pressure_function [] [] [Functions] [right_pressure_function] type = ParsedFunction expression = '-0.001 * t' [] [] # Material: Volume Elements [Materials] [elasticity_tensor] type = ComputeIsotropicElasticityTensor block = 'BaseMesh Box1' youngs_modulus = 1e6 poissons_ratio = 0.25 [] [stress] type = ComputeFiniteStrainElasticStress block = 'BaseMesh Box1' [] [] # Material: Shell Elements [Materials] [shell_elasticity] type = ADComputeIsotropicElasticityTensorShell block = 'Box1Hull_LowerDElements' youngs_modulus = 1e9 poissons_ratio = 0.3 through_thickness_order = SECOND [] [shell_strain] type = ADComputeIncrementalShellStrain block = 'Box1Hull_LowerDElements' displacements = 'disp_x disp_y disp_z' rotations = 'rot_x rot_y' thickness = 1.0 through_thickness_order = SECOND [] [shell_stress] type = ADComputeShellStress block = 'Box1Hull_LowerDElements' through_thickness_order = SECOND [] [] # move elements between subdomains back and forth [UserObjects] [GlobalSubdomainModifier] type = TimedSubdomainModifier times = '0.2 0.4' blocks_from = 'Box1 Box1Hull_LowerDElements' blocks_to = 'Box1_inactive Box1Hull_LowerDElements_inactive' execute_on = 'INITIAL TIMESTEP_BEGIN' [] [] [Preconditioning] [.\SMP] type = SMP full = true [] [] [Executioner] type = Transient end_time = 1.0 dtmin = 0.001 [TimeSteppers] [BlockEventTimeStepper] type = TimeSequenceStepper time_sequence = '0.05 0.1 0.2 0.4 1.0' [] [] solve_type = 'PJFNK' petsc_options = '-snes_converged_reason' petsc_options_iname = '-pc_type -pc_factor_mat_solver_package' petsc_options_value = ' lu mumps' l_tol = 1E-10 l_max_its = 20 nl_abs_tol = 1E-10 nl_rel_tol = 1e-8 nl_max_its = 20 [] [Outputs] exodus = true [] ```
Sorry, I have to re-open the issue. My last comment is now outdated as the code I give there is using [Physics/SolidMechanics/QuasiStatic].add_variables = true
and in its current state this does not apply the block-restriction correctly (already addressed in #28307). Therefore, the disp-variables have been not block restricted and did not trigger the error.
As a first step: I would like to understand what the motivation behind this check is. Why is it checked whether variables are defined on both lower dimensional blocks and higher dimensional blocks if they are block-restricted?
A good counterexample are the disp variables, which should (often must?) be defined for all possible blocks. For which variables must this not be the case?
@GiudGiud, please allow me to tag you here as we had the initial discussion in #28201 and you also suggested to change this behaviour.
Edit: This seems to be commit this check had been introduced: https://github.com/idaholab/moose/commit/8d8d065125b4cafd53cc13f7b3261b36dd937003
@lindsayad
I dont know why we ban variables to be both lower-D and higher-D
Thanks to the marvelous explanaition of @roystgnr over there in libmesh it looks the error message might a bit misleading. Citing from https://github.com/libMesh/libmesh/discussions/3937:
But let me try to help anyway: looking into
MooseMesh::cacheInfo()
, where the data structure is being set, it looks likeisLowerD()
isn't returning what the name says ("is this lower-dimensional than the rest of the mesh"), it's trying to return what the Doxygen comment says ("do elements in this subdomain haveinterior_parent()
values assigned"). By that definition, it can absolutely be correct for some blocks of beams to return true (because they're boundary elements of 2D or 3D elements) while others return false (because they're free-standing beams).
If I understand correctly, the check restricts having one and the same variable in blocks with interior_parent()
values and without interior_parent()
values assigned.
Depending on where this discussion goes, we should at least adapt the error message.
Please allow me to come back to this issue: Would it be an option to propose an PR changing the mooseError
to mooseWarning
till the underlying issue is solved?
Works for me. We should check in an example where it works, and try to identify the situations where it does not (block restriction to a block and to a lowerD block touching this block?) @lindsayad added this error in 12d2312462c I think
Yea I mean how would you evaluate the value of a monomial variable on a higher D face coincident with a lower-d element? There are two different sets of degrees of freedom to choose from
we could have a new integrity check that makes sure this particular case does not happen? @jmeier are you avoiding this case in your case?
Yea I mean how would you evaluate the value of a monomial variable on a higher D face coincident with a lower-d element? There are two different sets of degrees of freedom to choose from
I agree that we cannot mix lower-d-elements and higher-d-elements. So the error message is correct. But if I understand the explanation here correctly, Moose does not check if lower-d-elements are mixed with higher-d-elements. If I understand the explanation correctly, the function name _mesh.isLowerD()
is a bit misleading - the function does not return if a subdomain is "lower-d" but "if elements in this subdomain have interior_parent() values assigned".
Please consider the susanne mesh shown below. Some of the "lineSignPole" beams are not connected to higher-d subdomains, others are. I'll get the error for them.
we could have a new integrity check that makes sure this particular case does not happen?
Yes we should. But I do not know how to detect compatible subdomains.
@jmeier are you avoiding this case in your case?
Yes, by only moving one type of elements into another empty subdomain.
I think we should change the implementation of isLowerD so that it matches the name better
Discussed in https://github.com/idaholab/moose/discussions/28201