This setup provides an overview to the various configuration options for Euler 3D simulations. The domain is a simple cube with periodic boundary conditions in all directions and a Gaussian pulse is transported through the domain by a constant velocity.
The ateles.lua
that may also be used as a template for your own
configuration:
-- Example Ateles configuration for simulation of Euler3D equations --
--
-- This configuration file illustrates the various settings and --
-- options relevant for Euler 3D simulations. --
-- You may want to use it as a template for your configurations. --
-- NOTE: This run is configured to run only 2 iterations, for --
-- use you'll want to change that. See sim_control! --
-- -------------------------------------------------------------------------- --
gamma = 1.4 -- isentropic expansion coefficient
R = 1.0 -- gas constant
equation = { -- >>>>>>>>>>>>>>>
name = 'euler',
isen_coef = gamma,
r = R,
cv = R/(gamma-1),
numflux = 'hll', -- Numerical flux to use between elements.
-- Available are 'hll', 'godunov' and
-- 'lax_friedrich'. 'lax_friedrich' is not
-- recommended, as it may cause instabilities,
-- especially at boundaries.
linear_limit = 0.001, -- Linearization limit, if this is larger than 0
-- elements, where the indicator is smaller than
-- this limit will be computed with a linearized
-- flux.
linearization_indicator = 'error',
-- The estimator to use to decide, whether
-- linearization should be used. Only relevant if
-- linear_limit>0.
-- Available options are:
-- 'error': An estimation for the terms neglected
-- by linearization, involves all
-- variables. This is the default.
-- 'energy': Use deviation of energy from its
-- mean value to decide the
-- linearization.
-- 'density': Use deviation of density from its
-- mean to decide the linearization.
ensure_positivity = false, -- Ensure that density and energy remain positive
-- by only considering higher modes up to the point
-- where positivity is guaranteed.
porosity = 1.0, -- Porosity to use in material modelling for
-- wall representation in elements.
viscous_permeability = 1.0e-6, -- Viscous permeability for the porous medium
-- to represent wall geometries in elements.
thermal_permeability = 1.0e-3, -- Thermal permeability for the material to
-- represent walls.
material = {
-- Description of the material distribution to define obstacles inside the
-- domain.
characteristic = 0.0, -- Masking function (may be a variable) that describes
-- where Material is to be found (Chi(x,y,z)), should
-- be 1 inside material and 0 everywhere else.
relax_velocity = {0, 0, 0}, -- Velocity of the obstacle.
relax_temperature = 0.0 -- Temperature of the obstacle.
}
} -- equation <<<<<<<<<<<<
-- -------------------------------------------------------------------------- --
-- -------------------------------------------------------------------------- --
hours = 3600
jobtime = 2 * hours -- Time available for the computation.
-- This variable is not a setting for Ateles, but
-- used below. You might want to get this from an
-- environment variable in your job script.
-- use os.getenv('varname') to get environment variables.
sim_control = { -- >>>>>>>>>>>>>>>
-- Controlling the execution of the simulation.
time_control = {
-- Time definitions are provided in terms of:
-- * sim: simulation time, this is the time measurement for the
-- transient phenomenon that is simulated.
-- * iter: the number of iterations that were done
-- * clock: the real time that has passed since the beginning of
-- the simulation in seconds.
-- All three measures might be set, whatever is encountered first,
-- will trigger the setting:
-- {sim = 1.23, iter = 123, clock=12.3}
-- If instead of a table a single number is provided, this is
-- interpreted as the setting for sim.
-- All not-given times are set to never.
max = { -- Point in time when to stop the simulation.
sim = 1.0,
clock = jobtime - 5*60,
iter = 2 -- This is just for a quick check that the setup works
-- for real runs, you'd take this away.
},
-- Providing a clock setting for the max time allows you to ensure that
-- a restart file is written before the computation is ended by the
-- scheduler. We stop here five minutes early to allow for the restart to
-- be written. This also implies that single iterations should take less
-- than 5 minutes. If they take longer, you might run into the end without
-- writing a restart.
min = 0.0,
interval = {iter = 10}, -- This controls the output frequency to
-- report the current time step.
},
abort_criteria = {
-- Criteria upon which the simulation should be stopped.
stop_file = 'STOP' -- Stop file, can be used to signal the simulation to
-- gracefully end.
-- If this is empty (the default), this is disabled.
-- Non-empty settings here, will cause the simulation to
-- come to an end when a file of this name exists in the
-- working directory.
-- Thus, with stop_file = 'STOP', you can cause the
-- simulation to stop and write a restart by doing
-- "touch STOP" in the working directory of the run.
-- Empty files like the one created by touch, will be
-- deleted by Ateles. If you want to keep the file, it
-- needs to have some content. You can achieve this for
-- example by "echo keep > STOP".
}
} -- sim_control <<<<<<<<<<<<
-- -------------------------------------------------------------------------- --
-- -------------------------------------------------------------------------- --
mesh = { -- >>>>>>>>>>>>
-- Simple predefined cubical mesh, periodic in all directions.
predefined = 'cube',
origin = {0, 0, 0},
length = 1,
refinementLevel = 3
} -- mesh <<<<<<<<<<<<
-- Alternatively, for meshes from seeder you set the prefix (may be a path), to
-- where the mesh is found:
-- mesh = 'mesh/'
-- -------------------------------------------------------------------------- --
-- -------------------------------------------------------------------------- --
scheme = { -- >>>>>>>>>
spatial = {
-- the spatial discretization scheme (needs to match dimensionality of
-- equation)
name = 'modg',
modg_space = 'Q', -- How to build multidimensional polynomials.
-- 'Q' means we include all modes up to the maximal polynomial degree
-- in each direction, no matter the others, resulting in modes with
-- three times the maximal polynomial degree.
-- 'P' means that only modes are considered for which the sum of
-- the polynomial degree in each direction does not exceed the maximal
-- polynomial degree.
m = 11 -- the maximal polynomial degree for each spatial direction
},
temporal = {
-- the temporal discretization scheme
name = 'explicitRungeKutta',
steps = 4,
-- Strong stability preserving explicit Runge Kutta:
-- For stability preserving filters
-- name = 'explicitSSPRungeKutta',
-- steps = 2,
-- Implicit-Explicit Runge Kutta (DIRK)
-- If Material is used, this time scheme should be employed!
-- name = 'imexRungeKutta',
-- steps = 4,
-- Explicit Taylor expanded Runge Kutta
-- Higher order for linear autonomous equations.
-- name = 'explicitRungeKuttaTaylor'
-- steps = 10, -- arbitrary number of steps
-- Explicit Euler (unstable for higher spatial orders):
-- only for testing!
-- name = 'explicitEuler',
control = {
-- Choice of time step width.
name = 'cfl', -- the name of the timestep control mechanism
-- (alternatively a fixed timestep may be used).
cfl = 0.8, -- Courant-Friedrichs-Lewy number
-- Modal to nodal conversion for the timestep width can be avoided
-- by using a modal estimate. This is especially relevant when using
-- linearization.
-- Less accurate (may result in smaller time steps).
use_modal_estimate = false,
-- Alternatively a fixed time step may be configured:
-- name = 'fixed',
-- dt = 0.123
}
}
} -- scheme <<<<<<<<<<<<<<
-- -------------------------------------------------------------------------- --
-- -------------------------------------------------------------------------- --
initial_condition = { -- >>>>>>>>>>>>>>
-- As initial conditions all primitive variables (density, velocity and
-- pressure) must be provided as spatial functions (f(x,y,z)).
-- There are some predefined spatial functions, like the gaussian pulse that
-- may be used. Constants and Lua functions are also fine.
density = {
predefined = 'gausspulse',
center = { 0.5, 0.5, 0.5 },
halfwidth = 0.20,
amplitude = 2.0,
background = 1.225
},
pressure = 1,
velocityX = 1,
velocityY = 0.0,
velocityZ = 0.0
} -- initial_condition <<<<<<<<<<<<
-- -------------------------------------------------------------------------- --
-- -------------------------------------------------------------------------- --
boundary_condition = { -- >>>>>>>>>>
-- This minimal example is completely periodic and has no boundary conditions.
-- Each boundary condition is described by a kind, and space-time functions
-- for all required variables in the that boundary.
-- Space time functions are either predefined functions, Lua functions,
-- constants or combined functions, where temporal and spatial parts are
-- superimposed.
-- If there are values that are to be extrapolated (Neumann boundary
-- condition), you can set enforce_zero_grad to true, to use an extrapolation
-- of a polynomial with zero gradient at the boundary.
-- This is achieved by computing the last mode to fulfill this condition.
-- If you set neumann_mode_fraction to a smaller value than 1, then only
-- this fraction of lower modes will be used in the enforce_zero_grad
-- procedure and higher modes will be set to 0.
-- { -- SLIPWALL
-- -- Velocity in normal direction 0, other values extrapolated.
-- label = 'cylinder',
-- kind = 'slipwall', -- or 'wall'
-- enforce_zero_grad = true,
-- neumann_mode_fraction = 1.0
-- },
-- { -- PRIMITIVES
-- -- Prescribe all primitive variables.
-- label = 'outside',
-- kind = 'primitives',
-- density = 1.23,
-- velocityX = 0.2,
-- velocityY = 0.3,
-- velocityZ = 0.4,
-- pressure = 1
-- },
-- { -- CONSERVATIVES
-- -- Prescribe all conservative variables.
-- label = 'left',
-- kind = 'conservatives',
-- density = 1.23,
-- momentumX = 0.2,
-- momentumY = 0.3,
-- momentumZ = 0.4,
-- energy = 4
-- },
-- { -- INFLOW
-- -- Prescribe density and velocity, extrapolate pressure.
-- label = 'outside',
-- kind = 'conservatives',
-- density = 1.23,
-- velocityX = 0.2,
-- velocityY = 0.3,
-- velocityZ = 0.4
-- enforce_zero_grad = true,
-- neumann_mode_fraction = 1.0
-- },
-- { -- INFLOW_NORMAL
-- -- Prescribe density and velocity normal to boundary,
-- -- extrapolate pressure.
-- label = 'inlet',
-- kind = 'inflow_normal',
-- density = 1.23,
-- v_norm = 0.5,
-- enforce_zero_grad = true,
-- neumann_mode_fraction = 1.0
-- },
-- { -- SUPERSONIC_INFLOW_NORMAL
-- -- Prescribe all primitive variables with velocity normal to boundary.
-- label = 'superin',
-- kind = 'inflow_normal',
-- density = 1.23,
-- v_norm = 2.5,
-- pressure = 1
-- },
-- { -- OUTFLOW
-- -- Prescribe pressure, extrapolate all other variables.
-- label = 'east',
-- kind = 'outflow',
-- pressure = 1
-- enforce_zero_grad = true,
-- neumann_mode_fraction = 1.0
-- },
-- { -- SUPERSONIC_OUTFLOW
-- -- Extrapolate all variables.
-- label = 'superout',
-- kind = 'supersonic_outflow',
-- enforce_zero_grad = true,
-- neumann_mode_fraction = 1.0
-- },
} -- boundary_condition <<<<<<<<<<
-- -------------------------------------------------------------------------- --
-- -------------------------------------------------------------------------- --
restart = { -- >>>>>>>>>>>>>>>
-- Header of restart, to start simulation from.
-- example:
read = './restart_simulation_lastHeader.lua',
-- If an initialization should be done, when the file given in the
-- read setting above is missing, set the init_on_missing to true.
-- With an init_on_missing = false, the computation will stop, if
-- the file in read is not found. This option has no meaning when no
-- read is provided.
-- default: false
init_on_missing = true,
-- Prefix for the files, that are to be written during the
-- simulation. If this ends with a path separator, the restart files
-- will be written into the specified directory and that directory
-- has to exist
write = 'restart_', -- 'restart/' for a directory
time_control = {
-- Starting point after which restart files should
-- be written.
-- Setting iter to 0 here, results in restart files
-- being written from the initial condition onwards.
min = {iter = 0},
-- The maximal point in time, up to which, restarts
-- should be written.
-- Note, that if this is not defined at all, it will
-- be set to never, resulting in doing restarts for
-- all times, including a final restart after
-- reaching the termination of the time loop.
max = sim_control.time_control.max.sim,
-- Frequency at which restart files are to be
-- written between min and max.
interval = 0.1,
-- If a restart is read, it may be that the restart
-- writing did not happen at the desired interval,
-- nevertheless you might want to write the next
-- restart file according to the original interval
-- rythm. To achieve this you can tell the restart
-- to align the trigger to last interval before
-- the restart time with the align_trigger option:
align_trigger = { sim = true },
-- For each time component you can define whether
-- an alignment should be done or not.
-- If you only set one flag like:
-- align_trigger = false
-- It will be applied to the simtime, the others
-- will be set to false.
-- Default is false.
-- Controlling if a restart file should be written
-- or not involves communication, if a clock setting
-- is used.
-- This might have a negative impact on the
-- performance, if it is done every iteration and
-- a single iteration is too short.
-- By setting check_iter the interval at which
-- these checks are done, can be increased, and
-- thus performance impacts reduced.
-- CAUTION: be aware that increasing this to values
-- larger than 1, decreases the accuracy
-- of the points in time at which restarts
-- are written!
-- default:
-- check_iter = 1
}
} -- restart <<<<<<<<<<<<
-- -------------------------------------------------------------------------- --
-- -------------------------------------------------------------------------- --
tracking = { -- >>>>>>>>>>>>
{
label = 'QuantityOfInterest',
variable = { 'density' },
-- Available variables in Euler:
-- * density
-- * momentum
-- * energy
-- * pressure
-- * velocity
-- * speedOfsound: local speed of sound
-- * temperature: temperature of the fluid
-- * mach_number: local Mach number
-- * mach_vector: local velocity vector scaled by the speed of sound
-- * kinetic_energy: the kinetic energy of the fluid
-- * gradv: gradient of the velocity field
-- * vorticity: vorticity of the flow field
-- * q_criterion: Q-Criterion (positive second invariant of velocity
-- gradient tensor)
-- * lambda2: Lambda 2 criterion: largest eigenvalue of shear and
-- rotational contributions to the velocity gradient
-- tensor.
-- * linindicator: Indicator that is used to decide whether to just
-- compute the linearized Euler flux in the element.
-- This depends on the chosen linearization_indicator.
-- It will be 1 in elements that are computed nonlinearly
-- and 0 in elements where the linearized flux is used.
shape = { kind='global' },
time_control = {
min = { iter = 0 },
max = sim_control.time_control.max.sim,
interval = sim_control.time_control.max.sim/10
},
folder = 'track_',
output = { format = 'vtk' }
-- output = { format = 'asciispatial',
-- -- All degrees of freedom will be written, specify,
-- -- ndofs = 1 for dumping the average
-- ndofs=1 }
-- -- output = {format = 'harvester'} -- write restart files
-- Trackings can be reduced in space to single values:
-- reduction = {'sum','average'}, -- (default = 'none')
},
{
label = 'PointProbe',
variable = { 'pressure' },
shape = { kind='canoND', object = {origin={0.5,0.5,0.5}} },
folder = 'pp_',
output = { format = 'ascii',
-- track the value exactly at the given point (instead of
-- getting the complete element):
use_get_point = true },
time_control = {
min = { iter = 0 },
max = sim_control.time_control.max.sim,
interval = {iter = 1}
},
}
} -- tracking <<<<<<<<<<<<<<<
-- -------------------------------------------------------------------------- --
-- -------------------------------------------------------------------------- --
ply_sampling = { -- >>>>>>>>>>>>>>
-- Subsampling for tracking, define a ply_sampling table to activate
-- subsampling for all tracking objects (except those with use_get_point).
nlevels = 1, -- maximal level to use in subsampling
-- defaults to 0, which deactivates subsampling
--method = 'fixed', -- method to use for subsampling
-- 'adaptive': (recommended default) adaptive refinement
-- of the mesh based on solution
-- 'fixed': will refine all elements by nlevels and
-- evaluate the polynomials at the barycenter of
-- each fine element
-- Parameters for adaptive sampling:
--tolerance = 0, -- threshold for ignoring higher modes,
-- if the sum of absolute values of higher
-- modes in relation to the first mode is
-- below the tolerance, they will be cut off.
-- Default: 0 (never ignore modes).
-- Recommended: 0.01 - 0.05
--dof_reduction = 0.5, -- Factor to multiply the 1D number of degrees
-- of freedom with in each refinement.
-- (0.5 implies to only keep half the degrees
-- of freedom after the refinement).
-- Values smaller 0.5 are not useful here and
-- 0.5 already yields quite poor polynomial
-- representations in the sampling.
-- Default: 0.5
-- Recommended: 2/3 - 3/4, 0.7 generally looks
-- quite good.
--adaptiveDofReduction = false, -- Increase the number of modes to keep after
-- refinement above the configured
-- dof_reduction factor if no more than the
-- original memory will be used.
-- Default: false
-- Recommended: true (generally advisable, no
-- big drawbacks)
--absUpperBoundLevel = 0 -- Maximal absolute level to refine to.
-- 0 means no absolute level, all elements
-- will be limited in the refinement by the
-- nlevels set above
-- This is useful for multilevel meshes, where
-- each element might start out on a different
-- level.
-- For a complete mesh overview you might want
-- to use a very high nlevels setting but
-- limit the refinement by absUpperBoundLevel
-- to allow for a more uniform resolution in
-- the sampled data.
-- Default: 0 (no absolute upper bound)
} -- ply_sampling <<<<<<<<<<<<
-- -------------------------------------------------------------------------- --
-- -------------------------------------------------------------------------- --
projection = { -- >>>>>>>>>>>
-- Projection between modal to nodal space
-- for BC, IC and non-linear problems is given
-- kind = 'l2p', -- 'fpt', 'fxt' or 'l2p',
-- -- default: 'l2p'
-- for l2p the nodes are by default 'gauss-legendre',
-- can be changed by setting the nodes_kind:
-- nodes_kind = 'chebyshev',
-- for fpt the nodes are automatically 'chebyshev'
-- for fxt the nodes are automatically 'gauss-legendre'
-- lobattoPoints = false, -- if lobatto points should be used,
-- default = false,
-- only working for Chebyshev points!
factor = 1.0, -- dealising factor for fpt
-- oversampling factor to remove aliasing
-- effects by padding, default: 1
-- Note that for FXT an evenly oversampled
-- order is required, if this is not the
-- case, the next higher even order will be
-- used and the actual factor might
-- accordingly be higher.
-- FXT settings:
-- prec = 1.5e-8, -- precision to use for the fast multipole
-- computation during initialization.
-- Defaults to sqrt of epsilon for double
-- precision numbers (1.5e-8).
-- FPT settings:
-- approx_terms = 18, -- Number of terms used to approximate the
-- matrix multiplication for blocks, that
-- are detached from the diagonal.
-- The default of 18 is recommended for
-- double precision.
-- blocksize = 64, -- for FPT, default 64. The blocksize
-- defines how big the minimal block
-- should be that is approximated in
-- fast algorithm.
-- The smaller it is, the more operations
-- are merely approximated.
-- Recommended for double precision is a
-- setting of 64.
-- The fast algorithm will only be used
-- for m >= blocksize.
-- Note, that this has to be larger than
-- 2*approx_terms to provide any
-- reduction in operation counts.
-- striplen = 256, -- This provides the length for arrays to
-- apply the matrix operation to
-- simultaneously.
-- Default is the vlen from the
-- tem_compileconf_module.
-- subblockingWidth = 8, -- The subblockingWidth is used during the
-- unrolling of the diagonal multiplication
-- during the projection. By setting this
-- value to an appropriate value a better
-- cache usage can be achieved.
-- Default is 8
-- adapt_factor_pow2 = true, -- for FPT, default false. Should the
-- oversampling factor be adjusted to
-- obtain a power of 2 in the
-- oversampled order?
-- fftMultiThread = false -- for FPT, default false. Should nested
-- multithreading be activated for FFTW?
-- There can be individual projection settings for various parts
-- of the computation.
-- These are useful to allow for a higher oversampling in specific
-- parts.
-- individual projection methods for source terms
-- if none is provided, the general projection method is used
source_terms = {
-- the configuration parameter are similar to the
-- general projection method
-- kind = 'fpt',
factor = 1.0
},
-- individual projection methods for initial condition
-- if none is provided the general projection method is used
initial_condition = {
-- the configuration parameter are similar to the
-- general projection method
factor = 2.0
},
-- individual projection methods for boundary condition
-- if none is provided the general projection method is used
boundary_condition = {
-- the configuration parameter are similar to the
-- general projection method
-- kind = 'fpt',
factor = 2.0
},
-- individual projection methods for boundary condition
-- if none is provided the general projection method is used
--material= {
-- -- the configuration parameter are similar to the
-- -- general projection method
-- -- kind = 'fpt',
-- factor = 2.0
--}
} -- projection <<<<<<<<<<<<