Step 3a - Thermal expansion
In this sidebar we'll introduce a thermal expansion eigenstrain. To demonstrate the effect we reshape the domain from step 3 and make it narrow like a cantilever.
#
# Added subdomains and subdomain-specific properties
# https://mooseframework.inl.gov/modules/solid_mechanics/tutorials/introduction/step03.html
#
[GlobalParams]
displacements = 'disp_x disp_y'
[]
[Mesh]
[generated]
type = GeneratedMeshGenerator
dim = 2
nx = 10
ny = 20
xmin = -0.25
xmax = 0.25
ymax = 5
[]
[block1]
type = SubdomainBoundingBoxGenerator
input = generated
block_id = 1
bottom_left = '-0.25 0 0'
top_right = '0 5 0'
[]
[block2]
type = SubdomainBoundingBoxGenerator
input = block1
block_id = 2
bottom_left = '0 0 0'
top_right = '0.25 5 0'
[]
# select a single node in the center of the bottom boundary
[pin]
type = ExtraNodesetGenerator
input = block2
new_boundary = pin
coord = '0 0 0'
[]
[]
[AuxVariables]
[T]
[]
[]
[AuxKernels]
[temperature_ramp]
type = FunctionAux
execute_on = TIMESTEP_BEGIN
variable = T
function = 300+5*t
[]
[]
[Physics/SolidMechanics/QuasiStatic]
[all]
add_variables = true
automatic_eigenstrain_names = true
generate_output = 'vonmises_stress'
[]
[]
[BCs]
[pin_x]
type = DirichletBC
variable = disp_x
boundary = pin
value = 0
[]
[bottom_y]
type = DirichletBC
variable = disp_y
boundary = bottom
value = 0
[]
[]
[Materials]
[elasticity]
type = ComputeIsotropicElasticityTensor
youngs_modulus = 1e9
poissons_ratio = 0.3
[]
[expansion1]
type = ComputeThermalExpansionEigenstrain
temperature = T
thermal_expansion_coeff = 0.001
stress_free_temperature = 300
eigenstrain_name = thermal_expansion
block = 1
[]
[expansion2]
type = ComputeThermalExpansionEigenstrain
temperature = T
thermal_expansion_coeff = 0.002
stress_free_temperature = 300
eigenstrain_name = thermal_expansion
block = 2
[]
[stress]
type = ComputeLinearElasticStress
[]
[]
[Executioner]
type = Transient
solve_type = NEWTON
petsc_options_iname = '-pc_type'
petsc_options_value = 'lu'
end_time = 5
dt = 1
[]
[Outputs]
exodus = true
[]
(moose/modules/solid_mechanics/tutorials/introduction/mech_step03a.i)Input file
Mesh
Note the xmin and xmax upper and lower x-dimension extents are supplied here. The origin will lie in the center of the bottom boundary of this generated mesh.
New is the ExtraNodesetGenerator
which we append to the existing chain of mesh generators. This generator allows us to create a new nodeset containing all nodes located at the coordinates the user specified in "coord". Here we create a nodeset containing the single node at the origin. You need to make sure that a node actually exists at each specified coordinate! We call this nodeset pin
for obvious reasons and will use it below in the BCs.
AuxVariables
We introduce a new auxiliary variable T
(for temperature). Auxiliary variables are variables we're not solving for, but are computing directly. To simplify this step we are not solving a heat conduction problem, but instead just prescribing a global temperature that is rising with time (see next section). Auxiliary variables can be coupled in everywhere regular (so called nonlinear) variables are coupled. They are a great tool for simplifying a model during development.
AuxKernels
The FunctionAux
AuxKernel can set an AuxVariable to a function of space and time. Note the "execute_on" parameter that is available in many MOOSE systems. Here we skip execution during LINEAR and NON_LINEAR iterations and only update the variable value at the beginning of the timestep.
SolidMechanics QuasiStatic Physics
We've added the "automatic_eigenstrain_names" parameter to the quasi-static physics. With this option enabled the quasi-static physics will try to automatically detect all material objects that provide eigenstrain properties. This works well for most scenarios. Note that MOOSE will print a list of detected eigenstrain names very early in its console output. Look for
*** Automatic Eigenstrain Names ***
all: thermal_expansion
when you run this example. Here all
is the quasi-static physics block name and thermal_expansion
is the "eigenstrain_name" parameter value for the two eigenstrain materials below. The action correctly detected it and verified that eigenstrains are provided on all subdomains covered by the quasi-static physics block. To manually supply the eigenstrain material properties use the "eigenstrain_names" parameter. Like so
[Physics/SolidMechanics/QuasiStatic]
[all]
add_variables = true
eigenstrain_names = 'thermal_expansion'
generate_output = 'vonmises_stress'
[]
[]
BCs
We have changed the way we apply the boundary condition on the x displacement variable disp_x
to only constrain this variable at the pin
"boundary". Above we defined this boundary as the nodeset containing the single node at (0,0,0).
Pinning at a single point is less restrictive and allows the model to expand in x-direction along the bottom boundary (which will happen due to isotropic thermal expansion). Yet we still remove all rigid body modes
Translation, because we fix both x and y displacement on at least one node
Rotation, because we fix y displacement on another node (actually on all nodes along the bottom boundary)
Pinning nodes to remove rigid body modes is an important tool to create mechanics simulations that converge. The presence of rigid body modes will lead to non-convergence. BCs on single nodes rather than whole boundaries can help avoid overconstraining your problems. Keep in mind that to remove all 6 rigid body modes in a 3D simulation you need to apply BCs on at least 3 nodes (which cannot be co-linear). One node will have to be constrained in 3 direction, one in 2 and one in just one direction. The first node will remove three translation modes. The second node will remove two rotational modes (and will establish an axis of rotation). The third node will remove that final rotational mode.
Materials
An "Eigenstrain" in MOOSE is a stress free strain. It is an intrinsic shape change of a volume element due to effects like thermal expansion, swelling, diffusion of over/undersized solutes, etc.
We use two ComputeThermalExpansionEigenstrain
objects to compute an eigenstrain tensor in each of the two subdomains. The "stress_free_temperature" is set to 300K, which is the initial temperature set for the T
AuxVariable. At this temperature we assume the eigenstrain to be zero (with contraction at temperatures lower than 300K and expansion above). The "thermal_expansion_coeff" is chosen differently on the two subdomains. This effectively models a bimetallic strip.
Questions
Expected outcome
Think about what you expect to happen when you run the input.
Overconstraining
Apply the
disp_x
boundary condition to the entire bottom surface again and observe what happens. Undo that change before you move on to the next question.
Constraining even less
In the original input we're fixing the y displacement to 0 in the entire bottom boundary. Try to relax this constraint a bit try to add a second single node boundary using the
ExtraNodesetGenerator
(chained in after thepin
generator). Use one of the two bottom corner nodes. Now think about where you have to apply thedisp_y != 0
boundary condition.
Once you've answered the questions and run this example we will move on to Step 4 and setup a cantilever problem that prepares us for contact.