July 2025
www.inl.gov
INL is the one of the largest employers in Idaho with 6,200 employees and 478 interns
In 2024 the INL budget was over $2 billion
INL is the site where 52 nuclear reactors were designed and constructed, including the first reactor to generate usable amounts of electricity: Experimental Breeder Reactor I (EBR-1)
World's most powerful test reactor (250 MW thermal)
Constructed in 1967
Volume of 1.4 cubic meters, with 43 kg of uranium, and operates at 60C
TREAT is a test facility specifically designed to evaluate the response of fuels and materials to accident conditions
High-intensity (20 GW), short-duration (80 ms) neutron pulses for severe accident testing
NRIC is composed of two physical test beds to build prototypes of advanced nuclear reactors
DOME (Demonstration of Microreactor Experiments) in the historic EBR-II facility, a test bed site capable of hosting operational nuclear reactor concepts that produce less than 20MW thermal power.
LOTUS (Laboratory for Operation and Testing in the U.S.) in the historic Zero Power Physics Reactor (ZPPR) Cell, a test bed site capable of hosting operational nuclear reactor concepts that produce less than 500kW thermal power.
And an open-source online virtual test bed to demonstrate advanced reactors through modeling and simulation. More information about NRIC can be found at https://nric.inl.gov.
Multi-physics Object Oriented Simulation Environment
Development started in 2008
Open-sourced in 2014
Designed to solve computational engineering problems and reduce the expense and time required to develop new applications by:
being easily extended and maintained
working efficiently on a few and many processors
providing an object-oriented, extensible system for creating all aspects of a simulation tool
250 contributors
56,000 commits
5000 unique visitors per month
~40 new Discussion participants per week
1500 citations for the MOOSE papers
Most cited paper in Elsevier Software-X
More than 500 publications using MOOSE
30M tests per week
Continuous and Discontinuous Galerkin FEM
Finite Volume
Supports fully coupled or segregated systems, fully implicit and explicit time integration
Automatic differentiation (AD)
Unstructured mesh with FEM shapes
Higher order geometry
Mesh adaptivity (refinement and coarsening)
Massively parallel (MPI and threads)
User code agnostic of dimension, parallelism, shape functions, etc.
Operating Systems:
macOS
Linux
Windows (WSL)
MOOSE follows an Nuclear Quality Assurance Level 1 (NQA-1) development process
All commits undergo review using GitHub Pull Requests and must pass a set of application regression tests before they are available to our users
MOOSE includes a test suite and documentation system to allow for agile development while maintaining a NQA-1 process
Utilizes the Continuous Integration Environment for Verification, Enhancement, and Testing (CIVET)
External contributions are guided through the process by the team, and are very welcome!
LGPL 2.1
Does not limit what you can do with your application
Can license/sell your application as closed source
Modifications to the library itself (or the modules) are open source
New contributions are automatically LGPL 2.1
Multiphysics is popular, but how is it achieved?
Scientists are adept at creating applications in their domain
What about collaborating across research groups and/or disciplines?
Iterating between design teams?
Development of "coupling" codes?
Is there something better?
Data should be accessed through strict interfaces with code having separation of responsibilities
Allows for "decoupling" of code
Leads to more reuse and less bugs
Challenging for FEM: Shape functions, DOFs, Elements, QPs, Material Properties, Analytic Functions, Global Integrals, Transferred Data and much more are needed in FEM assembly
The complexity makes computational science codes brittle and hard to reuse
A consistent set of "systems" are needed to carry out common actions, these systems should be separated by interfaces
Systems break apart responsibility
No direct communication between systems
Everything flows through MOOSE interfaces
Objects can be mixed and matched to achieve simulation goals
Incoming data can be changed dynamically
Outputs can be manipulated (e.g. multiplication by radius for cylindrical coordinates)
An object, by itself, can be lifted from one application and used by another
Actions
AuxKernels
Base
BCs
Constraints
Controls
Dampers
DGKernels
DiracKernels
Distributions
Executioners
Functions
Geomsearch
ICs
Indicators
InterfaceKernels
Kernels
LineSearches
Markers
Materials
Mesh
MeshGenerators
MeshModifiers
Multiapps
NodalKernels
Outputs
Parser
Partitioner
Positions
Postprocessors
Preconditioners
Predictors
Problems
Reporters
RelationshipManagers
Samplers
Splits
TimeIntegrators
TimeSteppers
Transfers
UserObject
Utils
Variables
VectorPostprocessors
Physics
Chemical Reactions
Contact
Electromagnetics
Fluid Structure Interaction (FSI)
Geochemistry
Heat Transfer
Level Set
Navier Stokes
Peridynamics
Phase Field
Porous Flow
Solid Mechanics
Thermal Hydraulics
Numerics
External PETSc Solver
Function Expansion Tools
Optimization
Ray Tracing
rDG
Stochastic Tools
XFEM
Physics support
Fluid Properties
Solid Properties
Reactor
Many are open-source on GitHub. Some are accessible through the NCRC
Required for upcoming hands-on
Installing a text editor with input file syntax auto-complete
We will study the cooling of the concrete shielding around a future micro-reactor in the DOME Test Bed at the National Reactor Innovation Center in Idaho.
Exterior (left), Interior (right)
This example was created independently from studies at NRIC and INL. The dimensions have been modified and numerous systems and complexities are omitted.
Cooling system schematic (from NRIC overview Nov. 21)
Simplified geometry:
6.5m x 9.7m x 5.25m concrete box with 4m x 7.6m x 3.6m room
Concrete Domain: Thermal Mechanics
Heat conduction of the thermal radiation from the reactor to the boundary of shield.
Mechanical displacement and stress from the thermal expansion.
Water Domain: Thermal Fluids
Heat transfer through the fluid and back-and-forth from the concrete.
Natural convection of the fluid due to the temperature gradients.
Property | Units | Magnetite Concrete | Ordinary Concrete | Aluminum | Water |
---|---|---|---|---|---|
Thermal conductivity, | W/(mK) | 5.0 | 2.25 | 175 | 0.6 |
Density, | kg/m | 3,524 | 2,403 | 2,270 | 955.7 |
Heat capacity, | J/(kgK) | 1,050 | 1,050 | 875 | 4,181 |
Viscosity, | mPas | — | — | — | 0.798 |
Water heat transfer coefficient | W/m K | 600 | 600 | 600 | — |
Air heat transfer coefficient | W/m K | 10 | — | — | — |
Young's modulus | GPa | 2.75 | 30 | 68 | — |
Poisson's ratio | — | 0.15 | 0.2 | 0.36 | |
Thermal expansion coefficient | 10/K | 1.0 | 1.0 | 2.4 | — |
Step 1: Geometry and Diffusion
Step 2: Simple Heat Conduction Kernel
Step 3: Boundary conditions
Step 4: Heat Conduction kernel with Material
Step 5: Auxiliary Variables
Step 6: Transient Heat Conduction
Step 7: Mechanics
Step 8: Mesh Adaptivity
Step 9: Postprocessors
Step 10: Finite Volume
Step 11: Multiscale Simulation
Step 12: Custom Syntax
Step 13: Restart, recover and initialization hands-on
The first step is to solve a simple "Diffusion" problem. This step will introduce the basic system of MOOSE.
In order to implement the heat conduction equation, a Kernel
object is needed to represent:
We represent the boundary conditions using BC
objects. For example, Dirichlet boundary conditions:
Neumann boundary conditions:
or convective boundary conditions:
Instead of passing constant parameters to the heat conduction Kernel
object, the Material system can be used to supply the values. This allows for properties that vary in space and time as well as be coupled to variables in the simulation.
The heat flux can be compute from the temperature as:
This velocity can be computed using the Auxiliary system.
Solve the transient heat equation using the "heat transfer" module.
Thermal expansion of the concrete can be added to the coupled set of equations using the "solid mechanics" module.
In the transient simulation, a "traveling wave" profile moves through the concrete as it heats up. Adaptivity lets us resolve the temperature gradient at lower computational cost.
Postprocessor
and VectorPostprocessor
objects can be used to compute aggregate value(s) for a simulation, such as the average temperature on the boundary or the temperatures along a line within the solution domain.
Solve the pressure, velocity and temperature in a coupled system of equations by solving for heat transfer in the fluid region
Conservation of Mass (incompressible):
Conservation of momentum:
Conservation of Energy:
MOOSE is capable of running multiple applications together and transfer data between the various applications.
We introduce distributed thermal calculations for neutron detectors, placing the detectors in various locations in the concrete.
MOOSE includes a system to create custom input syntax for common tasks, in this step the syntax for the sets of equations are simplified for end-users.
Learn how to recover a MOOSE simulation that ended prematurely.
MOOSE uses WASP, developed at Oak Ridge National Laboratory, to process input files. Input files use a hierarchical syntax, with square brackets [something]
to delineate levels.
# These are comments
[Variables] # system name
[u] # object name, opening sub-block
family = LAGRANGE # a parameter for this object
order = FIRST # another parameter for this object
[] # closing object sub-block
[] # closing system block
More info on input syntax on this page.
Comments are preceded by #
. They are ignored by the input file parsing. They can be written on their own line:
# Let's define some variables!
[Variables]
...
or after valid syntax:
[Variables] # Let's define some variables!
...
A system for defining a finite element / volume mesh.
For complicated geometries, we often use CUBIT from Sandia National Laboratories cubit.sandia.gov.
Other mesh generators can work as long as they output a file format that libMesh reads.
Meshes in MOOSE are built or loaded using MeshGenerators.
To only generate the mesh without running the simulation, you can pass --mesh-only
on the command line.
FileMeshGenerator
is the MeshGenerator to load external meshes:
[Mesh]
[fmg]
type = FileMeshGenerator
file = square.e
[]
[]
(test/tests/meshgenerators/file_mesh_generator/file_mesh_generator.i)MOOSE supports reading and writing a large number of formats and could be extended to read more.
Extension | Description |
---|---|
.dat | Tecplot ASCII file |
.e, .exd | Sandia's ExodusII format |
.fro | ACDL's surface triangulation file |
.gmv | LANL's GMV (General Mesh Viewer) format |
.mat | Matlab triangular ASCII file (read only) |
.msh | GMSH ASCII file |
.n, .nem | Sandia's Nemesis format |
.plt | Tecplot binary file (write only) |
.node, .ele; .poly | TetGen ASCII file (read; write) |
.inp | Abaqus .inp format (read only) |
.ucd | AVS's ASCII UCD format |
.unv | I-deas Universal format |
.xda, .xdr | libMesh formats |
.vtk, .pvtu | Visualization Toolkit |
Built-in mesh generation is implemented for lines, rectangles, rectangular prisms or extruded reactor geometries.
[Mesh]
[generated]
type = GeneratedMeshGenerator
dim = 2
xmin = 0
xmax = 1
nx = 2
ymin = -2
ymax = 3
ny = 3
elem_type = 'TRI3'
[]
[]
(test/tests/mesh/face_info/face_info_tri.i)The sides are named in a logical way and are numbered:
1D: left = 0, right = 1
2D: bottom = 0, right = 1, top = 2, left = 3
3D: back = 0, bottom = 1, right = 2, top = 3, left = 4, front = 5
The capability is very convenient for parametric mesh optimization!
Human-readable names can be assigned to blocks, sidesets, and nodesets that can be used throughout an input file.
A parameter that requires an ID will accept either numbers or "names".
Names can be assigned to IDs for existing meshes to ease input file maintenance.
[Mesh]
file = three_block.e
# These names will be applied on the fly to the
# mesh so that they can be used in the input file
# In addition they will show up in the output file
block_id = '1 2 3'
block_name = 'wood steel copper'
boundary_id = '1 2'
boundary_name = 'left right'
[]
[BCs]
active = 'left right'
[left]
type = DirichletBC
variable = u
boundary = 'left'
value = 0
[]
[right]
type = DirichletBC
variable = u
boundary = 'right'
value = 1
[]
[]
[Materials]
active = empty
[empty]
type = MTMaterial
block = 'wood steel copper'
[]
[]
(test/tests/mesh/named_entities/name_on_the_fly.i)Meshes can be generated in MOOSE using mesh generators.
2D slice of the shield domain using GeneratedMeshGenerator:
[Mesh]
[bulk]
type = GeneratedMeshGenerator
dim = 2
xmax = 6.5
ymax = 9.7
nx = 7
ny = 10
[]
[]
(tutorials/shield_multiphysics/inputs/step01_diffusion/mesh_part1.i)An executable is available from loading the MOOSE conda or HPC module.
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step01_diffusion
moose-opt -i mesh_part1.i --mesh-only
Console output in mesh-only
mode shows a summary of the mesh.
Mesh Information:
elem_dimensions()={2}
elem_default_orders()={FIRST}
supported_nodal_order()=1
spatial_dimension()=2
n_nodes()=88
n_local_nodes()=88
n_elem()=70
n_local_elem()=70
n_active_elem()=70
n_subdomains()=1
n_elemsets()=0
n_partitions()=1
n_processors()=1
n_threads()=1
processor_id()=0
is_prepared()=true
is_replicated()=true
Mesh Bounding Box:
Minimum: (x,y,z)=( 0, 0, 0)
Maximum: (x,y,z)=( 6.5, 9.7, 0)
Delta: (x,y,z)=( 6.5, 9.7, 0)
Mesh Element Type(s):
QUAD4
Mesh Nodesets:
Nodeset 0 (bottom), 8 nodes
Bounding box minimum: (x,y,z)=( 0, 0, 0)
Bounding box maximum: (x,y,z)=( 6.5, 0, 0)
Bounding box delta: (x,y,z)=( 6.5, 0, 0)
Nodeset 1 (right), 11 nodes
Bounding box minimum: (x,y,z)=( 6.5, 0, 0)
Bounding box maximum: (x,y,z)=( 6.5, 9.7, 0)
Bounding box delta: (x,y,z)=( 0, 9.7, 0)
Nodeset 2 (top), 8 nodes
Bounding box minimum: (x,y,z)=( 0, 9.7, 0)
Bounding box maximum: (x,y,z)=( 6.5, 9.7, 0)
Bounding box delta: (x,y,z)=( 6.5, 0, 0)
Nodeset 3 (left), 11 nodes
Bounding box minimum: (x,y,z)=( 0, 0, 0)
Bounding box maximum: (x,y,z)=( 0, 9.7, 0)
Bounding box delta: (x,y,z)=( 0, 9.7, 0)
Mesh Sidesets:
Sideset 0 (bottom), 7 sides (EDGE2), 7 elems (QUAD4), 8 nodes
Side volume: 6.5
Bounding box minimum: (x,y,z)=( 0, 0, 0)
Bounding box maximum: (x,y,z)=( 6.5, 0, 0)
Bounding box delta: (x,y,z)=( 6.5, 0, 0)
Sideset 1 (right), 10 sides (EDGE2), 10 elems (QUAD4), 11 nodes
Side volume: 9.7
Bounding box minimum: (x,y,z)=( 6.5, 0, 0)
Bounding box maximum: (x,y,z)=( 6.5, 9.7, 0)
Bounding box delta: (x,y,z)=( 0, 9.7, 0)
Sideset 2 (top), 7 sides (EDGE2), 7 elems (QUAD4), 8 nodes
Side volume: 6.5
Bounding box minimum: (x,y,z)=( 0, 9.7, 0)
Bounding box maximum: (x,y,z)=( 6.5, 9.7, 0)
Bounding box delta: (x,y,z)=( 6.5, 0, 0)
Sideset 3 (left), 10 sides (EDGE2), 10 elems (QUAD4), 11 nodes
Side volume: 9.7
Bounding box minimum: (x,y,z)=( 0, 0, 0)
Bounding box maximum: (x,y,z)=( 0, 9.7, 0)
Bounding box delta: (x,y,z)=( 0, 9.7, 0)
Mesh Edgesets:
None
Mesh Subdomains:
Subdomain 0: 70 elems (QUAD4, 70 active), 88 active nodes
Volume: 63.05
Bounding box minimum: (x,y,z)=( 0, 0, 0)
Bounding box maximum: (x,y,z)=( 6.5, 9.7, 0)
Bounding box delta: (x,y,z)=( 6.5, 9.7, 0)
Global mesh volume = 63.05
Capturing features of the geometry using CartesianMeshGenerator:
@@ -1,10 +1,10 @@
[Mesh]
[bulk]
- type = GeneratedMeshGenerator
+ type = CartesianMeshGenerator
dim = 2
- xmax = 6.5
- ymax = 9.7
- nx = 7
- ny = 10
+ dx = '0.5 0.75 0.025 4.0 0.025 0.75 0.5'
+ dy = '0.5 0.3 0.025 7.6 0.025 0.75 0.5'
+ ix = '2 3 1 16 1 3 2'
+ iy = '2 1 1 30 1 3 2'
[]
[]
(- tutorials/shield_multiphysics/inputs/step01_diffusion/mesh_part1.i)Specifying subdomains or "blocks" to capture differing materials:
@@ -1,10 +1,17 @@
[Mesh]
[bulk]
type = CartesianMeshGenerator
dim = 2
dx = '0.5 0.75 0.025 4.0 0.025 0.75 0.5'
dy = '0.5 0.3 0.025 7.6 0.025 0.75 0.5'
ix = '2 3 1 16 1 3 2'
iy = '2 1 1 30 1 3 2'
+ subdomain_id = '0 0 0 0 0 0 0
+ 0 1 1 1 1 1 0
+ 0 2 2 3 2 2 0
+ 0 2 2 4 2 2 0
+ 0 2 2 2 2 2 0
+ 0 2 2 2 2 2 0
+ 0 0 0 0 0 0 0'
[]
[]
(- tutorials/shield_multiphysics/inputs/step01_diffusion/mesh_part2.i)Extending to 3D with "slices" of the domain:
@@ -1,17 +1,69 @@
[Mesh]
[bulk]
type = CartesianMeshGenerator
- dim = 2
+ dim = 3
dx = '0.5 0.75 0.025 4.0 0.025 0.75 0.5'
dy = '0.5 0.3 0.025 7.6 0.025 0.75 0.5'
+ dz = '0.5 0.3 0.025 3.6 0.025 0.3 0.5'
ix = '2 3 1 16 1 3 2'
iy = '2 1 1 30 1 3 2'
- subdomain_id = '0 0 0 0 0 0 0
- 0 1 1 1 1 1 0
- 0 2 2 3 2 2 0
- 0 2 2 4 2 2 0
- 0 2 2 2 2 2 0
- 0 2 2 2 2 2 0
- 0 0 0 0 0 0 0'
+ iz = '2 1 1 14 1 1 2'
+ subdomain_id = '
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+
+ 0 0 0 0 0 0 0
+ 0 1 1 1 1 1 0
+ 0 2 2 1 2 2 0
+ 0 2 2 1 2 2 0
+ 0 2 2 2 2 2 0
+ 0 2 2 2 2 2 0
+ 0 0 0 0 0 0 0
+
+ 0 0 0 0 0 0 0
+ 0 1 1 1 1 1 0
+ 0 2 2 3 2 2 0
+ 0 2 2 3 2 2 0
+ 0 2 2 2 2 2 0
+ 0 2 2 2 2 2 0
+ 0 0 0 0 0 0 0
+
+ 0 0 0 0 0 0 0
+ 0 1 1 1 1 1 0
+ 0 2 2 3 2 2 0
+ 0 2 2 4 2 2 0
+ 0 2 2 2 2 2 0
+ 0 2 2 2 2 2 0
+ 0 0 0 0 0 0 0
+
+ 0 0 0 0 0 0 0
+ 0 1 1 1 1 1 0
+ 0 2 2 3 2 2 0
+ 0 2 2 3 2 2 0
+ 0 2 2 2 2 2 0
+ 0 2 2 2 2 2 0
+ 0 0 0 0 0 0 0
+
+ 0 0 0 0 0 0 0
+ 0 1 1 1 1 1 0
+ 0 1 1 1 1 1 0
+ 0 1 1 1 1 1 0
+ 0 1 1 1 1 1 0
+ 0 1 1 1 1 1 0
+ 0 0 0 0 0 0 0
+
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0
+ '
[]
[]
(- tutorials/shield_multiphysics/inputs/step01_diffusion/mesh_part3.i)Z-axis not to scale
Finally, we can string together mesh generators to:
Remove blocks with BlockDeletionGenerator
Rename blocks to something more memorable with RenameBlockGenerator
@@ -1,69 +1,101 @@
[Mesh]
[bulk]
type = CartesianMeshGenerator
dim = 3
dx = '0.5 0.75 0.025 4.0 0.025 0.75 0.5'
dy = '0.5 0.3 0.025 7.6 0.025 0.75 0.5'
dz = '0.5 0.3 0.025 3.6 0.025 0.3 0.5'
ix = '2 3 1 16 1 3 2'
iy = '2 1 1 30 1 3 2'
iz = '2 1 1 14 1 1 2'
subdomain_id = '
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 2 2 1 2 2 0
0 2 2 1 2 2 0
0 2 2 2 2 2 0
0 2 2 2 2 2 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 2 2 3 2 2 0
0 2 2 3 2 2 0
0 2 2 2 2 2 0
0 2 2 2 2 2 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 2 2 3 2 2 0
0 2 2 4 2 2 0
0 2 2 2 2 2 0
0 2 2 2 2 2 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 2 2 3 2 2 0
0 2 2 3 2 2 0
0 2 2 2 2 2 0
0 2 2 2 2 2 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 1 1 1 1 1 0
0 1 1 1 1 1 0
0 1 1 1 1 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
'
[]
+ [hollow_concrete]
+ type = BlockDeletionGenerator
+ input = bulk
+ block = 4
+ []
+ [rename_blocks]
+ type = RenameBlockGenerator
+ input = hollow_concrete
+ old_block = '0 1 2 3'
+ new_block = 'concrete_hd concrete water Al'
+ show_info = true
+ []
+ [rename_boundaries_step1]
+ type = RenameBoundaryGenerator
+ input = 'rename_blocks'
+ old_boundary = 'back front'
+ new_boundary = 'temp1 temp2'
+ show_info = true
+ []
+ [rename_boundaries_step2]
+ type = RenameBoundaryGenerator
+ input = 'rename_boundaries_step1'
+ old_boundary = 'bottom top'
+ new_boundary = 'back front'
+ show_info = true
+ []
+ [rename_boundaries_step3]
+ type = RenameBoundaryGenerator
+ input = 'rename_boundaries_step2'
+ old_boundary = 'temp1 temp2'
+ new_boundary = 'bottom top'
+ []
[]
(- tutorials/shield_multiphysics/inputs/step01_diffusion/mesh_part4.i)We generate the full mesh now with the consolidated meshing script:
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step01_diffusion
moose-opt -i mesh.i --mesh-only
With this mesh, we first consider the steady-state diffusion equation on the domain : find such that
where on the back (), on the front () and with on the remaining boundaries.
An input file is used to represent the problem in MOOSE. It follows a very standardized syntax.
MOOSE uses the "hierarchical input text" (hit) format.
[Kernels]
[diffusion]
type = Diffusion
variable = T # Operate on the "temperature" variable from above
[]
[]
(tutorials/shield_multiphysics/inputs/step01_diffusion/step1.i)A basic MOOSE input file requires six parts, each of which will be covered in greater detail later.
[Mesh]
: Define the geometry of the domain
[Variables]
: Define the unknown(s) of the problem
[Kernels]
: Define the equation(s) to solve
[BCs]
: Define the boundary condition(s) of the problem
[Executioner]
: Define how the problem will be solved
[Outputs]
: Define how the solution will be returned
[Mesh]
[fmg]
type = FileMeshGenerator
file = 'mesh_in.e' # this file must be generated using mesh.i
[]
[]
[Variables]
[T]
# Adds a Linear Lagrange variable by default
[]
[]
[Kernels]
[diffusion]
type = Diffusion
variable = T # Operate on the "temperature" variable from above
[]
[]
[BCs]
[left]
type = DirichletBC # Simple u=value BC
variable = T # Variable to be set
boundary = top # Name of a sideset in the mesh
value = 330
[]
[right]
type = DirichletBC
variable = T
boundary = bottom
value = 300
[]
[]
[Executioner]
type = Steady # Steady state problem
solve_type = NEWTON # Perform a Newton solve
petsc_options_iname = '-pc_type -pc_hypre_type' # PETSc option pairs with values below
petsc_options_value = 'hypre boomeramg'
[]
[Outputs]
exodus = true # Output Exodus format
[]
(tutorials/shield_multiphysics/inputs/step01_diffusion/step1.i)An executable is available from loading the MOOSE conda or HPC module.
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step01_diffusion
moose-opt -i mesh.i --mesh-only
moose-opt -i step1.i
The simulation header gives a lot of helpful information
Framework Information:
MOOSE Version: git commit 77c5910099 on 2025-05-28
LibMesh Version:
PETSc Version: 3.23.0
SLEPc Version: 3.23.0
Current Time: Wed Jun 4 22:26:52 2025
Executable Timestamp: Mon Jun 2 08:29:52 2025
Input File(s):
/Users/giudgl/projects/moose_v9/tutorials/shield_multiphysics/inputs/step01_diffusion/step1.i
Checkpoint:
Wall Time Interval: Every 3600 s
User Checkpoint: Disabled
# Checkpoints Kept: 2
Execute On: TIMESTEP_END
Parallelism:
Num Processors: 1
Num Threads: 1
Mesh:
Parallel Type: replicated
Mesh Dimension: 3
Spatial Dimension: 3
Nodes: 21692
Elems: 17920
Num Subdomains: 4
Nonlinear System:
Num DOFs: 21692
Num Local DOFs: 21692
Variables: "T"
Finite Element Types: "LAGRANGE"
Approximation Orders: "FIRST"
Execution Information:
Executioner: Steady
Solver Mode: NEWTON
PETSc Preconditioner: hypre boomeramg strong_threshold: 0.7 (auto)
MOOSE Preconditioner: SMP (auto)
0 Nonlinear |R| = 3.409028e+03
0 Linear |R| = 3.409028e+03
1 Linear |R| = 1.290229e+02
2 Linear |R| = 1.113660e+01
3 Linear |R| = 8.340899e-01
4 Linear |R| = 5.736450e-02
5 Linear |R| = 2.859743e-03
1 Nonlinear |R| = 2.859743e-03
0 Linear |R| = 2.859743e-03
1 Linear |R| = 2.670323e-04
2 Linear |R| = 1.878905e-05
3 Linear |R| = 9.979916e-07
4 Linear |R| = 7.651689e-08
5 Linear |R| = 4.971569e-09
2 Nonlinear |R| = 4.971578e-09
Solve Converged!
To introduce the concept of FEM, consider a polynomial regression exercise. We can search for a polynomial function that solves the following problems:
Discrete example: Given sampled locations with associated values, we want our polynomial function to be as close to the input data as possible.
Continuous example: Given a complicated function, we want to have our polynomial function as close to the input function as possible.
Let us write the polynomial in the following form:
where are scalar coefficients (expansion coefficients) and monomials are "basis functions". Thus, the problem is to find such that is closest the the given points or a given function.
Define a set of points (Let's pick the points using ):
Substitute data into the polynomial model:
This results 4 equations for 3 unknowns () that can be expressed as the following linear system:
We want to get the function closest to the points. Distance in this case can be expressed by the discrete norm:
We want to minimize the norm of the squared distances ("least squares"):
which requires the solution of this problem:
which results in:
These coefficients define the solution function:
We want to minimize the squared distance between the known function () and the polynomial approximate () on a given domain :
The cumulative squared distance can be expressed as:
which we would like to minimize in a least-squares sense, with respect to the coefficients in (entries of ):
We can move the derivative with respect to into the integral:
which results in the following system (dropping the factor 2):
with
solving this sytem results in:
These coefficients define the solution function:
The coefficients are meaningless, they are just numbers used to define a function.
The solution is not the coefficients, but rather the function created when they are multiplied by their respective basis functions and summed.
The function is defined everywhere in the domain.
can be evaluated at the point , for example, by computing:
where the correspond to the coefficients in the solution vector, and the are the respective functions.
FEM is a method for numerically approximating the solution to partial differential equations (PDEs). FEM is widely applicable for a large range of PDEs and domains.
Example PDEs: Have you seen them before? Are they linear/nonlinear? Coupled?
(1)(2)(3)FEM finds a solution function that is made up of "shape functions" multiplied by coefficients and added together, just like in polynomial regression, except the functions are not typically as simple (although they can be).
The Galerkin Finite Element method is different from finite difference and finite volume methods because it finds a piecewise continuous function which is an approximate solution to the governing PDEs.
FEM provides an approximate solution. The true solution can only be represented as well as the shape function basis can represent it!
FEM is supported by a rich mathematical theory with proofs about accuracy, stability, convergence and solution uniqueness.
Using FEM to find the solution to a PDE starts with forming a "weighted residual" or "variational statement" or "weak form", this processes if referred to here as generating a weak form.
The weak form provides flexibility, both mathematically and numerically and it is needed by MOOSE to solve a problem.
Generating a weak form generally involves these steps:
Write down strong form of PDE.
Rearrange terms so that zero is on the right of the equals sign.
Multiply the whole equation by a "test" function .
Integrate the whole equation over the domain .
Integrate by parts and use the divergence theorem to get the desired derivative order on your functions and simultaneously generate boundary integrals.
Obtain the weak form for the equations listed on the previous slide and the shape functions.
Polynomial fitting:
Form equations that the coefficients of a polynomial function must satisfy to fit
Solve the linear system
Reconstruct the fit by evaluating the polynomial defined by its coefficients
Finite Element method:
Form equations on each element to minimize the residual of an equation
Solve the linear system
Reconstruct the function
Re-evaluate the equation and iterate (for nonlinear equations)
Suppose is a scalar function, is a vector function, and both are continuously differentiable functions, then the product rule states:
The function can be integrated over the volume and rearranged as:
(4)The divergence theorem transforms a volume integral into a surface integral on surface :
(5)where is the outward normal vector for surface . Combining Eq. (4) and Eq. (5) yield:
(6)(1) Write the strong form of the equation:
(2) Rearrange to get zero on the right-hand side:
(3) Multiply by the test function :
(4) Integrate over the domain :
(5) Integrate by parts and apply the divergence theorem, by using Eq. (6) on the left-most term of the PDE:
Write in inner product notation. Each term of the equation will inherit from an existing MOOSE type as shown below.
(7)[Kernels]
[diff]
type = Diffusion
variable = u
[]
[]
[BCs]
[right]
type = NeumannBC
variable = u
boundary = 1
value = 1
[]
[]
[Kernels]
[adv_u]
implicit = false
type = ConservativeAdvection
variable = u
velocity = '1 0 0'
[]
[]
[Kernels]
[ffn]
type = BodyForce
variable = u
function = f_fn
[]
[]
While the weak form is essentially what is needed for adding physics to MOOSE, in traditional finite element software more work is necessary.
The weak form must be discretized using a set of "basis functions" amenable for manipulation by a computer.
Images copyright Becker et al. (1981)
The discretized expansion of takes on the following form:
where are the "basis functions", which form the basis for the "trial function", . is the total number of functions for the discretized domain.
The gradient of can be expanded similarly:
In the Galerkin finite element method, the same basis functions are used for both the trial and test functions:
Substituting these expansions back into the example weak form (Eq. (7)) yields:
(8)The left-hand side of the equation above is referred to as the component of the "residual vector," .
Shape Functions are the functions that get multiplied by coefficients and summed to form the solution.
Individual shape functions are restrictions of the global basis functions to individual elements.
They are analogous to the functions from polynomial fitting (in fact, you can use those as shape functions).
Typical shape function families: Lagrange, Hermite, Hierarchic, Monomial, Clough-Toucher
Lagrange shape functions are the most common, which are interpolatory at the nodes, i.e., the coefficients correspond to the values of the functions at the nodes.
Example bi-quadratic basis functions defined on the (square) Quad9 element:
(left) is associated to a "corner" node, it is zero on the opposite edges.
(middle) is associated to a "mid-edge" node, it is zero on all other edges.
(right) is associated to the "center" node, it is symmetric and on the element.
Shape functions can be set for each variable in the Variables
block:
[Variables]
[u]
order = FIRST
family = LAGRANGE
block = 0
[]
[v]
order = FIRST
family = LAGRANGE
block = 1
[]
[]
(test/tests/variables/second_derivative/interface_kernels.i)The only remaining non-discretized parts of the weak form are the integrals. First, split the domain integral into a sum of integrals over elements:
(9)Through a change of variables, the element integrals are mapped to integrals over the "reference" elements .
where is the Jacobian of the map from the physical element to the reference element.
Quadrature, typically "Gaussian quadrature", is used to approximate the reference element integrals numerically.
where is the weight function at quadrature point .
Under certain common situations, the quadrature approximation is exact. For example, in 1 dimension, Gaussian Quadrature can exactly integrate polynomials of order with quadrature points.
Applying the quadrature to Eq. (9) we can simply compute:
where is the spatial location of the quadrature point and is its associated weight.
MOOSE handles multiplication by the Jacobian () and the weight () automatically, thus your Kernel
object is only responsible for computing the part of the integrand.
Sampling at the quadrature points yields:
Thus, the weak form of Eq. (8) becomes:
(10)The second sum is over boundary faces, . MOOSE Kernel
or BoundaryCondition
objects provide each of the terms in square brackets (evaluated at or as necessary), respectively.
There is a mesh, with cells and functions, polynomials, defined by their coefficients
We plug in these functions in the PDEs, then obtain a weak form
We evaluate the integrals in the weak form using a quadrature, thus forming a set of equations
Now let's solve these equations to obtain the coefficients
Newton's method is a "root finding" method with good convergence properties, in "update form", for finding roots of a scalar equation it is defined as: , is given by
The residual, , as defined by Eq. (10) is a nonlinear system of equations,
that is used to solve for the coefficients .
For this system of nonlinear equations Newton's method is defined as:
(11)where is the Jacobian matrix evaluated at the current iterate:
The solve type is specified in the [Executioner]
block within the input file:
[Executioner]
solve_type = PJFNK
Available options include:
PJFNK: Preconditioned Jacobian Free Newton Krylov (default)
JFNK: Jacobian Free Newton Krylov
NEWTON: Performs solve using exact Jacobian for preconditioning
FD: PETSc computes terms using a finite difference method (debug)
Uses a Krylov subspace-based linear solver
(12)The action of the Jacobian is approximated by:
(13)The Kernel
method computeQpResidual
is called to compute during the nonlinear step (Eq. (11)).
During each linear step of JFNK, the computeQpResidual
method is called to approximate the action of the Jacobian on the Krylov vector.
The action of the preconditioned Jacobian is approximated by:
(14)The Kernel
method computeQpResidual
is called to compute during the nonlinear step (Eq. (11)).
During each linear step of PJFNK, the computeQpResidual
method is called to approximate the action of the Jacobian on the Krylov vector. The computeQpJacobian
and computeQpOffDiagJacobian
methods are used to compute values for the preconditioning matrix.
The Kernel
method computeQpResidual
is called to compute during the nonlinear step (Eq. (11)).
The computeQpJacobian
and computeQpOffDiagJacobian
methods are used to compute the preconditioning matrix. It is assumed that the preconditioning matrix is the Jacobian matrix, thus the residual and Jacobian calculations are able to remain constant during linear iterations.
Select a preconditioner using PETSC options, either in the executioner or in the [Preconditioning]
block:
[Executioner]
type = Steady
petsc_options_iname = '-pc_type -pc_hypre_type'
petsc_options_value = 'hypre boomeramg'
Some examples:
LU : form the actual Jacobian inverse, useful for small to medium problems but does not scale well
Hypre BoomerAMG : algebraic multi-grid, works well for diffusive problems
Jacobi : preconditions with the diagonal, row sum, or row max of Jacobian
For parallel preconditioners, the sub-block (on-process) preconditioners can be controlled with the PETSc option -sub_pc_type
. E.g. for a parallel block Jacobi preconditioner (-pc_type bjacobi) the sub-block preconditioner could be set to ILU or LU etc. with -sub_pc_type ilu
, -sub_pc_type lu
, etc.
The Finite Element Method is a way of numerically approximating the solution of PDEs.
Just like polynomial fitting, FEM finds coefficients for basis functions.
The solution is the combination of the coefficients and the basis functions, and the solution can be sampled anywhere in the domain.
Integrals are computed numerically using quadrature.
Newton's method provides a mechanism for solving a system of nonlinear equations.
The Preconditioned Jacobian Free Newton Krylov (PJFNK) method allows us to avoid explicitly forming the Jacobian matrix while still computing its action.
MOOSE uses forward mode automatic differentiation from the MetaPhysicL package.
Moving forward, the idea is for application developers to be able to develop entire apps without writing a single Jacobian statement. This has the potential to decrease application development time.
In terms of computing performance, presently AD Jacobians are slower to compute than hand-coded Jacobians, but they parallelize extremely well and can benefit from using a NEWTON
solve, which often results in decreased solve time overall.
Relies on two techniques:
chain rule
operator overloading
One thing to note is that the derivatives are with regards to the degrees of freedom, but the residual is computed at quadrature points! There are therefore often several non-zero coefficients even for simply (value of variable u
at a quadrature point).
The remainder of the tutorial will focus on using automatic differentiation (AD) for computing Jacobian terms, but it is possible to compute them manually.
It is recommended that all new Kernel objects use AD.
The following relationships are useful when computing Jacobian terms.
(15)(16)Again, consider the advection-diffusion equation with nonlinear , , and :
Thus, the component of the residual vector is:
Using the previously-defined rules in Eq. (15) and Eq. (16) for and , the entry of the Jacobian is then:
That even for this "simple" equation, the Jacobian entries are nontrivial: they depend on the partial derivatives of , , and , which may be difficult or time-consuming to compute analytically.
In a multiphysics setting with many coupled equations and complicated material properties, the Jacobian might be extremely difficult to determine.
To implement the Heat Conduction equation, we will use a Kernel object to compute the residual and the Jacobian of the diffusion term:
where is the thermal diffusivity.
A Kernel
is C++ class, which inherits from MooseObject
that is used by MOOSE for coding volume integrals of a partial differential equation (PDE).
A system for computing the residual contribution from a volumetric term within a PDE using the Galerkin finite element method.
A Kernel
objects represents one or more terms in a PDE.
A Kernel
object computes the residual at each quadrature point on every element. When forming a Jacobian, the Kernel
object is also called to compute its components at each quadrature point.
Recall the steady-state diffusion equation on the 3D domain :
The weak form of this equation includes a volume integral, which in inner-product notation, is given by:
where are the test functions and is the finite element solution.
This integral is approximated by the kernel using the specified quadrature.
Every object in MOOSE includes a set of custom parameters within an InputParameters
object that is used to construct the object.
Some object parameters are required. MOOSE will error if they are not provided in the input file.
[Kernels]
[diff]
type = Diffusion
[]
[]
The example above will error because the variable
parameter is missing.
The MOOSE VSCode plugin
will automatically create a <required_parameter> =
line for each required parameter when using the syntax auto-complete.
If the value of a parameter is standard, it does not need to be always included in the input file, unless the user wants to change its value! In the example below, the block
parameter is not specified, which means the default (empty) is applied.
[Kernels]
[diff]
type = Diffusion
variable = u
[]
[]
The MOOSE VSCode plugin
will automatically create a <optional_parameter> = <default_value>
line for an optional parameter when using the auto-complete feature and selecting said parameter.
Various types of objects in MOOSE can be coupled to variables. MOOSE will then automatically compute the local variable values when executing the object.
[Variables]
[P][]
[T][]
[]
[UserObjects]
[temp_pressure_check]
type = CheckTemperatureAndPressure
temperature = T
pressure = P # if not provided a value of 101.325 would be used
[]
[]
Within the input file it is possible to used a variable name or a constant value for a coupledVar
parameter.
pressure = P
pressure = 42
Input constant values may be restricted to a range of values. This is enforced programmatically, and MOOSE will error if the user passes a value out of the specified bounds.
Each application is capable of generating documentation from the validParams
functions.
Option 1: Command line --dump
--dump [optional search string]
the search string may contain wildcard characters
searches both block names and parameters
Option 2: Command line --show-input
generates a tree based on your input file\\
Option 3: mooseframework.org/syntax
MOOSE can support integer, float, vector, string, ... parameters. However this is specified in each object, and types cannot be changed in the input file.
Other supported parameter types include:
Point
RealVectorValue
RealTensorValue
SubdomainID
std::map<std::string, Real>
MOOSE uses a large number of string types to make InputParameters
more context-aware. All of these types can be treated just like strings, but will cause compile errors if mixed improperly in the template functions.
SubdomainName
BoundaryName
FileName
DataFileName
VariableName
FunctionName
UserObjectName
PostprocessorName
MeshFileName
OutFileName
NonlinearVariableName
AuxVariableName
MOOSE supports enumerations as parameters. An enumeration is a fixed list of options, that the user may then select from. Defaults are supported for these enumerations.
In the example below, the value_type
parameters can take max
or min
values, with a default of max
. If you specify abc
to value_type
, it will error.
[Postprocessors]
[max]
type = ElementExtremeValue
variable = u
[]
[min]
type = ElementExtremeValue
variable = u
value_type = min
[]
[]
(test/tests/postprocessors/element_extreme_value/element_extreme_value.i)Variables can be defined in the input file, and substituted anywhere below their definition.
diff = 3
[Variables]
[u]
family = LAGRANGE
initial_condition = ${diff}
[]
[]
We can have the parser perform simple math for us using the ${fparser <some math>}
syntax. The available syntax can be found on this page.
diff = 3
scale_diff = 2
offset_diff = 1
[Variables]
[u]
family = LAGRANGE
initial_condition = ${fparse offset_diff + scale_diff * diff} # = 1 + 2 * 3
[]
[]
MOOSE supports both S.I. and imperial units. But everything must be consistent. Your input file, your mesh, and your material properties must use the same unit system. To help adapt your input file, we provide unit conversion capabilities.
length_in = 25
length_m = ${units 23 in -> m}
# we can still use input file variables too
length_meters = ${units ${length_in} in -> m}
A table of unit and units names is provided at this link.
Global parameters are defined in a special block and are substituted everywhere in the input they can be. This lets us reduce the size of the input file, at the cost these more implicit substitutions.
[GlobalParams]
second_order = true # this will go in the [Mesh] block
order = SECOND # this will go in the each variable object
[]
[Variables]
[u]
# the order is being changed to SECOND without writing it down here
[]
[v]
# we don't want v to be second order
order = FIRST
[]
[]
Be careful with global parameters with common parameter names such as block
or variable
. They will apply to every single object, even the ones you did not think of.
Input files can be concatenated using the !include <other input file.i>
syntax. This is helpful to:
share common input syntax between multiple inputs (for example a steady and a transient simulations, sharing the same mesh)
build long input files in multiple steps
The heat conduction equation amounts to a diffusion equation with a coefficient.
where is the thermal diffusivity.
To implement the coefficient a new Kernel object must be used: CoefDiffusion.
This object inherits from Diffusion and will use input parameters for specifying the diffusivity.
We introduce block restriction to differentiate between water and concrete. Block restriction is a common feature of MOOSE objects, introduced by setting
block = 'concrete'
[Mesh]
[fmg]
type = FileMeshGenerator
file = '../step01_diffusion/mesh_in.e'
[]
[]
[Variables]
[T]
# Adds a Linear Lagrange variable by default
[]
[]
[Kernels]
[diffusion_water]
type = CoefDiffusion
variable = T
coef = 0.6
block = water
[]
[diffusion_concrete_hd]
type = CoefDiffusion
variable = T
coef = 5
block = concrete_hd
[]
[diffusion_concrete]
type = CoefDiffusion
variable = T
coef = 2.25
block = concrete
[]
[diffusion_Al]
type = CoefDiffusion
variable = T
coef = 175
block = Al
[]
[]
[BCs]
[left]
type = DirichletBC # Simple u=value BC
variable = T # Variable to be set
boundary = top # Name of a sideset in the mesh
value = 330
[]
[right]
type = DirichletBC
variable = T
boundary = bottom
value = 300
[]
[]
[Executioner]
type = Steady # Steady state problem
solve_type = NEWTON # Perform a Newton solve
petsc_options_iname = '-pc_type -pc_hypre_type' # PETSc option pairs with values below
petsc_options_value = 'hypre boomeramg'
[]
[Outputs]
exodus = true # Output Exodus format
[]
(tutorials/shield_multiphysics/inputs/step02_coef_diffusion/step2.i)
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step02_coef_diffusion
moose-opt -i step2.i
A system for outputting simulation data to the screen or files.
The output system is designed to be just like any other system in MOOSE: modular and expandable.
It is possible to create multiple output objects for outputting:
at specific time or timestep intervals,
custom subsets of variables, and
to various file types.
There exists a short-cut syntax for common output types as well as common parameters.
The following two methods for creating an Output object are equivalent within the internals of MOOSE.
[Outputs]
exodus = true
[]
[Outputs]
[out]
type = Exodus
[]
[]
The content of each Output
can customized, see for example for an Exodus output:
[Outputs]
[out]
type = Exodus
output_material_properties = true
# removes some quantities from the output
hide = 'power_pp pressure_var'
[]
[]
[Outputs]
interval = 10 # this is a time step interval
[exo]
type = Exodus
interval = 1 # overrides interval from top-level
[]
[cp]
type = Checkpoint # Uses interval specified from top-level
[]
[]
The default naming scheme for output files utilizes the input file name (e.g., input.i) with a suffix that differs depending on how the output is defined: An "_out" suffix is used for Outputs created using the short-cut syntax. sub-blocks use the actual sub-block name as the suffix.
[Outputs]
exodus = true # creates input_out.e
[other] # creates input_other.e
type = Exodus
interval = 2
[]
[base]
type = Exodus
file_base = out # creates out.e
[]
[]
Short-cut | Sub-block ("type=") | Description |
---|---|---|
console | Console | Writes to the screen and optionally a file |
exodus | Exodus | The most common,well supported, and controllable output type |
vtk | VTK | Visualization Toolkit format, requires --enable-vtk when building libMesh |
gmv | GMV | General Mesh Viewer format |
nemesis | Nemesis | Parallel ExodusII format |
tecplot | Tecplot | Requires --enable-tecplot when building libMesh |
xda | XDA | libMesh internal format (ascii) |
xdr | XDR | libMesh internal format (binary) |
csv | CSV | Comma separated scalar values |
gnuplot | GNUPlot | Only support scalar outputs |
checkpoint | Checkpoint | MOOSE internal format used for restart and recovery |
Paraview can read many of these (CSV, Exodus, Nemesis, VTK, GMV)
Fixed temperatures at the boundary conditions are simple but not realistic. We want to have:
a fixed heat flux from the micro-reactor inside the concrete cavity
natural convection boundary conditions with the air around the shield
convective boundary conditions with the water block
System for computing residual contributions from boundary terms of a PDE.
A BoundaryCondition
(BC) object computes a residual on a boundary (or internal side) of a domain.
There are two flavors of BC objects: Nodal and Integrated.
Integrated BCs are integrated over a boundary or internal side. They are meant to add a surface integral term, coming from example from the application of the divergence theorem.
This integral is computed using a surface quadrature.
Non-integrated BCs set values of the residual directly on a boundary or internal side. They do not rely a quadrature-point based integration.
Set a condition on the value
of a variable on a boundary:
becomes
Integrated BCs (including Neumann BCs) are actually integrated over the external face of an element.
becomes:
If , then the boundary integral is zero ("natural boundary condition").
Periodic boundary conditions are useful for modeling quasi-infinite domains and systems with conserved quantities.
1D, 2D, and 3D
With mesh adaptivity
Can be restricted to specific variables
Supports arbitrary translation vectors for defining periodicity
A system for defining analytic expressions based on the spatial location (, , ) and time, .
A Function
can depend an other functions, but not on material properties or variables.
Many objects exist in MOOSE that utilize a function, such as:
FunctionDirichletBC
FunctionNeumannBC
FunctionIC
BodyForce
Each of these objects has a "function" parameter which is set in the input file, and controls which Function
object is used.
A ParsedFunction
allow functions to be defined by strings directly in the input file, e.g.:
[Functions]
[sin_fn]
type = ParsedFunction
expression = sin(x)
[]
[cos_fn]
type = ParsedFunction
expression = cos(x)
[]
[fn]
type = ParsedFunction
expression = 's/c'
symbol_names = 's c'
symbol_values = 'sin_fn cos_fn'
[]
[]
(test/tests/functions/parsed/function.i)It is possible to include other functions, as shown above, as well as scalar variables and postprocessor values with the function definition.
Whenever an object uses a Function
-name parameter, the user may elect to instead write the expression of a x,y,z,t function directly in that parameter. A ParsedFunction
will automatically be created for this function.
A ParsedFunction
or ConstantFunction
object is automatically constructed based on the default value if a function name is not supplied in the input file.
Let's vary the water temperature in time
[water_convection]
type = ADConvectiveHeatFluxBC
variable = T
boundary = 'water_boundary_inwards'
T_infinity = 300.0
heat_transfer_coefficient = 30
[]
The same BC
object can accept a function parameter:
[water_convection]
type = ADConvectiveHeatFluxBC
variable = T
boundary = 'water_boundary_inwards'
T_infinity_functor = water_T_ramp
heat_transfer_coefficient = 30
[]
[Functions]
[water_T_ramp]
type = PiecewiseLinear
x = '0 10 100'
y = '300 290 290'
[]
[]
Let's vary the power input in space
[from_reactor]
type = NeumannBC
variable = T
boundary = inner_cavity
# 100 kW reactor, 108 m2 cavity area
value = '${fparse 1e5 / 108}'
[]
This time we have to select a different object:
[from_reactor]
type = FunctionNeumannBC
variable = T
boundary = inner_cavity
# 100 kW reactor, 108 m2 cavity area
function = 'heat_flux'
[]
[Functions]
[heat_flux]
type = ParsedFunction
# apply heat flux only above z=1m
expression = 'if(z > 1, 1e5 / 108, 0)'
[]
[]
First, the sidesets must be added / present in the mesh. We modified the meshing script to generate sidesets for our boundary conditions
!include ../step01_diffusion/mesh.i
[Mesh]
[add_concrete_outer_boundary]
type = RenameBoundaryGenerator
input = rename_boundaries_step3
old_boundary = 'left right front bottom top back'
new_boundary = 'air_boundary air_boundary air_boundary ground air_boundary air_boundary'
[]
[add_water_concrete_interface]
type = SideSetsBetweenSubdomainsGenerator
input = add_concrete_outer_boundary
primary_block = 'water water water'
paired_block = 'concrete_hd concrete Al'
new_boundary = 'water_boundary'
[]
[add_water_concrete_interface_inwards]
type = SideSetsBetweenSubdomainsGenerator
input = add_water_concrete_interface
primary_block = 'concrete_hd concrete Al'
paired_block = 'water water water'
new_boundary = 'water_boundary_inwards'
[]
[add_inner_cavity_solid]
type = SideSetsAroundSubdomainGenerator
input = add_water_concrete_interface_inwards
block = Al
new_boundary = 'inner_cavity_solid'
include_only_external_sides = true
[]
[add_inner_cavity_water]
type = SideSetsAroundSubdomainGenerator
input = add_inner_cavity_solid
block = water
new_boundary = 'inner_cavity_water'
include_only_external_sides = true
[]
[]
(tutorials/shield_multiphysics/inputs/step03_boundary_conditions/mesh.i)We apply a NeumannBC for fixed heat flux on the inner cavity.
[BCs]
[from_reactor]
type = NeumannBC
variable = T
boundary = inner_cavity_solid
# 5 MW reactor, only 50kW removed through radiation, 144 m2 cavity area
value = '${fparse 5e4 / 144}'
[]
[]
(tutorials/shield_multiphysics/inputs/step03_boundary_conditions/step3.i)We apply a DirichletBC for a fixed temperature with the ground
.
[BCs]
[ground]
type = DirichletBC
variable = T
value = 300
boundary = 'ground'
[]
[]
(tutorials/shield_multiphysics/inputs/step03_boundary_conditions/step3.i)Convection with air using ConvectiveHeatFluxBC.
[BCs]
[air_convection]
type = ConvectiveHeatFluxBC
variable = T
boundary = 'air_boundary'
T_infinity = 300.0
# The heat transfer coefficient should be obtained from a correlation
heat_transfer_coefficient = 10
[]
[]
(tutorials/shield_multiphysics/inputs/step03_boundary_conditions/step3.i)Note that sidesets are oriented. The variables on which the BC is applied must be defined on the primary side (opposite the normal) of the sideset. For an external boundary, this is never a concern.
Convection with water
We use the same boundary condition for the water boundary as for the convection with air for now. When we introduce a separate variable for the water temperature, we will revisit this. We use the 'water_boundary_inwards' surface because the solid block is on its primary side.
[BCs]
[water_convection]
type = ConvectiveHeatFluxBC
variable = T
boundary = 'water_boundary_inwards'
T_infinity = 300.0
# The heat transfer coefficient should be obtained from a correlation
heat_transfer_coefficient = 600
[]
[]
(tutorials/shield_multiphysics/inputs/step03_boundary_conditions/step3.i)Summary of the boundary conditions:
[Mesh]
[fmg]
type = FileMeshGenerator
file = 'mesh_in.e'
[]
[]
[Variables]
[T]
# Adds a Linear Lagrange variable by default
block = 'concrete concrete_hd Al'
[]
[]
[Kernels]
[diffusion_concrete_hd]
type = CoefDiffusion
variable = T
coef = 5
block = concrete_hd
[]
[diffusion_concrete]
type = CoefDiffusion
variable = T
coef = 2.25
block = concrete
[]
[diffusion_Al]
type = CoefDiffusion
variable = T
coef = 175
block = Al
[]
[]
[BCs]
[from_reactor]
type = NeumannBC
variable = T
boundary = inner_cavity_solid
# 5 MW reactor, only 50kW removed through radiation, 144 m2 cavity area
value = '${fparse 5e4 / 144}'
[]
[air_convection]
type = ConvectiveHeatFluxBC
variable = T
boundary = 'air_boundary'
T_infinity = 300.0
# The heat transfer coefficient should be obtained from a correlation
heat_transfer_coefficient = 10
[]
[ground]
type = DirichletBC
variable = T
value = 300
boundary = 'ground'
[]
[water_convection]
type = ConvectiveHeatFluxBC
variable = T
boundary = 'water_boundary_inwards'
T_infinity = 300.0
# The heat transfer coefficient should be obtained from a correlation
heat_transfer_coefficient = 600
[]
[]
[Problem]
# No kernels on the water domain
kernel_coverage_check = false
[]
[Executioner]
type = Steady # Steady state problem
solve_type = NEWTON # Perform a Newton solve
petsc_options_iname = '-pc_type -pc_hypre_type' # PETSc option pairs with values below
petsc_options_value = 'hypre boomeramg'
[]
[Outputs]
exodus = true # Output Exodus format
[]
(tutorials/shield_multiphysics/inputs/step03_boundary_conditions/step3.i)
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step03_boundary_conditions
moose-opt -i mesh.i --mesh-only
moose-opt -i step3.i
We only show the solid temperature. The water temperature is a constant for now.
Instead of passing constant coefficients to the heat conduction kernel, we use the Material system to supply the values.
where is the thermal conductivity.
This system allows for properties that vary in space and time, that can be coupled to variables in the simulation.
A system for defining material properties to be used by multiple systems and allow for variable coupling.
The material system operates by creating a producer/consumer relationship among objects
Material
objects produce properties.
Other MOOSE objects (including materials) consume these properties.
Quantities are recomputed at quadrature points, as needed.
Multiple Material
objects may define the same "property" for different parts of the subdomain or boundaries.
Values of material properties can be stored at the previous ("old") and two-before ("older") time steps.
It can be useful to have "old" values of Material
properties available in a simulation, such as in solid mechanics plasticity constitutive models.
Traditionally, this type of value is called a "state variable"; in MOOSE, they are called "stateful material properties".
Stateful Material
properties require more memory.
Material properties may have default values, which can be found in the documentation, and are automatically prefilled when using the syntax auto-complete.
Only scalar (Real
) valued properties may have defaults.
Output of Material
properties is enabled by setting the "outputs" parameter.
The following example creates two additional variables called "mat1" and "mat2" that will show up in the output file.
[Materials]
[block_1]
type = OutputTestMaterial
block = 1
output_properties = 'real_property tensor_property'
outputs = exodus
variable = u
[]
[block_2]
type = OutputTestMaterial
block = 2
output_properties = 'vector_property tensor_property'
outputs = exodus
variable = u
[]
[]
[Outputs]
exodus = true
[]
(test/tests/materials/output/output_block.i)Material
properties can be of arbitrary (C++) type, but not all types can be output.
Type | AuxKernel | Variable Name(s) |
---|---|---|
Real | MaterialRealAux | prop |
RealVectorValue | MaterialRealVectorValueAux | prop_1, prop_2, and prop_3 |
RealStdVector | MaterialStdVectorAux | prop_1, prop_2, and prop_3 |
RealTensorValue | MaterialRealTensorValueAux | prop_11, prop_12, prop_13, prop_21, etc. |
DenseMatrix | MaterialRealDenseMatrixAux | prop_11, prop_12, prop_13, prop_21, etc. |
AD-material property types can also be output.
Three material properties must be produced for consumption by kernels of the heat conduction equation:
thermal conductivity by the conduction term
density and specific heat by the time derivative of the energy
Both shall be computed with a single Material object: HeatConductionMaterial.
[Materials]
[concrete_hd]
type = ADHeatConductionMaterial
block = concrete_hd
temp = 'T'
# we specify a function of time, temperature is passed as the time argument
# in the material
thermal_conductivity_temperature_function = '5.0 + 0.001 * t'
[]
[concrete]
type = ADHeatConductionMaterial
block = concrete
temp = 'T'
thermal_conductivity_temperature_function = '2.25 + 0.001 * t'
[]
[Al]
type = ADHeatConductionMaterial
block = Al
temp = T
thermal_conductivity_temperature_function = '175'
[]
[]
(tutorials/shield_multiphysics/inputs/step04_heat_conduction/step4.i)The CoefDiffusion Kernel object uses input parameters for defining the thermal conductivity. Instead, the HeatConduction Kernel utilizes the material properties defined in HeatConductionMaterial automatically.
[Kernels]
[diffusion_concrete]
type = ADHeatConduction
variable = T
[]
[]
(tutorials/shield_multiphysics/inputs/step04_heat_conduction/step4.i)Note: we use kernels with automatic differentiation (AD) for simplicity.
[Mesh]
[fmg]
type = FileMeshGenerator
file = '../step03_boundary_conditions/mesh_in.e'
[]
[]
[Variables]
[T]
# Adds a Linear Lagrange variable by default
block = 'concrete_hd concrete Al'
[]
[]
[Kernels]
[diffusion_concrete]
type = ADHeatConduction
variable = T
[]
[]
[Materials]
[concrete_hd]
type = ADHeatConductionMaterial
block = concrete_hd
temp = 'T'
# we specify a function of time, temperature is passed as the time argument
# in the material
thermal_conductivity_temperature_function = '5.0 + 0.001 * t'
[]
[concrete]
type = ADHeatConductionMaterial
block = concrete
temp = 'T'
thermal_conductivity_temperature_function = '2.25 + 0.001 * t'
[]
[Al]
type = ADHeatConductionMaterial
block = Al
temp = T
thermal_conductivity_temperature_function = '175'
[]
[]
[BCs]
[from_reactor]
type = NeumannBC
variable = T
boundary = inner_cavity_solid
# 5 MW reactor, only 50 kW removed from radiation, 144 m2 cavity area
value = '${fparse 5e4 / 144}'
[]
[air_convection]
type = ADConvectiveHeatFluxBC
variable = T
boundary = 'air_boundary'
T_infinity = 300.0
# The heat transfer coefficient should be obtained from a correlation
heat_transfer_coefficient = 10
[]
[ground]
type = DirichletBC
variable = T
value = 300
boundary = 'ground'
[]
[water_convection]
type = ADConvectiveHeatFluxBC
variable = T
boundary = 'water_boundary_inwards'
T_infinity = 300.0
# The heat transfer coefficient should be obtained from a correlation
heat_transfer_coefficient = 600
[]
[]
[Problem]
# No kernels on the water domain
kernel_coverage_check = false
# No materials on the water domain
material_coverage_check = false
[]
[Executioner]
type = Steady # Steady state problem
solve_type = NEWTON # Perform a Newton solve, uses AD to compute Jacobian terms
petsc_options_iname = '-pc_type -pc_hypre_type' # PETSc option pairs with values below
petsc_options_value = 'hypre boomeramg'
[]
[Outputs]
exodus = true # Output Exodus format
[]
(tutorials/shield_multiphysics/inputs/step04_heat_conduction/step4.i)
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step04_heat_conduction
moose-opt -i step4.i
A system for direct calculation of field variables ("AuxVariables") that is designed for postprocessing, coupling, and proxy calculations.
The term "nonlinear variable" is defined, in MOOSE language, as a variable that is being solved for using a nonlinear system of PDEs using Kernel
and BoundaryCondition
objects.
The term "auxiliary variable" is defined, in MOOSE language, as a variable that is directly calculated using an AuxKernel
object.
Auxiliary variables are declared in the [AuxVariables]
input file block
Auxiliary variables are field variables that are associated with finite element shape functions and can serve as a proxy for nonlinear variables
Auxiliary variables currently come in two flavors:
Element (e.g. constant or higher order monomials)
Nodal (e.g. linear Lagrange)
Auxiliary variables have "old" and "older" states, from previous time steps, just like nonlinear variables
Element auxiliary variables can compute:
average values per element, if stored in a constant monomial variable
spatial profiles using higher order variables
AuxKernel objects computing elemental values can couple to nonlinear variables and both element and nodal auxiliary variables
[AuxVariables]
[aux]
order = CONSTANT
family = MONOMIAL
[]
[]
Element auxiliary variables are computed at each node and are stored as linear Lagrange variables
AuxKernel objects computing nodal values can only couple to nodal nonlinear variables and other nodal auxiliary variables
[AuxVariables]
[aux]
order = LAGRANGE
family = FIRST
[]
[]
VectorAuxKernels
can compute vector auxiliary variables.
The auxiliary variable will have to be one of the vector types (LAGRANCE_VEC, MONOMIAL_VEC or NEDELEC_VEC).
[AuxVariables]
[aux]
order = FIRST
family = LAGRANGE_VEC
[]
[]
[AuxKernels]
[parsed]
type = ParsedVectorAux
variable = aux
expression_x = 'x + y'
expression_y = 'x - y'
[]
[]
We are not solving for the temperature in the water yet. To represent it as a variable that is not in the nonlinear system, we use an auxiliary variable.
[AuxVariables]
[T_fluid]
family = MONOMIAL
order = CONSTANT
block = 'water'
initial_condition = 300
[]
[]
(tutorials/shield_multiphysics/inputs/step05_auxiliary_variables/step5.i)Heat flux
The heat flux can be computed using Fourier's law:
The primary unknown ("nonlinear variable") is the temperature.
Once the temperature is computed, the AuxiliarySystem can compute and output the heat flux field using the coupled temperature variable and the thermal conductivity property via DiffusionFluxAux.
Auxiliary variables come in two flavors: Nodal and Elemental.
Nodal auxiliary variables cannot couple to gradients of nonlinear variables since gradients of continuous variables are not well-defined at the nodes.
Elemental auxiliary variables can couple to gradients of nonlinear variables since evaluation occurs in the element interiors.
@@ -1,93 +1,141 @@
[Mesh]
[fmg]
type = FileMeshGenerator
file = '../step03_boundary_conditions/mesh_in.e'
[]
[]
[Variables]
[T]
# Adds a Linear Lagrange variable by default
block = 'concrete_hd concrete Al'
[]
[]
[Kernels]
[diffusion_concrete]
type = ADHeatConduction
variable = T
[]
[]
[Materials]
[concrete_hd]
type = ADHeatConductionMaterial
block = concrete_hd
temp = 'T'
# we specify a function of time, temperature is passed as the time argument
# in the material
thermal_conductivity_temperature_function = '5.0 + 0.001 * t'
[]
[concrete]
type = ADHeatConductionMaterial
block = concrete
temp = 'T'
thermal_conductivity_temperature_function = '2.25 + 0.001 * t'
[]
[Al]
type = ADHeatConductionMaterial
block = Al
temp = T
thermal_conductivity_temperature_function = '175'
+ []
+[]
+
+[AuxVariables]
+ [T_fluid]
+ family = MONOMIAL
+ order = CONSTANT
+ block = 'water'
+ initial_condition = 300
+ []
+ [heat_flux_x]
+ family = MONOMIAL
+ order = CONSTANT
+ block = 'concrete_hd concrete'
+ []
+ [heat_flux_y]
+ family = MONOMIAL
+ order = CONSTANT
+ block = 'concrete_hd concrete'
+ []
+ [heat_flux_z]
+ family = MONOMIAL
+ order = CONSTANT
+ block = 'concrete_hd concrete'
+ []
+[]
+
+[AuxKernels]
+ [diff_flux_x]
+ type = DiffusionFluxAux
+ variable = heat_flux_x
+ diffusion_variable = T
+ diffusivity = 'thermal_conductivity'
+ component = 'x'
+ []
+ [diff_flux_y]
+ type = DiffusionFluxAux
+ variable = heat_flux_y
+ diffusion_variable = T
+ diffusivity = 'thermal_conductivity'
+ component = 'y'
+ []
+ [diff_flux_z]
+ type = DiffusionFluxAux
+ variable = heat_flux_z
+ diffusion_variable = T
+ diffusivity = 'thermal_conductivity'
+ component = 'z'
[]
[]
[BCs]
[from_reactor]
type = NeumannBC
variable = T
boundary = inner_cavity_solid
# 5 MW reactor, only 50 kW removed from radiation, 144 m2 cavity area
value = '${fparse 5e4 / 144}'
[]
[air_convection]
type = ADConvectiveHeatFluxBC
variable = T
boundary = 'air_boundary'
T_infinity = 300.0
# The heat transfer coefficient should be obtained from a correlation
heat_transfer_coefficient = 10
[]
[ground]
type = DirichletBC
variable = T
value = 300
boundary = 'ground'
[]
[water_convection]
type = ADConvectiveHeatFluxBC
variable = T
boundary = 'water_boundary_inwards'
T_infinity = 300.0
# The heat transfer coefficient should be obtained from a correlation
heat_transfer_coefficient = 600
[]
[]
[Problem]
# No kernels on the water domain
kernel_coverage_check = false
# No materials on the water domain
material_coverage_check = false
[]
[Executioner]
type = Steady # Steady state problem
solve_type = NEWTON # Perform a Newton solve, uses AD to compute Jacobian terms
petsc_options_iname = '-pc_type -pc_hypre_type' # PETSc option pairs with values below
petsc_options_value = 'hypre boomeramg'
[]
[Outputs]
exodus = true # Output Exodus format
[]
(- tutorials/shield_multiphysics/inputs/step04_heat_conduction/step4.i)
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step05_auxiliary_variables
moose-opt -i step5.i
A system for dictating the simulation solving strategy.
Steady-state executioners generally solve the nonlinear system just once.
[Executioner]
type = Steady
[]
(test/tests/executioners/steady_time/steady_time.i)The Steady executioner can solve the nonlinear system multiple times while adaptively refining the mesh to improve the solution.
Transient executioners solve the nonlinear system at least once per time step.
Option | Definition |
---|---|
dt | Starting time step size |
num_steps | Number of time steps |
start_time | The start time of the simulation |
end_time | The end time of the simulation |
scheme | Time integration scheme (discussed next) |
[Executioner]
type = Transient
scheme = 'implicit-euler'
solve_type = 'PJFNK'
start_time = 0.0
num_steps = 5
dt = 0.1
[]
(test/tests/executioners/executioner/transient.i)Option | Definition |
---|---|
steady_state_detection | Whether to try and detect achievement of steady-state (Default = false ) |
steady_state_tolerance | Used for determining a steady-state; Compared against the difference in solution vectors between current and old time steps (Default = 1e-8 ) |
There are a number of options that appear in the executioner block and are used to control the solver. Here are a few common options:
Option | Definition |
---|---|
l_tol | Linear Tolerance (default: 1e-5) |
l_max_its | Max Linear Iterations (default: 10000) |
nl_rel_tol | Nonlinear Relative Tolerance (default: 1e-8) |
nl_abs_tol | Nonlinear Absolute Tolerance (default: 1e-50) |
nl_max_its | Max Nonlinear Iterations (default: 50) |
A system for defining schemes for numerical integration in time.
The TimeIntegrator can be set using "scheme" parameter within the [Executioner]
block, if the "type = Transient", the following options exist:
implicit-euler
: Backward Euler (default)
bdf2
: Second order backward difference formula
crank-nicolson
: Second order Crank-Nicolson method
dirk
: Second order Diagonally-Implicit Runge-Kutta (DIRK)
newmark-beta
: Second order Newmark-beta method (structural dynamics)
It is also possible to specify a time integrator as a separate sub-block within the input file. This allows for additional types and parameters to be defined, including custom TimeIntegrator objects.
[Executioner]
type = Transient
start_time = 0.0
num_steps = 6
dt = 0.1
[TimeIntegrator]
type = NewmarkBeta
beta = 0.4225
gamma = 0.8
[]
[]
(test/tests/time_integrators/newmark-beta/newmark_beta_prescribed_parameters.i)Consider the test problem:
for , and , is chosen so the exact solution is given by and and are the initial and Dirichlet boundary conditions corresponding to this exact solution.
A system for computing time steps for transient executioners.
MOOSE includes many built-in TimeStepper objects:
ConstantDT
SolutionTimeAdaptiveDT
IterationAdaptiveDT
FunctionDT
PostprocessorDT
TimeSequenceStepper
IterationAdaptiveDT grows or shrinks the time step based on the number of iterations taken to obtain a converged solution in the last converged step.
[Executioner]
type = Transient
solve_type = NEWTON
start_time = 0.0
dtmin = 1.0
end_time = 10.0
[TimeStepper]
type = IterationAdaptiveDT
optimal_iterations = 1
linear_iteration_ratio = 1
dt = 5.0
[]
[]
(test/tests/time_steppers/iteration_adaptive/adapt_tstep_shrink_init_dt.i)Provide a vector of time points using parameter time_sequence
, the object simply moves through these time points.
The and parameters are automatically added to the sequence.
Only time points satisfying are considered.
If a solve fails at step an additional time point is inserted and the step is resolved.
New Feature: Time steppers can now be composed to follow complex time histories. By default, the minimum of all the time steps computed by all the time steppers is used!
What steps will be taken, starting at time = 0s?
[TimeSteppers]
[constant]
type = ConstantDT
dt = 0.2
[]
[hit_these_times]
type = TimeSequenceStepper
time_sequence = '0.5 1 1.5 2.1'
[]
[]
To create a time-dependent problem add in the time derivative:
The time term exists in the heat transfer module as HeatConductionTimeDerivative.
We introduce a time derivative kernel to model the contribution to the residual/Jacobian (and various time integration vectors) of the time derivative.
[Kernels]
[diffusion_concrete]
type = ADHeatConduction
variable = T
[]
[time_derivative]
type = ADHeatConductionTimeDerivative
variable = T
[]
[]
(tutorials/shield_multiphysics/inputs/step06_transient_heat_conduction/step6_transient.i)Time stepping parameters are passed to the Executioner block with the Transient executioner type.
[Executioner]
type = Transient
num_steps = 10
dt = '${units 12 h -> s}'
solve_type = NEWTON
petsc_options_iname = '-pc_type -pc_hypre_type'
petsc_options_value = 'hypre boomeramg'
[]
(tutorials/shield_multiphysics/inputs/step06_transient_heat_conduction/step6_transient.i)There are generally two uses for time-dependent runs:
Transient: Performing a natural evolution of the model through time.
Pseudo-transient: Form of under-relaxation for a steady-state solve that more stably converges to the solution.
Material properties now include specific heat capacity and density for the time-derivative term.
HeatConductionMaterial has a parameter for the heat capacity.
GenericConstantMaterial is used to define the density.
@@ -1,22 +1,43 @@
[Materials]
[concrete_hd]
type = ADHeatConductionMaterial
block = concrete_hd
temp = 'T'
# we specify a function of time, temperature is passed as the time argument
# in the material
thermal_conductivity_temperature_function = '5.0 + 0.001 * t'
+ specific_heat = 1050
[]
[concrete]
type = ADHeatConductionMaterial
block = concrete
temp = 'T'
thermal_conductivity_temperature_function = '2.25 + 0.001 * t'
+ specific_heat = 1050
[]
[Al]
type = ADHeatConductionMaterial
block = Al
temp = T
thermal_conductivity_temperature_function = '175'
+ specific_heat = 875
+ []
+ [density_concrete_hd]
+ type = ADGenericConstantMaterial
+ block = 'concrete_hd'
+ prop_names = 'density'
+ prop_values = '3524' # kg / m3
+ []
+ [density_concrete]
+ type = ADGenericConstantMaterial
+ block = 'concrete'
+ prop_names = 'density'
+ prop_values = '2403' # kg / m3
+ []
+ [density_Al]
+ type = ADGenericConstantMaterial
+ block = 'Al'
+ prop_names = 'density'
+ prop_values = '2270' # kg / m3
[]
[]
(- tutorials/shield_multiphysics/inputs/step04_heat_conduction/step4.i)
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step06_transient_heat_conduction
moose-opt -i step6_transient.i
Since the goal of a pseudo-transient is to achieve a steady state, the heat capacity (and density) do not matter and simply serve as relaxation factors. So in this example, we use a multiplier to reduce heat capacity to converge the steady-state solution faster:
cp_multiplier = 1e-6
@@ -1,43 +1,43 @@
[Materials]
[concrete_hd]
type = ADHeatConductionMaterial
block = concrete_hd
temp = 'T'
# we specify a function of time, temperature is passed as the time argument
# in the material
thermal_conductivity_temperature_function = '5.0 + 0.001 * t'
- specific_heat = 1050
+ specific_heat = '${fparse cp_multiplier * 1050}'
[]
[concrete]
type = ADHeatConductionMaterial
block = concrete
temp = 'T'
thermal_conductivity_temperature_function = '2.25 + 0.001 * t'
- specific_heat = 1050
+ specific_heat = '${fparse cp_multiplier * 1050}'
[]
[Al]
type = ADHeatConductionMaterial
block = Al
temp = T
thermal_conductivity_temperature_function = '175'
- specific_heat = 875
+ specific_heat = '${fparse cp_multiplier * 875}'
[]
[density_concrete_hd]
type = ADGenericConstantMaterial
block = 'concrete_hd'
prop_names = 'density'
prop_values = '3524' # kg / m3
[]
[density_concrete]
type = ADGenericConstantMaterial
block = 'concrete'
prop_names = 'density'
prop_values = '2403' # kg / m3
[]
[density_Al]
type = ADGenericConstantMaterial
block = 'Al'
prop_names = 'density'
prop_values = '2270' # kg / m3
[]
[]
(- tutorials/shield_multiphysics/inputs/step06_transient_heat_conduction/step6_transient.i)The Transient
executioner has a steady_state_detection
option to determine if the simulation has reached a steady-state:
@@ -1,8 +1,9 @@
[Executioner]
type = Transient
- num_steps = 10
- dt = '${units 12 h -> s}'
+ steady_state_detection = true
solve_type = NEWTON
petsc_options_iname = '-pc_type -pc_hypre_type'
petsc_options_value = 'hypre boomeramg'
+ # Difficult to converge with relative tolerance close to steady-state
+ nl_abs_tol = 1e-8
[]
(- tutorials/shield_multiphysics/inputs/step06_transient_heat_conduction/step6_transient.i)
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step06_transient_heat_conduction
moose-opt -i step6_pseudo_transient.i
Compute the elastic and thermal strain if the shield is only held on the ground surface
where is the Cauchy stress tensor, is an additional source of stress, is the displacement vector, is the body force, is the unit normal to the boundary, is the prescribed displacement on the boundary and is the prescribed traction on the boundary.
Provides a set of tools for the calculation of multicomponent aqueous reactive transport in porous media, originally developed as the MOOSE application RAT (Guo et al., 2013).
Provides the necessary tools for modeling mechanical contact using algorithms to enforce constraints between surfaces in the mesh, to prevent penetration and develop contact forces.
Frictional ironing model using mortar contact.
The Electromagnetics module provides components and models to simulate electromagnetic wave problems using MOOSE, and facilitate coupling of electromagnetic simulations to other physical domains. Maxwell's equations are solved for complex fields using a Helmholtz wave equation formulation in 1-D and 2-D. Electrostatic contact is also provided for imperfect electric interfaces.
Electric field radiation pattern of half-wave dipole antenna.
Provides support for stand-alone native PETSc applications that are to be coupled with moose-based applications. It is also a general example for coupling to an external application.
The Fluid Properties module provides a consistent interface to fluid properties such as density, viscosity, enthalpy and many others, as well as derivatives with respect to the primary variables. The consistent interface allows different fluids to be used in an input file by simply swapping the name of the Fluid Properties UserObject in a plug-and-play manner.
Provides tools that solve fluid and structure problems, wherein, their behavior is inter-dependent. Currently capable of simulating fluid-structure interaction behavior using an acoustic formulation for the fluid.
Sloshing in an advanced reactor vessel
A MOOSE module for continuous, mesh-agnostic, high-fidelity, reduced-data MultiApp coupling
Functional expansions (FXs) are a methodology that represent information as moments of a functional series (Flusser et al., 2016). This is related to a Fourier series representation of cyclic data. Moments are generated via numerical integration for each term in the functional series to represent the field of interest. These moments can then be used to reconstruct the field in a separate app (Wendt et al., 2018; Wendt and Kerby, 2017; Kerby et al., 2017).
Solves geochemical models. The capabilities include:
Equilibrium aqueous systems
Redox disequilibrium
Sorption and surface complexation
Kinetics
All of the above combined with fluid and heat transport
It is designed to interface easily with the porous flow module so that complicated reactive transport scenarios can be studied.
Basic utilities for solving the transient heat conduction equation:
Also contains capability for generalized heat transfer (convection, radiation, ...).
The level set module provides basic functionality to solve the level set equation, which is simply the multi-dimensional advection equation:
A library for the implementation of simulation tools that solve the multi-dimensional Navier-Stokes equations using either the continuous Galerkin finite element (CGFE) or the finite volume (FV) method. The Navier-Stokes equations may be solved with:
An incompressible formulation (CGFE & FV)
A weakly compressible formulation (FV)
A fully compressible formulation (FV)
Zero-dimensional turbulence models are available and coarse regularized k-epsilon will be added soon.
Flow in a lid-driven cavity with Re=417 (left) and Re=833 (right).
The MOOSE optimization module provides functionality for solving inverse optimization problems in MOOSE. It is based on PDE constrained optimization using the PETSc TAO optimization solver.
Figure 1: Optimization cycle example for parameterizing an internal heat source distribution to match the simulated and experimental temperature field, and , respectively.
The MOOSE phase field module is a library for simplifying the implementation of simulation tools that employ the phase field model.
The PorousFlow module is a library of physics for fluid and heat flow in porous media. It is formulated in an extremely general manner, so is capable of solving problems with an arbitrary number of phases (gas, liquid, etc) and fluid components (species present in each fluid phase), using any set of primary variables.
Provides capability for tracing rays through a finite element mesh. Notable features include:
Contribution to residuals and Jacobians from along a ray
Ray interaction with internal and external boundaries
Supports storage and manipulation of data unique to each ray
Supports ray interaction with field variables
Highly parallelizable: tested to 20k MPI ranks
Example of flashlight point sources within a diffusion-reaction problem
Overlay of the rays used within the problem on the left
The MOOSE rDG module is a library for the implementation of simulation tools that solve convection-dominated problems using the class of so-called reconstructed discontinuous Galerkin (rDG) methods. The specific rDG method implemented in this module is rDG(P0P1), which is equivalent to the second-order cell-centered finite volume method (FVM).
Adds advanced meshing capabilities to MOOSE so that users can create complex-geometry meshes related to the structures of reactor cores. This includes:
Creating and modifying hexagonal mesh components for assemblies
Stitching assemblies together to form core meshes
Creating peripheral regions for assemblies and cores
Adding IDs for pins and assembly regions
Enabling the dynamic and static simulation of rotational control drums.
Meshing a microreactor in stages using the Reactor module: from pins and control drums to assemblies, cores, and peripheral regions.
A toolbox designed for performing stochastic analysis for MOOSE-based applications. Capabilities include:
Parameter Studies
Sensitivity Analysis
Uncertainty Quantification
Surrogate/Reduced-Order Model generation
The Solid Mechanics module is a library of simulation tools that solve continuum mechanics problems. The module can be used to simulation both linear and finite strain mechanics, including Elasticity and Cosserat elasticity, Plasticity and micromechanics plasticity, Creep, and Damage due to cracking and property degradation.
The Thermal Hydraulics module is a library of components that can be used to build thermal-hydraulic simulations. Basic capabilities include a 1-phase, variable-area, inviscid, compressible flow model with a non-condensable vapor mixture, 2-D and 3-D heat conduction, a control logic system, and pluggable closure systems and models.
A MOOSE-based implementation of the extended finite element method, which is a numerical method that is especially designed for treating discontinuities.
When running in parallel the default mode for operation is to use a replicated mesh, which creates a complete copy of the mesh for each processor.
[Mesh]
parallel_type = replicated
[]
Changing the type to distributed when running in parallel operates such that only the portion of the mesh owned by a processor is stored on that processor.
[Mesh]
parallel_type = distributed
[]
If the mesh is too large to read in on a single processor, it can be split prior to the simulation.
Copy the mesh to a large memory machine
Use the --split-mesh
option to split the mesh into pieces
Run the executable with --use-split
Calculations can take place in either the initial mesh configuration or, when requested, the "displaced" configuration.
To enable displacements, provide a vector of displacement variable names for each spatial dimension in the Mesh block.
[Mesh]
[gen]
type = GeneratedMeshGenerator
dim = 2
xmin = 0
ymin = 0
xmax = 0.2
ymax = 0.5
nx = 5
ny = 15
elem_type = QUAD4
[]
displacements = 'disp_x disp_y'
[]
(test/tests/transfers/general_field/shape_evaluation/displaced/child.i)Objects can enforce the use of the displaced mesh within the validParams function.
params.set<bool>("use_displaced_mesh") = true;
(framework/src/auxkernels/PenetrationAux.C)We utilize the custom syntax (more on this in Step 12) to automatically add the necessary objects (Variables, Kernels, Materials, etc.) for this problem: Physics/SolidMechanics/QuasiStatic
[Mesh]
[fmg]
type = FileMeshGenerator
file = '../step03_boundary_conditions/mesh_in.e'
[]
[]
[GlobalParams]
displacements = 'disp_x disp_y disp_z'
[]
[Variables]
[T]
# Adds a Linear Lagrange variable by default
block = 'concrete_hd concrete Al'
[]
[]
[Kernels]
[diffusion_concrete]
type = ADHeatConduction
variable = T
[]
[gravity]
type = Gravity
variable = 'disp_z'
value = '-9.81'
block = 'concrete_hd concrete Al'
[]
[]
[Physics/SolidMechanics/QuasiStatic]
[all]
# This block adds all of the proper Kernels, strain calculators, and Variables
# for Solid Mechanics equations in the correct coordinate system (autodetected)
add_variables = true
strain = FINITE
eigenstrain_names = eigenstrain
use_automatic_differentiation = true
generate_output = 'vonmises_stress elastic_strain_xx elastic_strain_yy strain_xx strain_yy'
block = 'concrete_hd concrete Al'
[]
[]
[BCs]
[from_reactor]
type = NeumannBC
variable = T
boundary = inner_cavity_solid
# 5 MW reactor, only 50 kW removed from radiation, 144 m2 cavity area
value = '${fparse 5e4 / 144}'
[]
[air_convection]
type = ADConvectiveHeatFluxBC
variable = T
boundary = 'air_boundary'
T_infinity = 300.0
# The heat transfer coefficient should be obtained from a correlation
heat_transfer_coefficient = 10
[]
[ground]
type = DirichletBC
variable = T
value = 300
boundary = 'ground'
[]
[water_convection]
type = ADConvectiveHeatFluxBC
variable = T
boundary = 'water_boundary_inwards'
T_infinity = 300.0
# The heat transfer coefficient should be obtained from a correlation
heat_transfer_coefficient = 600
[]
[hold_ground_x]
type = DirichletBC
variable = disp_x
boundary = ground
value = 0
[]
[hold_ground_y]
type = DirichletBC
variable = disp_y
boundary = ground
value = 0
[]
[hold_ground_z]
type = DirichletBC
variable = disp_z
boundary = ground
value = 0
[]
[]
[Materials]
[concrete_hd]
type = ADHeatConductionMaterial
block = concrete_hd
temp = 'T'
# we specify a function of time, temperature is passed as the time argument
# in the material
thermal_conductivity_temperature_function = '5.0 + 0.001 * t'
[]
[concrete]
type = ADHeatConductionMaterial
block = concrete
temp = 'T'
thermal_conductivity_temperature_function = '2.25 + 0.001 * t'
[]
[Al]
type = ADHeatConductionMaterial
block = Al
temp = T
thermal_conductivity_temperature_function = '175'
[]
[elasticity_tensor_concrete_hd]
type = ADComputeIsotropicElasticityTensor
youngs_modulus = 2.75e9 # (Pa)
poissons_ratio = 0.15
block = 'concrete_hd'
[]
[elasticity_tensor_concrete]
type = ADComputeIsotropicElasticityTensor
youngs_modulus = 30e9 # (Pa)
poissons_ratio = 0.2
block = 'concrete'
[]
[elasticity_tensor_Al]
type = ADComputeIsotropicElasticityTensor
youngs_modulus = 68e9 # (Pa)
poissons_ratio = 0.36
block = 'Al'
[]
[elastic_stress]
type = ADComputeFiniteStrainElasticStress
block = 'concrete_hd concrete Al'
[]
[thermal_strain_concrete_hd]
type = ADComputeThermalExpansionEigenstrain
stress_free_temperature = 300
eigenstrain_name = eigenstrain
temperature = T
thermal_expansion_coeff = 1e-5 # 1/K
block = 'concrete_hd'
[]
[thermal_strain_concrete]
type = ADComputeThermalExpansionEigenstrain
stress_free_temperature = 300
eigenstrain_name = eigenstrain
temperature = T
thermal_expansion_coeff = 1e-5 # 1/K
block = 'concrete'
[]
[thermal_strain_Al]
type = ADComputeThermalExpansionEigenstrain
stress_free_temperature = 300 # arbitrary value
eigenstrain_name = eigenstrain
temperature = T
thermal_expansion_coeff = 2.4e-5 # 1/K
block = 'Al'
[]
# NOTE: This handles thermal expansion by coupling to the displacements
[density_concrete_hd]
type = Density
block = 'concrete_hd'
density = '3524' # kg / m3
[]
[density_concrete]
type = Density
block = 'concrete'
density = '2403' # kg / m3
[]
[density_Al]
type = Density
block = 'Al'
density = '2270' # kg / m3
[]
[]
[Problem]
# No kernels on the water domain
kernel_coverage_check = false
# No materials defined on the water domain
material_coverage_check = false
[]
[Executioner]
type = Steady
solve_type = NEWTON
automatic_scaling = true
petsc_options_iname = '-pc_type -pc_hypre_type -ksp_gmres_restart'
petsc_options_value = 'hypre boomeramg 500'
line_search = none
[]
[Outputs]
exodus = true
[]
(tutorials/shield_multiphysics/inputs/step07_mechanics/step7.i)
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step07_mechanics
moose-opt -i step7.i
Displacements are exaggerated to be visible.
-adaptivity is a method of automatically refining/coarsening the mesh in regions of high/low estimated solution error.
Concentrate degrees of freedom (DOFs) where the error is highest, while reducing DOFs where the solution is already well-captured.
Compute a measure of error using an Indicator
object
Mark an element for refinement or coarsening based on the error using a Marker
object
Mesh adaptivity can be employed in both Steady
and Transient
executioners.
MOOSE employs "self-similar", isotropic refinement patterns: when refining an element is split into elements of the same type.
For example, when using Quad4 elements, four "child" elements are created when the element is refined.
Coarsening happens in reverse, children are deleted and the "parent" element is reactivated.
The original mesh starts at refinement level 0.
Indicators
report an amount of "error" for each element, built-in Indicators
include:
GradientJumpIndicator
Jump in the gradient of a variable across element edges. A good "curvature" indicator that works well over a wide range of problems.
FluxJumpIndicator
Similar to GradientJump
, except that a scalar coefficient (e.g. thermal conductivity) can be provided to produce a physical "flux" quantity.
LaplacianJumpIndicator
Jump in the second derivative of a variable. Only useful for shape functions.
AnalyticIndicator
Computes the difference between the finite element solution and a user-supplied Function
representing the analytic solution to the problem.
After an Indicator
has computed the error for each element, a decision to refine or coarsen elements must be made using a Marker
object.
ErrorFractionMarker
Selects elements based on their contribution to the total error.
ErrorToleranceMaker
Refine if error is greater than a specified value and coarsen if it is less.
ValueThresholdMarker
Refine if variable value is greater than a specific value and coarsen if it is less.
BoxMarker
Refine or coarsen inside or outside a given box.
ComboMarker
Combine several of the above Markers
.
[Adaptivity]
initial_steps = 2
cycles_per_step = 2
marker = marker
initial_marker = marker
max_h_level = 2
[Indicators]
[indicator]
type = GradientJumpIndicator
variable = u
[]
[]
[Markers]
[marker]
type = ErrorFractionMarker
indicator = indicator
coarsen = 0.1
refine = 0.7
[]
[]
[]
(test/tests/adaptivity/cycles_per_step/cycles_per_step.i) @@ -1,6 +1,7 @@
[Mesh]
[fmg]
type = FileMeshGenerator
file = '../step03_boundary_conditions/mesh_in.e'
[]
+ uniform_refine = 0
[]
(- tutorials/shield_multiphysics/inputs/step04_heat_conduction/step4.i)Without modification, running the input will produce the same solution as in Step 4:
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step08_adaptivity
moose-opt -i step8_uniform.i
There are several ways to instigate uniform refinement:
Directly modify the input to change uniform_refine = 0
to uniform_refine = 2
Modify parameter using command-line interface:
moose-opt -i step8_uniform.i Mesh/uniform_refine=2
Use the -r
command-line option:
moose-opt -i step8_uniform.i -r 2
Each refinement increases the number of elements by a factor of
The Adaptivity System is used to perfrom adaptive mesh refinement.
Indicators provide a measure of the error in the simulation, see GradientJumpIndicator.
Markers flag elements for refinement or coarsening, see ValueThresholdMarker
[Adaptivity]
marker = jump_threshold
max_h_level = 2
[Indicators]
[temperature_jump]
type = GradientJumpIndicator
variable = T
scale_by_flux_faces = true
[]
[]
[Markers]
[jump_threshold]
type = ValueThresholdMarker
coarsen = 0.3
variable = temperature_jump
refine = 2
block = 'concrete_hd concrete Al'
[]
[]
[]
(tutorials/shield_multiphysics/inputs/step08_adaptivity/step8_adapt.i)
moose-opt -i step8_adapt.i
Aggregate values based on simulation data are useful for understanding the simulation as well as defining coupling values across coupled equations.
There are two main systems for aggregating data: Postprocessors and VectorPostprocessors.
All MOOSE Postprocessors are based on the UserObject System, so we will begin with an introduction there.
A system for defining an arbitrary interface between MOOSE objects.
The UserObject system provides data and calculation results to other MOOSE objects.
Postprocessors are UserObjects that compute a single scalar value.
VectorPostprocessors are UserObjects that compute vectors of data.
UserObjects define their own interface, which other MOOSE objects can call to retrieve data.
UserObjects are computed at specified "times" by the execute_on option in the input file:
execute_on = 'initial timestep_end'
execute_on = linear
execute_on = nonlinear
execute_on = 'timestep_begin final failed'
They can be restricted to specific blocks, sidesets, and nodesets
A system for computing a "reduction" or "aggregation" calculation based on the solution variables that results in a single scalar value.
The operation defined in the ::compute...
routine is applied at various locations depending on the Postprocessor type.
ElementPostprocessor: operates on each element
NodalPostprocessor: operates on each node
SidePostprocessor: operates on each element side on a boundary
InternalSidePostprocessor: operates on internal element sides
InterfacePostprocessor: operates on each element side on subdomain interfaces
GeneralPostprocessor: operates once per execution
MOOSE includes a large number built-in Postprocessors
: ElementAverageValue
, SideAverageValue
, ElementL2Error
, ElementH1Error
, and many more
By default, Postprocessors
will output to a formatted table on the screen and optionally using the [Outputs]
block be stored in CSV file.
[Output]
csv = true
[]
A system for "reduction" or "aggregation" calculations based on the solution variables that results in one or many vectors of values.
MOOSE includes a large number built-in VectorPostprocessors
: NodalValueSampler
, LineValueSampler
, PointValueSampler
, and many more.
VectorPostprocessors
output is optionally enabled using the [Outputs]
block. A CSV file for each vector and timestep will be created.
[Output]
csv = true
[]
Postprocessors and VectorPostprocessors in this example:
!include ../step08_adaptivity/step8_adapt.i
[Postprocessors]
[num_elements]
type = NumElements
execute_on = 'INITIAL TIMESTEP_END'
[]
[max_temperature_concrete]
type = NodalExtremeValue
variable = T
block = 'concrete_hd concrete'
value_type = max
execute_on = 'INITIAL TIMESTEP_END'
[]
[water_heat_flux]
type = ADSideDiffusiveFluxIntegral
variable = T
boundary = water_boundary_inwards
diffusivity = 'thermal_conductivity'
[]
[]
[VectorPostprocessors]
[temperature_sample_x]
type = LineValueSampler
num_points = 50
start_point = '1.275 4.625 0.8'
end_point = '5.275 4.625 0.8'
variable = T
sort_by = x
execute_on = 'INITIAL TIMESTEP_END'
[]
[temperature_sample_y]
type = LineValueSampler
num_points = 50
start_point = '3.275 0.825 0.8'
end_point = '3.275 8.425 0.8'
variable = T
sort_by = y
execute_on = 'INITIAL TIMESTEP_END'
[]
[]
[Outputs]
csv = true
[]
(tutorials/shield_multiphysics/inputs/step09_postprocessing/step9.i)
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step09_postprocessing
moose-opt -i step9.i
Then plot from the CSV
file in python, excel, paraview etc
To have non-zero values at t=0
, the postprocessors must be executed on INITIAL
.
Postprocessor Values:
+----------------+--------------------------+----------------+----------------+
| time | max_temperature_concrete | num_elements | water_heat_flux|
+----------------+--------------------------+----------------+----------------+
| 0.000000e+00 | 3.000000e+02 | 1.792000e+04 | 0.000000e+00 |
| 4.320000e+04 | 3.226249e+02 | 1.792000e+04 | 5.445889e+03 |
| 8.640000e+04 | 3.348682e+02 | 2.436000e+04 | 7.445028e+03 |
| 1.296000e+05 | 3.416370e+02 | 3.379600e+04 | 8.692277e+03 |
| 1.728000e+05 | 3.464075e+02 | 3.491600e+04 | 9.406888e+03 |
| 2.160000e+05 | 3.500610e+02 | 3.519600e+04 | 9.912671e+03 |
+----------------+--------------------------+----------------+----------------+
#!/usr/bin/env python3
import os
import shutil
import mooseutils
import plotly.graph_objects as go
def run():
exec = shutil.which("moose-opt") or mooseutils.find_moose_executable_recursive()
if not exec:
raise AssertionError("Cannot find a valid MOOSE executable.")
mooseutils.run_executable(exec, ["-i", "step9.i"])
def plot():
pp_data = mooseutils.PostprocessorReader('step9_out.csv')
times = pp_data["time"]
time_hrs = times / 3600
fig = go.Figure(
data=go.Scatter(
x=time_hrs,
y=pp_data["max_temperature_concrete"] - 273,
)
)
fig.update_layout(
xaxis=dict(title=dict(text="Time (hours)")),
yaxis=dict(title=dict(text="Concrete Max Temperature (C)")),
)
fig.show()
fig = go.Figure(
data=go.Scatter(
x=time_hrs,
y=pp_data["water_heat_flux"] / 1000,
)
)
fig.update_layout(
xaxis=dict(title=dict(text="Time (hours)")),
yaxis=dict(title=dict(text="Water heat flux (kW/m2)")),
)
fig.show()
vpp_data_x = mooseutils.VectorPostprocessorReader('step9_out_temperature_sample_x_*.csv')
vpp_data_y = mooseutils.VectorPostprocessorReader('step9_out_temperature_sample_y_*.csv')
figx = go.Figure()
figy = go.Figure()
for it in vpp_data_x.times()[::2]:
vpp_data_x.update(it)
vpp_data_y.update(it)
label = f"Time = {int(time_hrs[it] / 24)} days"
figx.add_trace(go.Scatter(x=vpp_data_x["x"], y=vpp_data_x["T"] - 273, name=label))
figy.add_trace(go.Scatter(x=vpp_data_y["y"], y=vpp_data_y["T"] - 273, name=label))
figx.update_layout(
xaxis=dict(title=dict(text="x (m)")),
yaxis=dict(title=dict(text="Temperature (C)")),
)
figy.update_layout(
xaxis=dict(title=dict(text="y (m)")),
yaxis=dict(title=dict(text="Temperature (C)")),
)
figx.show()
figy.show()
if __name__ == '__main__':
if not os.path.exists('step9_out.csv'):
run()
plot()
(tutorials/shield_multiphysics/inputs/step09_postprocessing/step9.py)Ensure the MOOSE python utilities are in the PYTHONPATH
:
export PYTHONPATH=$PYTHONPATH:$HOME/projects/moose/python
python step9.py
We have only solved the heat equation in the concrete until now. We want to model natural circulation in the water tank inside the shield.
Conservation of Mass:
(17)Conservation of momentum:
(18)Conservation of Energy:
(19)where is the fluid velocity, is fluid viscosity, is the pressure, is the density, is the gravity vector, and is the temperature.
(1) Flexible: Works with arbitrary mixed cell types (even if they are mixed in the same problem)
(2) Inherently conservative: Uses the integral form of the PDEs. This makes it perfect for applications where conservation laws need to be respected (fluid flows).
(3) Accurate: Can be second-order accurate in space. Higher order possible, but not common.
(4) Robust: It is the current standard for most commercial (STAR-CCM+, ANSYS-Fluent, etc.) and major open-source (OpenFOAM, etc.) CFD codes.
(5) Rich literature: Has been researched for decades.
First, domain is split into cells ().
In MOOSE, the cell-centered finite volume approximation (Moukalled et al. (2016) and Jasak (1996)) is used due to the fact that it supports both unstructured and structured meshes:
Constant over the cells (value at cell centroid): if
Constant over the faces (value at face centroid): if
Error analysis is done using Taylor expansions, we prefer second-order discretization/interpolation schemes.
(1) Write the strong form of the equation:
(2) Integrate the equation over the domain :
(3) Split the integral into different terms:
Split into cell-wise integrals:
Use the finite volume approximation (on cell C):
For a finite volume variable, there is only one quadrature point and it is the cell centroid. This form is very similar to the one used in the FEM routines (We always use a test function of 1!).
ADReal
FVReaction::computeQpResidual()
{
return _rate * _u[_qp];
}
(framework/src/fvkernels/FVReaction.C)Othogonal scenario: ( and are parallel)
Non-othogonal scenario:
Split into cell-wise integrals and use the divergence theorem:
On an internal cell (let's say on cell C):
for orthogonal scenario: (cheap and accurate)
for nonorthogonal scenario:
The surface normal () is expanded into a -parallel () and a remaining vector ():
on the right hand side is computed using the interpolation of cell gradients (next slide)
Basic interpolation scheme:
Cell gradients can be estimated using the Green-Gauss theorem:
At the same time:
From the two equations:
(Alternative approaches: least-squares, node-based interpolation, skewness-corrected interpolation)
ADReal
FVDiffusion::computeQpResidual()
{
using namespace Moose::FV;
const auto state = determineState();
auto dudn = gradUDotNormal(state, _correct_skewness);
ADReal coeff;
// If we are on internal faces, we interpolate the diffusivity as usual
if (_var.isInternalFace(*_face_info))
{
const ADReal coeff_elem = _coeff(elemArg(), state);
const ADReal coeff_neighbor = _coeff(neighborArg(), state);
// If the diffusion coefficients are zero, then we can early return 0 (and avoid warnings if we
// have a harmonic interpolation)
if (!coeff_elem.value() && !coeff_neighbor.value())
return 0;
interpolate(_coeff_interp_method, coeff, coeff_elem, coeff_neighbor, *_face_info, true);
}
// Else we just use the boundary values (which depend on how the diffusion
// coefficient is constructed)
else
{
const auto face = singleSidedFaceArg();
coeff = _coeff(face, state);
}
return -1 * coeff * dudn;
}
(framework/src/fvkernels/FVDiffusion.C)Split to integral to cell-wise integrals and use the divergence theorem:
On an internal cell (let's say on cell C), assuming that is constant:
Common interpolation method for :
Upwind
(Weighted) Average
TVD limited schemes: van Leer, Minmod
Unifies the evaluation of Functions, Variables, and certain Materials on faces, elements, quadrature points, etc.
Can be used to easily evaluate gradients on elements/faces as well.
They require an argument that contains information on the way the value should be obtained:
ElemArg
: used to evaluate on an element, contains a link to the underlying element in libMesh
FaceArg
: used to evaluate on a face, has to contains information about the face, surrounding elements and the interpolation method
auto elem_arg = ElemArg{elem.get(), false};
(unit/src/MooseFunctorTest.C)auto face = FaceArg({&fi, LimiterType::CentralDifference, true, false, nullptr, nullptr});
(unit/src/MooseFunctorTest.C) test_gradient(face);
(unit/src/MooseFunctorTest.C)ADReal
FVAdvection::computeQpResidual()
{
const auto state = determineState();
const auto & limiter_time = _subproblem.isTransient()
? Moose::StateArg(1, Moose::SolutionIterationType::Time)
: Moose::StateArg(1, Moose::SolutionIterationType::Nonlinear);
const bool elem_is_upwind = _velocity * _normal >= 0;
const auto face = makeFace(*_face_info,
Moose::FV::limiterType(_advected_interp_method),
elem_is_upwind,
false,
&limiter_time);
ADReal u_interface = _var(face, state);
return _normal * _velocity * u_interface;
}
(framework/src/fvkernels/FVAdvection.C)a=1.1
diff=1.1
[Mesh]
[./gen_mesh]
type = GeneratedMeshGenerator
dim = 2
xmin = 2
xmax = 3
ymin = 0
ymax = 1
nx = 2
ny = 2
elem_type = TRI3
[../]
[]
[Variables]
[v]
type = MooseVariableFVReal
initial_condition = 1
[]
[]
[FVKernels]
[advection]
type = FVAdvection
variable = v
velocity = '${a} ${fparse 2*a} 0'
advected_interp_method = 'average'
[]
[reaction]
type = FVReaction
variable = v
[]
[diff_v]
type = FVDiffusion
variable = v
coeff = ${diff}
[]
[body_v]
type = FVBodyForce
variable = v
function = 'forcing'
[]
[]
[FVBCs]
[exact]
type = FVFunctionDirichletBC
boundary = 'left right top bottom'
function = 'exact'
variable = v
[]
[]
[Functions]
[exact]
type = ParsedFunction
expression = 'sin(x)*cos(y)'
[]
[forcing]
type = ParsedFunction
expression = '-2*a*sin(x)*sin(y) + a*cos(x)*cos(y) + 2*diff*sin(x)*cos(y) + sin(x)*cos(y)'
symbol_names = 'a diff'
symbol_values = '${a} ${diff}'
[]
[]
[Executioner]
type = Steady
solve_type = 'NEWTON'
[]
[Outputs]
csv = true
[]
[Postprocessors]
[error]
type = ElementL2Error
variable = v
function = exact
outputs = 'console csv'
execute_on = 'timestep_end'
[]
[h]
type = AverageElementSize
outputs = 'console csv'
execute_on = 'timestep_end'
[]
[]
(test/tests/fvkernels/mms/non-orthogonal/advection-diffusion-reaction.i)Focuses on coarse-mesh applications
Supports free and porous medium flows
Supports incompressible, weakly-compressible and (some) compressible simulations
Under intense development
To the right: cooling of a spent fuel cask with natural circulation (Results by Sinan Okyay)
We introduce the Boussinesq approximation:
We set up the flow equations:
cp_water_multiplier = 5e-2
mu_multiplier = 1
power = '${fparse 5e4 / 144}'
[Mesh]
[fmg]
type = FileMeshGenerator
file = 'mesh2d_in.e'
[]
[]
[Variables]
[vel_x]
type = INSFVVelocityVariable
block = 'water'
initial_condition = 1e-4
[]
[vel_y]
type = INSFVVelocityVariable
block = 'water'
initial_condition = 1e-4
[]
[pressure]
type = INSFVPressureVariable
block = 'water'
initial_condition = 1e5
[]
[T_fluid]
type = INSFVEnergyVariable
initial_condition = 300
block = 'water'
scaling = 1e-05
[]
[lambda]
type = MooseVariableScalar
family = SCALAR
order = FIRST
[]
[]
[AuxVariables]
# This isn't used in simulation, but useful for visualization
[vel_z]
type = INSFVVelocityVariable
block = 'water'
initial_condition = 0
[]
[mixing_length]
block = 'water'
order = CONSTANT
family = MONOMIAL
fv = true
[]
[]
[GlobalParams]
velocity_interp_method = rc
rhie_chow_user_object = ins_rhie_chow_interpolator
rho = rho
[]
[FVKernels]
[water_ins_mass_advection]
type = INSFVMassAdvection
advected_interp_method = upwind
block = water
variable = pressure
[]
[water_ins_mass_pressure_pin]
type = FVPointValueConstraint
lambda = lambda
phi0 = 1e5
point = '1 3 0'
variable = pressure
[]
[water_ins_momentum_time_vel_x]
type = INSFVMomentumTimeDerivative
block = water
momentum_component = x
variable = vel_x
[]
[water_ins_momentum_time_vel_y]
type = INSFVMomentumTimeDerivative
block = water
momentum_component = y
variable = vel_y
[]
[water_ins_momentum_advection_x]
type = INSFVMomentumAdvection
advected_interp_method = upwind
block = water
momentum_component = x
variable = vel_x
characteristic_speed = 0.01
[]
[water_ins_momentum_advection_y]
type = INSFVMomentumAdvection
advected_interp_method = upwind
block = water
momentum_component = y
variable = vel_y
characteristic_speed = 0.1
[]
[water_ins_momentum_diffusion_x]
type = INSFVMomentumDiffusion
block = water
momentum_component = x
mu = mu
variable = vel_x
[]
[water_ins_momentum_diffusion_y]
type = INSFVMomentumDiffusion
block = water
momentum_component = y
mu = mu
variable = vel_y
[]
[water_ins_momentum_pressure_x]
type = INSFVMomentumPressure
block = water
momentum_component = x
pressure = pressure
variable = vel_x
[]
[water_ins_momentum_pressure_y]
type = INSFVMomentumPressure
block = water
momentum_component = y
pressure = pressure
variable = vel_y
[]
[water_ins_momentum_gravity_z]
type = INSFVMomentumGravity
block = water
gravity = '0 -9.81 0'
momentum_component = y
variable = vel_y
[]
[water_ins_momentum_boussinesq_z]
type = INSFVMomentumBoussinesq
T_fluid = T_fluid
alpha_name = alpha
block = water
gravity = '0 -9.81 0'
momentum_component = y
ref_temperature = 300
rho = 955.7
variable = vel_y
[]
# Energy conservation equation
[water_ins_energy_time]
type = INSFVEnergyTimeDerivative
block = water
dh_dt = dh_dt
rho = rho
variable = T_fluid
[]
[water_ins_energy_advection]
type = INSFVEnergyAdvection
advected_interp_method = upwind
block = water
variable = T_fluid
[]
[water_ins_energy_diffusion_all]
type = FVDiffusion
block = water
coeff = k
variable = T_fluid
[]
# Turbulence
[water_ins_viscosity_rans_x]
type = INSFVMixingLengthReynoldsStress
variable = vel_x
mixing_length = mixing_length
momentum_component = 'x'
u = vel_x
v = vel_y
[]
[water_ins_viscosity_rans_y]
type = INSFVMixingLengthReynoldsStress
variable = vel_y
mixing_length = mixing_length
momentum_component = 'y'
u = vel_x
v = vel_y
[]
[water_ins_energy_rans]
type = WCNSFVMixingLengthEnergyDiffusion
variable = T_fluid
cp = cp
mixing_length = mixing_length
schmidt_number = 1
u = vel_x
v = vel_y
[]
[]
[AuxKernels]
[mixing_length]
type = WallDistanceMixingLengthAux
variable = mixing_length
walls = 'water_boundary inner_cavity_water'
execute_on = 'initial'
[]
[]
[FunctorMaterials]
[water]
type = ADGenericFunctorMaterial
block = 'water'
prop_names = 'rho k cp mu alpha_wall'
prop_values = '955.7 0.6 ${fparse cp_water_multiplier * 4181} ${fparse 7.98e-4 * mu_multiplier} 30'
[]
[boussinesq_params]
type = ADGenericFunctorMaterial
prop_names = 'alpha '
prop_values = '2.9e-3'
[]
[water_ins_enthalpy_material]
type = INSFVEnthalpyFunctorMaterial
block = water
cp = cp
execute_on = ALWAYS
outputs = none
temperature = T_fluid
[]
[total_viscosity]
type = MixingLengthTurbulentViscosityFunctorMaterial
u = 'vel_x'
v = 'vel_y'
mixing_length = mixing_length
mu = mu
[]
[]
[FVBCs]
[vel_x_water_boundary]
type = INSFVNoSlipWallBC
boundary = 'water_boundary inner_cavity_water'
function = 0
variable = vel_x
[]
[vel_y_water_boundary]
type = INSFVNoSlipWallBC
boundary = 'water_boundary inner_cavity_water'
function = 0
variable = vel_y
[]
[T_fluid_inner_cavity]
type = FVFunctorNeumannBC
boundary = inner_cavity_water
functor = ${power}
variable = T_fluid
[]
[T_fluid_water_boundary]
type = FVFunctorConvectiveHeatFluxBC
boundary = water_boundary
variable = T_fluid
T_bulk = T_fluid
T_solid = 300
heat_transfer_coefficient = 600
is_solid = false
[]
[]
[UserObjects]
[ins_rhie_chow_interpolator]
type = INSFVRhieChowInterpolator
pressure = 'pressure'
u = 'vel_x'
v = 'vel_y'
block = 'water'
[]
[]
[Problem]
kernel_coverage_check = false
[]
[Executioner]
type = Transient
solve_type = NEWTON
automatic_scaling = true
off_diagonals_in_auto_scaling = true
line_search = none
# Direct solve works for everything small enough
petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_mat_solver_package'
petsc_options_value = 'lu NONZERO superlu_dist'
nl_abs_tol = 1e-8
nl_max_its = 10
l_max_its = 3
steady_state_tolerance = 1e-12
steady_state_detection = true
normalize_solution_diff_norm_by_dt = false
start_time = -1
dtmax = 100
[TimeStepper]
type = FunctionDT
function = 'if(t < 1, 0.1, t / 10)'
[]
[]
[Outputs]
exodus = true
[]
(tutorials/shield_multiphysics/inputs/step10_finite_volume/step10.i)While we can run 3D cases unconverged on a laptop, it is also clear the turn around on finding issues is too long. We switch to 2D:
[Mesh]
[bulk]
type = CartesianMeshGenerator
dim = 2
dx = '0.5 0.75 2.0'
dy = '0.5 0.3 0.025 3.6 0.025 0.3 0.5'
ix = '16 24 64'
iy = '16 10 1 112 1 10 16'
subdomain_id = '
0 0 0
0 2 1
0 2 3
0 2 4
0 2 3
0 1 1
0 0 0
'
[]
[hollow_concrete]
type = BlockDeletionGenerator
input = bulk
block = 4
[]
[rename_blocks]
type = RenameBlockGenerator
input = hollow_concrete
old_block = '0 1 2 3'
new_block = 'concrete_hd concrete water Al'
[]
[add_concrete_outer_boundary]
type = RenameBoundaryGenerator
input = rename_blocks
old_boundary = 'left right bottom top'
new_boundary = 'air_boundary symmetry ground air_boundary'
[]
[add_water_concrete_interface]
type = SideSetsBetweenSubdomainsGenerator
input = add_concrete_outer_boundary
primary_block = 'water water water'
paired_block = 'concrete_hd concrete Al'
new_boundary = 'water_boundary'
[]
[add_water_concrete_interface_inwards]
type = SideSetsBetweenSubdomainsGenerator
input = add_water_concrete_interface
primary_block = 'concrete_hd concrete Al'
paired_block = 'water water water'
new_boundary = 'water_boundary_inwards'
[]
[add_inner_cavity_solid]
type = SideSetsAroundSubdomainGenerator
input = add_water_concrete_interface_inwards
block = Al
new_boundary = 'inner_cavity_solid'
include_only_external_sides = true
[]
[add_inner_cavity_water]
type = SideSetsAroundSubdomainGenerator
input = add_inner_cavity_solid
block = water
new_boundary = 'inner_cavity_water'
include_only_external_sides = true
[]
[]
(tutorials/shield_multiphysics/inputs/step10_finite_volume/mesh2d.i)To make sure the convergence criterion is fairly applied to all equations, the non-linear variables should be on the same scale.
Making equations non-dimensional is a common technique to achieve this. But this is not typically done in MOOSE, where modelers have direct access to dimensionalized quantities.
MOOSE includes the ability to either manually or automatically scale non-linear variables.
moose-opt -i mesh2d.i --mesh-only
moose-opt -i step10.i
Most mistakes in an input file will cause wrong results, usually affecting convergence of the solve as well. We cover here two common problems:
Input file mistakes and how to find them
Non-convergence of the solver
If a careful review of the input does not find the error, the next thing to pay attention to is the simulation log.
Are there any warnings? By default MOOSE will not error on warnings
Are there any unused parameters? They could be misspelled!
If that does work, it is time to examine how the simulation evolves in MOOSE
By default, MOOSE outputs on the end of timesteps
[Outputs]
execute_on = TIMESTEP_END
We can change this parameter to output as often as linear iterations! We make sure to output material properties as well, in case the problem lies there:
[Outputs]
[exo] # filename suffix
type = Exodus
execute_on = 'LINEAR TIMESTEP_END'
output_material_properties = true
[]
[]
Add any output you need to understand the root cause!
To look for an issue during setup, we can list the objects created by MOOSE for numerous systems. For example, for material properties,
[Debug]
show_material_props = true
[]
For a general log on the entire setup:
[Debug]
show_actions = true
[]
To look for an issue during the execution,
[Debug]
show_execution_order = ALWAYS
[]
This will output to the console, the execution of all MOOSE's objects, in their respective nodal/elemental/side loops on the mesh.
A comprehensive list of techniques is available in the documentation
First, you should diagnose the non-convergence by printing the residuals for all variables:
[Debug]
show_var_residual_norms = true
[]
You can then identify which variable is not converging. Equation scaling issues have been covered earlier. Let's explore two other common causes:
initialization
bad mesh
Make sure to initialize every nonlinear variable using the [ICs]
block. To check initialization, use the Exodus output:
[Outputs]
exodus = true
execute_on = INITIAL
[]
Meshing is hard. We have some tools to help in the MeshGenerator system but generally you should:
visually inspect your mesh. Look for unsupported features: non-conformality (except from libMesh refinement), overlapping cells...
use the MeshDiagnosticsGenerator and turn on the relevant checks
use show_info = true
in the FileMeshGenerator and verify that the output is as expected
replace your mesh with a simple MOOSE-generated rectangular mesh to check if the mesh is at fault
Documentation for every object
GitHub discussions forum : please follow the guidelines before posting
We want to
Couple the solid heat conduction solve with the fluid solve and
Study the effects of the local environment on sensors placed in the shield.
A system for performing multiple simulations within a main simulation.
MOOSE was originally created to solve fully-coupled systems of PDEs, but not all systems need to be/are fully coupled:
Multiscale systems are generally loosely coupled between scales
Systems with both fast and slow physics can be decoupled in time
Simulations involving input from external codes may be solved
The MultiApp system creates simulations of loosely (or tightly) coupled systems of fully-coupled equations
Loosely-Coupled
Each physics solved with a separate linear/nonlinear solve.
Data exchange once per timestep (typically)
Tightly-Coupled / Picard
Each physics solved with a separate linear/nonlinear solve.
Data is exchanged and physics re-solved until “convergence”
Fully-Coupled
All physics solved for in one linear/nonlinear solve
Example scheme (implicit-explicit)
Each "app" is considered to be a solve that is independent, and there is always a "main" that is driving the simulation
The "main" (or "parent") app can have any number of MultiApp
objects
Each MultiApp
can represent many sub-applications ("sub-apps" or "child" apps)
Each sub-app can solve for different physics from the main application
A sub-app can be another MOOSE application or could be an external application
A sub-app can have MultiApps, thus create a multi-level solve
MultiApp objects are declared in the [MultiApps]
block
app_type
The name of the MooseApp
derived application to run (e.g., "AnimalApp")
positions
List of 3D coordinates describing the offset of the sub-application into the physical space of the main application
execute_on
Allows control when sub-applications are executed: INITIAL, LINEAR, NONLINEAR, TIMESTEP_BEGIN, TIMESTEP_END
input_files
One input file can be supplied for all the sub-apps or a file can be provided for each
[MultiApps]
[micro]
type = TransientMultiApp
app_type = DarcyThermoMechApp
positions = '0.01285 0.0 0
0.01285 0.0608 0
0.01285 0.1216 0
0.01285 0.1824 0
0.01285 0.2432 0
0.01285 0.304 0'
input_files = step10_micro.i
execute_on = 'timestep_end'
[]
[]
(tutorials/darcy_thermo_mech/step10_multiapps/problems/step10.i)The MultiApp system is designed for efficient parallel execution of hierarchical problems.
The main application utilizes all processors
The processors are split among each sub-apps within each MultiApp and are run simultaneously
Multiple MultiApps will be executed one after another
A system to move data to and from the "parent application" and "sub-applications" of a MultiApp.
New Feature: Transfers can now send data between sub-applications. We refer to this capability as 'siblings' transfer.
Transferred data typically is received by the Auxiliary and Postprocessor systems.
The data on the receiving application should couple to these values in the normal way and each sub-application should be able to solve on its own.
Fields can be transferred between applications using a variety of interpolation algorithms.
The direction of the transfer is specified by giving the from_multi_app
or to_multi_app
parameter.
The source field is evaluated at the destination points (generally nodes or element centroids, depending on the receiving variable type).
The evaluations are then put into the receiving AuxVariable
field specified by the variable
parameter.
GeneralField
versions of each transfer are implemented using a different algorithm and may be preferred as they support more features.
[Transfers]
[from_sub]
source_variable = sub_u
variable = transferred_u
type = MultiAppGeneralFieldShapeEvaluationTransfer
from_multi_app = sub
execute_on = 'initial timestep_end'
# Test features non-overlapping meshes
error_on_miss = false
[]
[elemental_from_sub]
source_variable = sub_u
variable = elemental_transferred_u
type = MultiAppGeneralFieldShapeEvaluationTransfer
from_multi_app = sub
# Test features non-overlapping meshes
error_on_miss = false
[]
[]
(test/tests/transfers/multiapp_mesh_function_transfer/exec_on_mismatch.i)Many UserObjects
compute spatially-varying data that is not associated directly with a mesh. For example, local pin-wise averages of a power variable.
Any UserObject
can override Real spatialValue(Point &)
to provide a value given a point in space
A UserObjectTransfer
can sample this spatially-varying data from one app and put the values into an AuxVariable
in another
A GeneralField
versions of this transfer is implemented using a different algorithm and may be preferred as it is more feature-complete.
[Transfers]
[layered_transfer_to_sub_app]
type = MultiAppUserObjectTransfer
user_object = main_uo
variable = sub_app_var
to_multi_app = sub_app
displaced_target_mesh = true
[]
[layered_transfer_from_sub_app]
type = MultiAppUserObjectTransfer
user_object = sub_app_uo
variable = from_sub_app_var
from_multi_app = sub_app
displaced_source_mesh = true
[]
[]
(test/tests/transfers/multiapp_userobject_transfer/3d_1d_parent.i)A Postprocessor or a scalar variable transfer allows a transfer of scalar values between applications
When transferring to a MultiApp
, the value can either be put into a Postprocessor
value or can be put into a constant AuxVariable
field - for example, the main app variable value at the position of the child application can be stored in a postprocessor
When transferring from a MultiApp
to the parent application, the Postprocessor
values from all the sub-apps can be interpolated to form an auxiliary field on the parent application
[Transfers]
[pp_transfer]
type = MultiAppPostprocessorTransfer
to_multi_app = pp_sub
from_postprocessor = average
to_postprocessor = from_parent
[]
[]
(test/tests/transfers/multiapp_postprocessor_transfer/parent.i)Three inputs representing each region/physics:
Solid heat conduction: step11_2d_heat_conduction.i
Thermal fluids: step11_2d_fluid.i
Sensor response: step11_local.i
Primary difference from the previous step is the addition of the T_solid
auxiliary variable, which is used as the "container" for solid heat-conduction app to transfer its solution into.
@@ -1,26 +1,31 @@
[AuxVariables]
# This isn't used in simulation, but useful for visualization
[vel_z]
type = INSFVVelocityVariable
block = 'water'
initial_condition = 0
[]
[mixing_length]
block = 'water'
order = CONSTANT
family = MONOMIAL
fv = true
[]
+ # This is the variable that is transferred from the main app
+ [T_solid]
+ block = 'concrete_hd concrete Al'
+ initial_condition = 300
+ []
[]
[FVBCs]
[T_fluid_water_boundary]
type = FVFunctorConvectiveHeatFluxBC
boundary = water_boundary
variable = T_fluid
T_bulk = T_fluid
- T_solid = 300
+ T_solid = T_solid
heat_transfer_coefficient = 600
is_solid = false
[]
[]
(- tutorials/shield_multiphysics/inputs/step10_finite_volume/step10.i)[AuxVariables]
[T_fluid]
type = INSFVEnergyVariable
initial_condition = 300
block = 'water'
[]
[]
[MultiApps]
[fluid]
# For pseudo-transient
type = TransientMultiApp
# For steady-state fixed-point iteration
# type = FullSolveMultiApp
input_files = step11_2d_fluid.i
execute_on = 'TIMESTEP_END'
# Pass in parameter values as if from command line
cli_args = 'power=${power}'
[]
[]
[Transfers]
[send_T_solid]
type = MultiAppCopyTransfer
to_multi_app = fluid
source_variable = T
variable = T_solid
[]
[recv_T_fluid]
type = MultiAppCopyTransfer
from_multi_app = fluid
source_variable = T_fluid
variable = T_fluid
to_blocks = 'water'
from_blocks = 'water'
[]
[]
(tutorials/shield_multiphysics/inputs/step11_multiapps/step11_2d_heat_conduction.i)[Mesh]
# We make a 3D sphere, but really this could be done in 1D
[sphere]
type = SphereMeshGenerator
radius = 10
nr = 3
n_smooth = 10
[]
# Dimensions of each layer are not realistic
[HDPE_inner]
type = ParsedSubdomainMeshGenerator
input = 'sphere'
combinatorial_geometry = 'x*x + y*y + z*z < 2*2'
block_id = 1
[]
[boron_inner]
type = ParsedSubdomainMeshGenerator
input = 'HDPE_inner'
combinatorial_geometry = '(x*x + y*y + z*z > 2*2) & (x*x + y*y + z*z < 3*3)'
block_id = 2
[]
[HDPE_mid]
type = ParsedSubdomainMeshGenerator
input = 'boron_inner'
combinatorial_geometry = '(x*x + y*y + z*z > 3*3) & (x*x + y*y + z*z < 6*6)'
block_id = 3
[]
[boron_mid]
type = ParsedSubdomainMeshGenerator
input = 'HDPE_mid'
combinatorial_geometry = '(x*x + y*y + z*z > 6*6) & (x*x + y*y + z*z < 7*7)'
block_id = 4
[]
[HDPE_outer]
type = ParsedSubdomainMeshGenerator
input = 'boron_mid'
combinatorial_geometry = 'x*x + y*y + z*z > 7*7'
block_id = 5
[]
[rename]
type = RenameBlockGenerator
input = 'HDPE_outer'
old_block = '1 2 3 4 5'
new_block = 'HDPE_inner boron_inner HDPE_mid boron_mid HDPE_outer'
[]
[rename_boundary]
type = RenameBoundaryGenerator
input = 'rename'
old_boundary = '0'
new_boundary = 'outer'
[]
# length_unit = 0.01
[scale]
type = TransformGenerator
input = rename_boundary
transform = SCALE
vector_value = '0.01 0.01 0.01'
[]
[]
[Variables]
[T]
initial_condition = 300
[]
[]
# Solve heat equation, with a source from boron absorption
[Kernels]
[conduction]
type = HeatConduction
variable = T
[]
[source]
type = CoupledForce
variable = T
block = 'boron_inner boron_mid'
v = flux
# 2 is our arbitrary value for the group cross section
coef = 2
[]
[]
[BCs]
[outer]
type = PostprocessorDirichletBC
boundary = 'outer'
variable = 'T'
postprocessor = 'T_boundary'
[]
[]
[AuxVariables]
# Received from the main solve
[flux]
initial_condition = 1e5
[]
[]
[Materials]
[hdpe]
type = HeatConductionMaterial
block = 'HDPE_inner HDPE_mid HDPE_outer'
# arbitrary
thermal_conductivity = 10
[]
[boron]
type = HeatConductionMaterial
block = 'boron_inner boron_mid'
# arbitrary
thermal_conductivity = 7
[]
[]
[Executioner]
type = Steady
solve_type = NEWTON
petsc_options_iname = '-pc_type -pc_hypre_type'
petsc_options_value = 'hypre boomeramg'
[]
[Postprocessors]
# Used for boundary condition, received from the main solve
[T_boundary]
type = Receiver
default = 320
[]
# Compute those then send to the main app
[T_hdpe_out]
type = ElementAverageValue
variable = 'T'
block = 'HDPE_outer'
[]
[T_boron_mid]
type = ElementAverageValue
variable = 'T'
block = 'boron_mid'
[]
[T_hdpe_mid]
type = ElementAverageValue
variable = 'T'
block = 'HDPE_mid'
[]
[T_boron_inner]
type = ElementAverageValue
variable = 'T'
block = 'boron_inner'
[]
[T_hdpe_inner]
type = ElementAverageValue
variable = 'T'
block = 'HDPE_inner'
[]
[]
[Outputs]
exodus = true
[]
(tutorials/shield_multiphysics/inputs/step11_multiapps/step11_local.i)[AuxVariables]
[flux]
[InitialCondition]
type = FunctionIC
function = '1e4 * exp(-((x-3.25)^2 + (y-2.225)^2))'
[]
[]
[T_hdpe_inner]
family = MONOMIAL
order = CONSTANT
block = Al
[]
[T_boron_inner]
family = MONOMIAL
order = CONSTANT
block = Al
[]
[]
[MultiApps]
[detectors]
type = FullSolveMultiApp
input_files = 'step11_local.i'
# Create one app at each position
positions_objects = 'detector_positions'
# displace the subapp output to their position in the parent app frame
output_in_position = true
# compute the global temperature first
execute_on = 'TIMESTEP_END'
# Pass in parameter values as if from command line
cli_args = 'Outputs/console=false'
[]
[]
[Transfers]
[send_exterior_temperature]
type = MultiAppVariableValueSamplePostprocessorTransfer
to_multi_app = detectors
source_variable = T
postprocessor = T_boundary
[]
[send_local_flux]
type = MultiAppVariableValueSampleTransfer
to_multi_app = detectors
source_variable = flux
variable = flux
[]
[hdpe_temperature]
type = MultiAppPostprocessorInterpolationTransfer
from_multi_app = detectors
postprocessor = T_hdpe_inner
variable = T_hdpe_inner
[]
[boron_temperature]
type = MultiAppPostprocessorInterpolationTransfer
from_multi_app = detectors
postprocessor = T_boron_inner
variable = T_boron_inner
[]
[]
(tutorials/shield_multiphysics/inputs/step11_multiapps/step11_2d_heat_conduction.i)Before fully coupled simulation, we must make sure each input file runs well separately.
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step11_multiapps
moose-opt -i mesh2d_coarse.i --mesh-only
moose-opt -i step11_local.i
moose-opt -i step11_2d_fluid.i
moose-opt -i step11_2d_heat_conduction.i MultiApps/active='' Transfers/active=''
Sensor temperature field with dummy fixed boundary conditions
moose-opt -i step11_2d_heat_conduction.i
The individual sensor results can be plotted 'in-position' in the global geometry.
Postprocessed quantities can be transferred from the local child app meshes to the global mesh.
Add custom syntax to build objects that are common to all conjugate heat transfer thermal mechanical problems:
Kernels and BCs for solid heat conduction
Objects for solid mechanics
Kernels and BCs for fluid flow
Kernels and BCs for fluid heat transfer
A system for the programmatic creation of simulation objects and input file syntax.
Action recognize syntax such as [Kernels]
or [Outputs]
and perform actions based on them. Many actions simply create an object, using the type
parameter. Other parse parameters in the block and perform the relevant setup steps.
The MOOSE action system operates on tasks, each task is connected to one or many actions. Tasks are ordered based on their dependencies, which are set by the developers. This ensures the correctness of the simulation setup. To see tasks being executed, use Debug/show_actions=true
.
An action designed to build one or many other MooseObjects, such as in the case of the [Kernels]
, [Variables]
, [BCs]
, etc.. blocks.
An action designed to build an entire equation. Solid mechanics, computational fluid dynamics, heat conduction are all implemented as Physics. Depending on the Physics
, it can include only the kernels, or also include boundary conditions and material properties.
[Physics]
[SolidMechanics]
[QuasiStatic]
[all]
# This block adds all of the proper Kernels, strain calculators, and Variables
# for SolidMechanics in the correct coordinate system (autodetected)
add_variables = true
strain = FINITE
eigenstrain_names = eigenstrain
use_automatic_differentiation = true
generate_output = 'vonmises_stress elastic_strain_xx elastic_strain_yy strain_xx strain_yy'
[]
[]
[]
[]
(tutorials/darcy_thermo_mech/step10_multiapps/problems/step10.i)Physics
are meant to facilitate numerous simulation common needs such as:
multi-system simulation setups
preconditioning
initialization from mesh files
interaction with other Physics
, creating the adequate coupling terms
Defines the kernels, the boundary conditions of selected supported types, and some numerical parameters
Physics/HeatConduction/FiniteElement
[Physics]
[HeatConduction]
[FiniteElement]
[concrete]
block = 'concrete_hd concrete Al'
temperature_name = "T"
system_names = 'nl0'
preconditioning = 'none'
# Solve for steady state
# It takes a while to heat up concrete
initial_temperature = 300
transient = false
# Heat conduction boundary conditions can be defined
# inside the HeatConduction physics block
fixed_temperature_boundaries = 'ground'
boundary_temperatures = '300'
heat_flux_boundaries = 'inner_cavity_solid'
# 50 kW from radiation, using real surface
boundary_heat_fluxes = '${power}'
fixed_convection_boundaries = "water_boundary_inwards air_boundary"
fixed_convection_T_fluid = "T_fluid 300"
fixed_convection_htc = "${h_water} 10"
[]
[]
[]
[]
(tutorials/shield_multiphysics/inputs/step12_physics/step12.i)Defines the kernels and some helper materials for computing strain.
Physics/SolidMechanics/QuasiStatic
[Physics]
[SolidMechanics]
[QuasiStatic]
[concrete]
# This block adds all of the proper Kernels, strain calculators, and Variables
# for Solid Mechanics in the correct coordinate system (autodetected)
add_variables = true
strain = FINITE
eigenstrain_names = eigenstrain
use_automatic_differentiation = true
generate_output = 'vonmises_stress elastic_strain_xx elastic_strain_yy strain_xx strain_yy'
block = 'concrete_hd concrete Al'
[]
[]
[]
[]
(tutorials/shield_multiphysics/inputs/step12_physics/step12.i)The flow equations are separated from the conservation of energy in the fluid for readability purposes.
Defines both the kernels and the boundary conditions.
[Physics]
[NavierStokes]
[Flow]
[water]
block = 'water'
system_names = 'flow'
compressibility = 'incompressible'
initial_velocity = '1e-5 1e-5'
initial_pressure = '1e5'
# p only appears in a gradient term, and thus could be offset by any constant
# We pin the pressure to avoid having this nullspace
pin_pressure = true
pinned_pressure_type = POINT-VALUE
pinned_pressure_point = '1 3 0'
pinned_pressure_value = '1e5'
gravity = '0 -9.81 0'
boussinesq_approximation = true
ref_temperature = 300
wall_boundaries = 'water_boundary inner_cavity_water'
momentum_wall_types = 'noslip noslip'
[]
[]
[]
[]
(tutorials/shield_multiphysics/inputs/step12_physics/step12.i)Physics/NavierStokes/FluidHeatTransfer
[Physics]
[NavierStokes]
[FluidHeatTransfer]
[water]
block = 'water'
system_names = 'flow'
initial_temperature = 300
# This is a rough coupling to heat conduction
energy_wall_types = 'convection heatflux'
energy_wall_functors = 'T:${h_water} ${power}'
energy_scaling = 1e-5
[]
[]
[]
[]
(tutorials/shield_multiphysics/inputs/step12_physics/step12.i)Physics/NavierStokes/Turbulence
[Physics]
[NavierStokes]
[Turbulence]
[mixing-length]
block = 'water'
turbulence_handling = 'mixing-length'
coupled_flow_physics = 'water'
fluid_heat_transfer_physics = 'water'
system_names = 'flow'
mixing_length_walls = 'water_boundary inner_cavity_water'
mixing_length_aux_execute_on = 'initial'
[]
[]
[]
[]
(tutorials/shield_multiphysics/inputs/step12_physics/step12.i)First declare the names of the systems to use in the Problem
[Problem]
nl_sys_names = 'nl0 flow'
kernel_coverage_check = false
material_coverage_check = false
[]
(tutorials/shield_multiphysics/inputs/step12_physics/step12.i)then specify those systems in each Physics
.
Multi-system allows for customization of solvers via Preconditioning.
Single Matrix Preconditioner (SMP)
[Preconditioning]
[thermomecha]
type = SMP
nl_sys = 'nl0'
petsc_options_iname = '-pc_type -pc_hypre_type -ksp_gmres_restart'
petsc_options_value = 'hypre boomeramg 500'
[]
[flow]
type = SMP
nl_sys = 'flow'
petsc_options_iname = '-pc_type -pc_factor_shift_type'
petsc_options_value = 'lu NONZERO'
[]
[]
(tutorials/shield_multiphysics/inputs/step12_physics/step12.i)
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step12_physics
moose-opt -i step12.i
A debugger is often more effective than print statements in helping to find bugs
Many debuggers exist: LLDB, GDB, Totalview, ddd, Intel Debugger, etc.
Typically it is best to use a debugger that is associated with your compiler
Here LLDB/GDB are used, both are simple to use and are included in the MOOSE package
A "Segmentation fault," "Segfault," or "Signal 11" error denotes a memory bug (often array access out of bounds).
Segmentation fault: 11
A segfault is a "good" error to have, because a debugger can easily pinpoint the problem.
[Mesh]
file = reactor.e
#Let's assign human friendly names to the blocks on the fly
block_id = '1 2'
block_name = 'fuel deflector'
boundary_id = '4 5'
boundary_name = 'bottom top'
[]
[Variables]
#Use active lists to help debug problems. Switching on and off
#different Kernels or Variables is extremely useful!
active = 'diffused convected'
[diffused]
order = FIRST
family = LAGRANGE
initial_condition = 0.5
[]
[convected]
order = FIRST
family = LAGRANGE
initial_condition = 0.0
[]
[]
[Kernels]
#This Kernel consumes a real-gradient material property from the active material
active = 'convection diff_convected example_diff time_deriv_diffused time_deriv_convected'
[convection]
type = ExampleConvection
variable = convected
[]
[diff_convected]
type = Diffusion
variable = convected
[]
[example_diff]
type = ExampleDiffusion
variable = diffused
coupled_coef = convected
[]
[time_deriv_diffused]
type = TimeDerivative
variable = diffused
[]
[time_deriv_convected]
type = TimeDerivative
variable = convected
[]
[]
[BCs]
[bottom_diffused]
type = DirichletBC
variable = diffused
boundary = 'bottom'
value = 0
[]
[top_diffused]
type = DirichletBC
variable = diffused
boundary = 'top'
value = 5
[]
[bottom_convected]
type = DirichletBC
variable = convected
boundary = 'bottom'
value = 0
[]
[top_convected]
type = NeumannBC
variable = convected
boundary = 'top'
value = 1
[]
[]
[Materials]
[example]
type = ExampleMaterial
block = 'fuel'
diffusion_gradient = 'diffused'
#Approximate Parabolic Diffusivity
independent_vals = '0 0.25 0.5 0.75 1.0'
dependent_vals = '1e-2 5e-3 1e-3 5e-3 1e-2'
[]
[example1]
type = ExampleMaterial
block = 'deflector'
diffusion_gradient = 'diffused'
# Constant Diffusivity
independent_vals = '0 1.0'
dependent_vals = '1e-1 1e-1'
[]
[]
[Executioner]
type = Transient
solve_type = 'PJFNK'
petsc_options_iname = '-pc_type -pc_hypre_type'
petsc_options_value = 'hypre boomeramg'
dt = 0.1
num_steps = 10
[]
[Outputs]
execute_on = 'timestep_end'
exodus = true
[]
(examples/ex21_debugging/ex21.i)
cd ~/projects/moose/examples/ex21_debugging
make -j12
./ex21-opt -i ex21.i
Time Step 0, time = 0
dt = 0
Time Step 1, time = 0.1
dt = 0.1
Segmentation fault: 11
To use a debugger with a MOOSE-based application, it must be compiled in something other than optimized mode (opt); debug (dbg) mode is recommended because it will produce full line number information in stack traces:
cd ~/projects/moose/examples/ex21_debugging
METHOD=dbg make -j12
This will create a "debug version" of an application: ex21-dbg
.
The compiled debug application can be executed using either GDB (gcc) or LLDB (clang):
gdb --args ./ex21-dbg -i ex21.i
lldb -- ./ex21-dbg -i ex21.i
These commands will start the debugger, load the executable, and open the debugger command prompt.
At any prompt in GDB or LLDB, you can type "h" and hit Enter to get help.
Set a "breakpoint" in MPI_Abort
so that the code pauses (maintaining the stack trace):
(lldb) b MPI_Abort
Breakpoint 1: where = libmpi.12.dylib`MPI_Abort, address = 0x000000010b18f460
Run the application, type "r" and hit Enter, and the application will hit the breakpoint:
(lldb) r
Process 77675 launched: './ex21-dbg' (x86_64)
When the application stops, get the backtrace:
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x000000010b18f460 libmpi.12.dylib`MPI_Abort
frame #1: 0x00000001000e5f8c libex21-dbg.0.dylib`MooseArray<double>::operator[](this=0x0000000112919388, i=0) const at MooseArray.h:276
frame #2: 0x00000001000e580b libex21-dbg.0.dylib`ExampleDiffusion::computeQpResidual(this=0x0000000112918a18) at ExampleDiffusion.C:37
frame #3: 0x0000000100486b99 libmoose-dbg.0.dylib`Kernel::computeResidual(this=0x0000000112918a18) at Kernel.C:99
The backtrace shows that in ExampleDiffusion::computeQpResidual()
an attempt was made to access entry 0 of a MooseArray
with 0 entries.
return _coupled_coef[_qp] * Diffusion::computeQpResidual();
There is only one item being indexed on that line: _coupled_coef
; therefore, consider how _coupled_coef
was declared
In ExampleDiffusion.h
, the member variable _coupled_coef
is a VariableValue
that should be declared as a reference:
const VariableValue _coupled_coef;
Not storing this as a reference will cause a copy of the VariableValue
to be made during construction. This copy will never be resized, nor will it ever have values written to it.
#pragma once
#include "Diffusion.h"
class ExampleDiffusion : public Diffusion
{
public:
ExampleDiffusion(const InputParameters & parameters);
static InputParameters validParams();
protected:
virtual Real computeQpResidual() override;
virtual Real computeQpJacobian() override;
/**
* THIS IS AN ERROR ON PURPOSE!
*
* The "&" is missing here!
*
* Do NOT copy this line of code!
*/
const VariableValue _coupled_coef;
};
(examples/ex21_debugging/include/kernels/ExampleDiffusion.h)
#include "ExampleDiffusion.h"
/**
* This function defines the valid parameters for
* this Kernel and their default values
*/
registerMooseObject("ExampleApp", ExampleDiffusion);
InputParameters
ExampleDiffusion::validParams()
{
InputParameters params = Diffusion::validParams();
params.addRequiredCoupledVar(
"coupled_coef", "The value of this variable will be used as the diffusion coefficient.");
return params;
}
ExampleDiffusion::ExampleDiffusion(const InputParameters & parameters)
: Diffusion(parameters), _coupled_coef(coupledValue("coupled_coef"))
{
}
Real
ExampleDiffusion::computeQpResidual()
{
return _coupled_coef[_qp] * Diffusion::computeQpResidual();
}
Real
ExampleDiffusion::computeQpJacobian()
{
return _coupled_coef[_qp] * Diffusion::computeQpJacobian();
}
(examples/ex21_debugging/src/kernels/ExampleDiffusion.C)Restart
Running a simulation that uses data from a previous simulation, using different input files
Recover
Resuming an existing simulation after a premature termination
Solution file
A mesh format containing field data in addition to the mesh (i.e. a normal output file)
Checkpoint
A snapshot of the simulation including all meshes, solutions, and stateful data
N to N
In a restart context, this means the number of processors for the previous and current simulations match
N to M
In a restart context, different numbers of processors may be used for the previous and current simulations
This method is best suited for restarting a simulation when the mesh in the previous simulation exactly matches the mesh in the current simulation and only initial conditions need to be set for one more variables.
This method requires only a valid solution file
MOOSE supports N to M restart when using this method
[Mesh]
# MOOSE supports reading field data from ExodusII, XDA/XDR, and mesh checkpoint files (.e, .xda, .xdr, .cp)
file = previous.e
# This method of restart is only supported on serial meshes
distribution = serial
[]
[Variables/nodal]
family = LAGRANGE
order = FIRST
initial_from_file_var = nodal
initial_from_file_timestep = 10
[]
[AuxVariables/elemental]
family = MONOMIAL
order = CONSTANT
initial_from_file_var = elemental
initial_from_file_timestep = 10
[]
Advanced restart and recovery in MOOSE require checkpoint files
Checkpoints are automatically enabled by default and are output every 1 hour of wall time (customizable interval), but can be disabled with:
[Outputs]
wall_time_checkpoint = false
[]
To enable automatic checkpoints using the default options (every time step, and keep last two) in a simulation simply add the following flag to your input file:
[Outputs]
checkpoint = true
[]
For more control over the checkpoint system, create a sub-block in the input file that will allow you to change the file format, suffix, frequency of output, the number of checkpoint files to keep, etc.
Set num_files
to at least 2 to minimize the chance of ending up with a corrupt restart file
[Outputs]
exodus = true
[out]
type = Checkpoint
time_step_interval = 3
num_files = 2
wall_time_interval = 3600 # seconds
[]
[]
(test/tests/outputs/checkpoint/checkpoint_interval.i)This method is best suited for situations when the mesh from the previous simulation and the current simulation match and the variables and stateful data should be loaded from the pervious simulation.
Support for modifying some variables is supported such as dt
and time_step
. By default, MOOSE will automatically use the last values found in the checkpoint files
Only N to N restarts are supported using this method
[Mesh]
# Serial number should match corresponding Executioner parameter
file = out_cp/0010-mesh.cpr
# This method of restart is only supported on serial meshes
distribution = serial
[]
[Problem]
# Note that the suffix is left off in the parameter below.
restart_file_base = out_cp/LATEST # You may also use a specific number here
[]
It is possible to load and project data onto a different mesh from a solution file usually as an initial condition in a new simulation.
MOOSE supports this through the use of a SolutionUserObject
A simulation that has terminated due to a fault can be recovered simply by using the --recover
command-line flag, but it requires a checkpoint file.
./frog-opt -i input.i --recover
When running a multiapp simulation you do not need to enable checkpoint output in each sub app input file. The parent app stores the restart data for all sub apps in its file.
@@ -1,23 +1,25 @@
[Mesh]
[fmg]
type = FileMeshGenerator
- file = '../step03_boundary_conditions/mesh_in.e'
+ file = 'step13a_base_calc_out.e'
+ use_for_exodus_restart = true
[]
[]
[Variables]
[T]
# Adds a Linear Lagrange variable by default
block = 'concrete_hd concrete Al'
- initial_condition = 300
+ initial_from_file_var = 'T'
[]
[]
[Executioner]
type = Transient
- num_steps = 4
+ start_time = '${units 2 day -> s}'
+ num_steps = 6
dt = '${units 12 h -> s}'
solve_type = NEWTON
petsc_options_iname = '-pc_type -pc_hypre_type'
petsc_options_value = 'hypre boomeramg'
[]
(- tutorials/shield_multiphysics/inputs/step13_restart/step13a_base_calc.i)only variables with initial_from_file_var
set will be initialized
reading exodus files is a replicated operation, meaning the file is loaded by every process in parallel. Use Nemesis files in parallel to reduce memory costs
cd ~/projects/moose/tutorials/shield_multiphysics/inputs/step13_restart
# Generate the initialization file
moose-opt -i step13a_base_calc.i
# Use the exodus file to initialize some variables
moose-opt -i step13b_initialization_from_exodus.i
[Outputs]
exodus = true
checkpoint = true
[]
(tutorials/shield_multiphysics/inputs/step13_restart/step13a_base_calc.i) @@ -1,13 +1,15 @@
[Mesh]
[fmg]
type = FileMeshGenerator
- file = '../step03_boundary_conditions/mesh_in.e'
+ file = 'step13a_base_calc_out_cp/LATEST'
[]
[]
[Problem]
+ # all variables, both nonlinear and auxiliary, are 'restarted'
+ restart_file_base = 'step13a_base_calc_out_cp/LATEST'
# No kernels on the water domain
kernel_coverage_check = false
# No materials on the water domain
material_coverage_check = false
[]
(- tutorials/shield_multiphysics/inputs/step13_restart/step13a_base_calc.i)initial conditions specified in the input override any restarted fields. This must be allowed in the Problem
block to avoid unintentional behavior.
moose-opt -i step13a_base_calc.i
moose-opt -i step13c_restart_from_checkpoint.i
Recover lets us start from the last checkpoint before the simulation stopped.
moose-opt -i step13a_base_calc.i
# Use Ctrl+C / Cmd+C to cancel the calculation
# Recover from the last valid checkpoint
moose-opt -i step13a_base_calc.i --recover
A system for the programmatic creation of simulation objects and input file syntax.
A system for direct calculation of field variables ("AuxVariables") that is designed for postprocessing, coupling, and proxy calculations.
System for computing residual contributions from boundary terms of a PDE.
A system for imposing constraints within a simulation, such as limiting the heat flux across a gap or fixing solution variables across an interface using mortar methods.
A system for programmatically modifying the input parameters of objects during a simulation.
For example, turning objects on and off:
[Controls]
[integral_value]
type = PIDTransientControl
postprocessor = integral
target = 1.5
parameter = 'BCs/left/value'
K_integral = -1
K_proportional = -1
K_derivative = -0.1
execute_on = 'initial timestep_begin'
[]
[]
(test/tests/controls/pid_control/pid_control.i)A system to limit the computed change to the solution during each non-linear iteration to prevent the solver from dramatically changing the solution from one iteration to the next. This may prevent, for example, the solver from attempting to evaluate non-physical values such as negative temperature.
A system for debugging a simulation from the input files. It offers several summaries of the objects used, as well as an execution log of Actions and objects during the simulation.
A system for computing residual contributions for volume terms for the discontinuous Galerkin finite element method.
A system for computing residual calculations from point sources.
A system for defining statistical distribution (e.g., uniform, normal, Weibull) functions for use with the stochastic tools module.
A system for dictating the simulation solving strategy.
Executors
are an experimental system to build composed numerical schemes. Current Executioners
can be replaced with their equivalent Executor
A system for defining analytic expressions based on the spatial location (, , ) and time, .
A Function
can depend an other functions, but not on material properties or variables.
System for computing residual contributions from boundary terms of a PDE using the finite volume method.
Split between finite volume Dirichlet and flux boundary conditions.
System for computing residual contributions from interface terms of a PDE using the finite volume method.
The contribution is usually a flux term, identical on both sides of the interface for conservation.
A system for computing the residual contribution of a term within a PDE using the finite volume method.
Finite volume elemental kernels are typically used for volumetric terms (e.g. source, reaction).
Finite volume flux kernels are used for terms integrated by parts (e.g. diffusion) or various fluxes from neighbor cells (e.g. advection).
A system for locating geometric elements within a simulation such as the nearest node across a gap.
A system for initializing field variables (non-linear and auxiliary) prior to execution of a simulation.
A system for computing an error estimation for use with automatic mesh refinement and coarsening.
A system to assist in coupling different physics across sub-domains, such as setting the flux of two species to be equivalent across a boundary between two domains.
A system for computing the residual contribution from a volumetric term within a PDE using the Galerkin finite element method.
This system is meant for creating custom line searches for use during the non-linear solve.
Line searches determine the update vector between Newton-Krylov solve iterations.
A system for setting status of an element to refine, coarsen, or remain the same for automatic mesh adaptivity.
A system for defining material properties to be used by multiple systems and allow for variable coupling.
A system for defining a finite element / volume mesh.
A system for generating a finite element mesh using successive geometric construction routines such as building a 2D grid and then extruding into 3D space.
A system for performing multiple simulations within a main simulation.
A system for computing a residual contribution of a PDE at nodes within the finite element mesh.
A system for outputting simulation data to the screen or files.
A system for converting input data into MOOSE objects for creating a simulation.
A system for partitioning a finite element mesh for parallel execution of a simulation.
A system for keeping track of the Positions
of objects within the mesh during a simulation. It can be leveraged to spawn MultiApps
at these locations, to group data near these positions for transfers, and for postprocessing around them.
A system for computing a "reduction" or "aggregation" calculation based on the solution variables that results in a single scalar value.
A system for defining the preconditioning matrix for use with the non-linear solver.
A system for predicting the next iteration of a simulation based on previous solution iterates.
A system for defining the numerical systems that comprise a simulation.
A system for defining geometric or algebraic information needed to perform a calculation in parallel.
This information is then "ghosted", which means it is replicated across all the processes that need it. The information is often ghosted in "layers", for the first few elements near a process' domain boundary.
An advanced system for postprocessing. It is based on a producer/consumer paradigm. Objects may produce reporters, which they declare to the Problem, and other objects may retrieve them from the Problem.
The reporter data can be of very many different types, from a single scalar to maps, vectors and points.
Vectorpostprocessors are an example of reporters, using std::vector<Real>
for the reporter data. Reporters include automatic json output.
A system for defining distribution sampling strategies for use with the stochastic tools module.
A system for splitting the preconditioning matrix to optimize the non-linear solving for multiphysics problems.
A system for defining schemes for numerical integration in time.
A system for computing time steps for transient executioners.
A system to move data to and from the "parent application" and "sub-applications" of a MultiApp.
New Feature: Transfers can now send data between sub-applications. We refer to this capability as 'siblings' transfer.
A system for defining an arbitrary interface between MOOSE objects.
A system for "reduction" or "aggregation" calculations based on the solution variables that results in one or many vectors of values.