Variables¶
Variables are used to parameterize the simulation for design changes, creating ML training data, and design optimization.
Typically the variable are read from the input decks; for example, *PARAMETER definitions in LS-DYNA. You can also define a variable for use.
The following types of variables are available: FloatVariable, IntSetVariable, and StrSetVariable.
Members of a variable¶
Every variable carries four members, from the Variable base class:
nameThe variable’s name. It is the key the value is looked up under in the
val_dictpassed tosolve(), so it must match the name in the deck.valueThe current value. It is a property: assigning to it is checked against the variable’s bounds or its set of allowable values.
typeThe Python type the variable holds —
float,intorstr.descriptionEach variable has an optional
descriptionargument. If not provided, the class docstring is used as the description.
FloatVariable(name, value, upper_bound=None, lower_bound=None, description=None)
is the continuous variable. It adds:
lower_bound,upper_boundThe range the value must stay within.
None(the default) leaves that side unbounded.
A value outside the range is refused at construction with a ValueError,
and on assignment with an AssertionError:
from kunene.variables import FloatVariable
t = FloatVariable('T', 75., lower_bound=10., upper_bound=200.)
t.value = 80. # fine
t.value = 500. # AssertionError
FloatVariable('T', 500., upper_bound=200.) # ValueError
IntSetVariable(name, value, allowable=None, description=None) and
StrSetVariable(name, value, allowable=None, description=None) are the
discrete variables — an integer and a string chosen from a fixed set. Both
add:
allowableThe set of values the variable may take. A list or tuple is converted to a set. If it is omitted or empty it becomes
{value}, which pins the variable to its initial value — rarely what is wanted, so pass the set explicitly.
from kunene.variables import IntSetVariable, StrSetVariable
n = IntSetVariable('N', 2, [1, 2, 3])
n.allowable # {1, 2, 3} — the list became a set
n.value = 3 # fine
n.value = 7 # AssertionError
m = StrSetVariable('M', 'foo', ('foo', 'bar'))
m.allowable # {'foo', 'bar'}
IntSetVariable('N', 5).allowable # {5}: no set given, so pinned to 5
Only assignment is checked, never the initial value, so
IntSetVariable('N', 9, [1, 2]) is built without complaint and holds a
value outside its own set. The checks on assignment are assert
statements, which Python removes when run with -O.
parameters() returns an UnknownVariable when the deck gives neither
a type nor a default — a jinja {{ }} name, or an OpenRadioss expression
parameter. It has name, value and description but its type
is None, and its value is read-only.
Variable discovery¶
Both WorkArea and SimulationIterator support variable discovery
via parameters(). The files are copied first so that solver actions
can read their input files: WorkArea copies them into its work
directory, SimulationIterator into a variables_discovery
subdirectory of the results root. The originals are never modified.
from kunene.graph_actions import WorkArea, SimulationIterator
wa = WorkArea(wf, copy_paths=['path/to/spring.k'])
for v in wa.parameters():
print(v)
itr = SimulationIterator(wf, copy_paths=['path/to/spring.k'])
for v in itr.parameters():
print(v)
See Discovering graph usage for more details on variable and output discovery.
Using a variable as an argument to an action¶
First, you have to define the variable, then you can use it to control actions.
from kunene.args import Location
from kunene.variables import FloatVariable
from kunene.openfoam_actions import OpenFOAM_Field
# define variable
etime = FloatVariable( 'ET', 40. )
# The variable can be used to construct an action
# Below it is used to control an extraction time
f = OpenFOAM_Field( name='TF', field_variable='T',
time=etime, location=Location.NODAL)
# the value given to solve() replaces the variable
f.solve( {'ET':50} )
The action reads the OpenFOAM case in the current working directory, which
is the work area the graph runs in, so there is no case-directory argument:
put the case there with the copy_paths of a WorkArea or a
SimulationIterator.
The two decorators that make this work are
@WorkAction.allow_variables_as_arguments on __init__ and
@WorkAction.assign_variables_values_to_members on solve. An action
that should accept variables as constructor arguments needs both.