# MULTIPLIER_FUNCTION

Specifies a scalar multiplier function to scale values of other commands and parameters at run time.

## Type

AcuSolve Command

## Syntax

MULTIPLIER_FUNCTION ("name") {parameters...}

## Qualifier

User-given name.

## Parameters

- type (enumerated) [=none]
- Type of the multiplier function.
- constant or const
- Fixed value. Requires constant_value.
- sine_series or sine
- Summation of a series of sine functions. Requires sine_coefficients.
- piecewise_linear or linear
- Piecewise linear curve fit. Requires curve_fit_values and curve_fit_variable.
- cubic_spline or spline
- Cubic spline curve fit. Requires curve_fit_values and curve_fit_variable.
- piecewise_log_linear or log_linear
- Piecewise log/linear curve fit. Requires curve_fit_values and curve_fit_variable.
- design_variable
- User-defined name of the design optimization variable.
- response_variable
- The responses to be used for optimization.
- user_function or user
- User-defined function. Requires user_function, user_values and user_strings.
- user_global_data or ugd
- User-defined global variable. Requires user_global_data.
- modifiable
- Used like constant type, except value may be modified within a user-defined function of another multiplier function.

- constant_value or value (real) (=1)
- The constant value of the multiplier function. Used with constant and modifiable types.
- sine_coefficients (array) [={1,0,0}]
- A three-column array of amplitude/frequency/phase data values. Used with sine_series type.
- curve_fit_values or curve_values (array) [={0,1}]
- A two-column array of independent-variable/multiplier-function data values. Used with piecewise_linear, cubic_spline, and piecewise_log_linear types.
- curve_fit_variable or curve_var (enumerated) [=time]
- Independent variable of the curve fit. Used with piecewise_linear,
cubic_spline, and
piecewise_log_linear types.
- time
- Current run time.
- cyclic_time
- Current run time, except cycled with period curve_fit_variable_cyclic_period.
- time_step or step
- Current time step.
- time_increment or dt
- Current time increment.
- multiplier_function
- Multiplier function. Requires curve_fit_variable_multiplier_function.
- user_global_data
- User-defined global variable. Requires curve_fit_variable_user_global_data.

- curve_fit_variable_multiplier_function (string) [=none]
- Name of the multiplier function. Used with multiplier_function curve fit variable.
- curve_fit_variable_user_global_data (string) [=none]
- Name of the user global data. Used with user_global_data curve fit variable.
- curve_fit_variable_cyclic_period (real) >=0 [=1]
- The period of cyclic time. Used with cyclic_time curve fit variable.
- design_variable (list) [={}]
- Design_variable list to be used with OPTIMIZATION.
- response_variable (string) [=""]
- User-defined name of the response variable that is computed from the simulation.
- user_function or user (string) [no default]
- Name of the user-defined function. Used with user_function type.
- user_values (array) [={}]
- Array of values to be passed to the user-defined function. Used with user_function type.
- user_strings (list) [={}]
- Array of strings to be passed to the user-defined function. Used with user_function type.
- user_history_variables (list) [={}]
- Array of history values passed to the user-defined function. Used with user_function type. For each entry in this array, AcuSolve allocates storage such that you can store and access values across time steps within a UDF.
- user_global_data or ugd (string) [no default]
- Name of the user global data variable. Used with user_function type or user_global_data curve fit variable.
- evaluation (enumerated) [=once_per_solution_update]
- Frequency of evaluating the multiplier function.
- once_per_solution_update or often
- Every solution update.
- once_per_time_step or step
- Every time step.

- filter (enumerated) [=none]
- Type of filter to smooth the multiplier function. May not be used with modifiable type.
- none
- No filter.
- relaxation or damp
- Smooth the value of the multiplier function. Requires filter_relaxation_factor.
- iir
- Infinite impulse response digital filter. Requires iir_input_coefficients and iir_output_coefficients.
- mic
- Multi-Iterative Coupling.

- filter_relaxation_factor (real) >=0 <=1 [=0.5]
- The value of the filter relaxation factor. Used with relaxation filter.
- iir_input_coefficients (array) [={1}]
- Infinite impulse response digital filter coefficients applied to computed values. Used with iir filter.
- iir_output_coefficients (array) [={}]
- Infinite impulse response digital filter coefficients applied to previously filtered values. Used with iir filter.
- dependencies (list) [={}]
- List of other multiplier functions this one depends on. Required when this multiplier function depends on another indirectly through a user global data.

## Description

This command specifies a scalar multiplier function to be used to dynamically scale various problem parameters at run time.

- MULTIPLIER_FUNCTION
- SOLAR_RADIATION
- EXTERNAL_CODE
- REFERENCE_FRAME
- MESH_MOTION
- FLEXIBLE_BODY
- TIME_INCREMENT
- GRAVITY
- MASS_HEAT_SOURCE
- VOLUME_HEAT_SOURCE
- MASS_SPECIES_SOURCE
- VOLUME_SPECIES_SOURCE
- VISCOSITY_MODEL
- CONDUCTIVITY_MODEL
- DIFFUSIVITY_MODEL
- POROSITY_MODEL
- SURFACE_TENSION_MODEL
- CONTACT_ANGLE_MODEL
- EMISSIVITY_MODEL
- NODAL_BOUNDARY_CONDITION
- PERIODIC_BOUNDARY_CONDITION
- LINE_SOURCE
- FAN_COMPONENT
- HEAT_EXCHANGER_COMPONENT
- ELEMENT_BOUNDARY_CONDITION
- SIMPLE_BOUNDARY_CONDITION
- SURFACE_INTEGRATED_CONDITION
- RADIATION_SURFACE

```
GRAVITY( "pulse gravity" ) {
type = constant
gravity = { 0, -9.81, 0 }
multiplier_function = "pulse function"
}
MULTIPLIER_FUNCTION( "pulse function" ) {
type = piecewise_linear
curve_fit_values = { 0., 0 ;
10., 0 ;
20., 1 ;
100., 1 ; }
curve_fit_variable = time
}
```

The physical gravity values are stored in the gravity parameter. The MULTIPLIER_FUNCTION command simply scales these values to produce the values used in AcuSolve.

```
GRAVITY( "pulse gravity" ) {
type = user_function
user_function = "usrSomeGravity"
multiplier_function} = "pulse function"
```

the resulting values from the user-defined function "usrSomeGravity" are scaled by the multiplier function in a similar fashion as above.

A constant type provides a fixed scaling factor for all times.

A sine_series type defines a time-dependent scaling factor of the form:

```
MULTIPLIER_FUNCTION( "sine series" ) {
type = sine_series
sine_coefficients = { 1., 10., 1.57 ;2., 20., 3.14 ; }
}
```

A multiplier function of type piecewise_linear, cubic_spline, or piecewise_log_linear computes an interpolated value from the curve fit data of curve_fit_values as a function of curve_fit_variable. curve_fit_values is a two-column array of real values. The first column specifies the independent variable values while the second column specifies the corresponding multiplier function values. The independent variable values must be in ascending order. The limit point values of the curve fit are used when curve_fit_variable falls outside of the curve fit limits.

```
0. 0
10. 0
20. 1
100. 1
```

```
MULTIPLIER_FUNCTION( "pulse function" ) {
type = piecewise_linear
curve_fit_values = Read( "pulse_function.fit" )
curve_fit_variable = time
}
```

```
MULTIPLIER_FUNCTION( "growth" ) {
type = piecewise_log_linear
curve_fit_values = { 10, 1 ; 13, 1000 }
curve_fit_variable = time_step
}
```

```
1 1
...
10 1
11 10
12 100
13 1000
14 1000
...
```

```
MULTIPLIER_FUNCTION( "curve fit UGD" ) {
type = piecewise_linear
curve_fit_values = { 0, 0 ;100, 200 }
curve_fit_variable = user_global_data
curve_fit_variable_user_global_data = "var_1"
}
USER_GLOBAL_DATA( "var_1" ) {
value = 25
}
```

A multiplier function of type user_function executes a user-defined function to obtain its scaling factor; see the AcuSolve User-Defined Functions Manual for a detailed description of user-defined functions.

```
NODAL_BOUNDARY_CONDITION( "inflow x_velocity" ) {
variable = x_velocity
type = nodal
nodes = Read( "inflow.nbc" )
nodal_values = Read( "inflow.xvel" )
multiplier_function = "sine wave at 10 Hz"
}
MULTIPLIER_FUNCTION( "sine wave at 10 Hz" ) {
type = user_function
user_function = "usrSinWave"
user_values = { 10. } # frequency
}
```

```
#include "acusim.h"
#include "udf.h"
UDF_PROTOTYPE( usrSinWave ) ; /* function prototype */
Void usrSinWave (
UdfHd udfHd, /* Opaque handle for accessing data */
Real* outVec, /* Output vector */
Integer nItems, /* Number of items in outVec */
Integer vecDim /* Vector dimension of outVec */
) {
Real freq ; /* frequency */
Real time ; /* run time */
Real* usrVals ; /* user values */
udfCheckNumUsrVals( udfHd, 1 ) ; /* check for error */
usrVals = udfGetUsrVals( udfHd ) ; /* get the user vals */
freq = usrVals[0] ; /* get the frequency */
time = udfGetTime( udfHd ) ; /* get the run time */
*outVec = sin( time * freq * 6.2832 ) ; /* compute mult.func.*/
} /* end of usrSinWave() */
```

```
NODAL_BOUNDARY_CONDITION( "inflow x-vel" ) {
variable = x_velocity
...
multiplier_function = "inflow pressure control"
}
MULTIPLIER_FUNCTION( "inflow pressure control" ) {
type = user_function
user_function = "usrClientServer"
user_values = { -4, 1, 0 }
user_strings = { "rsh pelican usrPres.pl","inflow" }
}
```

```
#include "acusim.h"
#include "udf.h"
UDF_PROTOTYPE(usrClientServer) ; /* function prototype */
Void usrClientServer(
UdfHd udfHd, /* Opaque handle for accessing data */
Real* outVec, /* Output vector */
Integer nItems, /* Number of items in outVec */
Integer vecDim /* Vector dimension of outVec */
) {
Real mfValue ; /* MF return value */
Real targPres ; /* target pressure */
Real verbose ; /* verbose level */
Real* trac ; /* pointer to surface traction */
Real* usrVals ; /* user supplied values */
String command ; /* execution command */
String inflowOsi ; /* inflow surface output */
String* usrStrs ; /* user supplied strings */
char buffer[1024] ; /* a string buffer */
char* name ; /* name of the UDF */
udfCheckNumUsrVals( udfHd, 3 ) ;
udfCheckNumUsrStrs( udfHd, 2 ) ;
usrVals = udfGetUsrVals( udfHd ) ;
usrStrs = udfGetUsrStrs( udfHd ) ;
targPres = usrVals[0] ;
mfValue = usrVals[1] ;
verbose = usrVals[2] ;
command = usrStrs[0] ;
inflowOsi = usrStrs[1] ;
/* Start the client */
if ( udfFirstCall(udfHd) ) {
sprintf( buffer, "%s %g %g %g", command,
targPres, mfValue, verbose ) ;
udfOpenPipePrim( udfHd, buffer ) ;
}
if ( !udfFirstStep(udfHd) ) {
/* Get the average pressure at the inflow surface */
trac = udfGetOsiData( udfHd,inflowOsi, UDF_OSI_TRACTION ) ;
/* Send the data to the client program */
udfWritePipe( udfHd, "pressure= %.16g", -trac[0] ) ;
/* Receive the data from the client program */
udfReadPipe( udfHd, buffer, 1024 ) ;
sscanf( buffer, "%*s %le", &mfValue ) ;
if ( fabs(-trac[0]-targPres) > 1.e-4*fabs(targPres) ) {
udfSetSig( udfHd, UDF_SIG_NO_CONV, 0 ) ;
}
}
outVec[0] = mfValue ;
name = udfGetName( udfHd ) ;
udfCheckUgd( udfHd, name ) ;
udfSetUgdData( udfHd, name, mfValue ) ;
} /* end of usrClientServer() */
```

```
#!/usr/bin/env perl
$| = 1 ;
if ( scalar(@ARGV) != 3 ) {
die "Usage: $0 target_pressure initValue verbose" ;
}
$targPres = shift @ARGV ;
$mf = shift @ARGV ;
$verbose = shift @ARGV ;
$atFct = 0.8 ;
while( <> ) {
chomp ;
$line = $_ ;
if ( $line !~ /\Apressure= (.*)\Z/ ) {
die "Invalid line: $_\n" ;
}
$mfPrev = $mf ;
$p1 = $1 ;
$p2 = $p1 * $p1 ;
$lhs11 = $atFct * $lhs11 + $p1 * $p1 ;
$lhs12 = $atFct * $lhs12 + $p1 * $p2 ;
$lhs22 = $atFct * $lhs22 + $p2 * $p2 ;
$res1 = $atFct * $res1 + $p1 * $mf ;
$res2 = $atFct * $res2 + $p2 * $mf ;
$d = $lhs11 * $lhs22 - $lhs12 * $lhs12 ;
if ( $d > 1.e-8 * ($lhs11 * $lhs22) ) {
$a1 = (+$lhs22 * $res1 - $lhs12 * $res2) / $d ;
$a2 = (-$lhs12 * $res1 + $lhs11 * $res2) / $d ;
$mf = ($a2 * $targPres + $a1) * $targPres ;
} elsif ( $lhs11 > 0 ) {
$a1 = $res1 / $lhs11 ;
$mf = $a1 * $targPres ;
}
$mf = 2.0 * $mfPrev if $mf > 2.0 * $mfPrev ;
$mf = 0.5 * $mfPrev if $mf < 0.5 * $mfPrev ;
printf "multiplier_function= %.16g\n", $mf ;
print STDERR "pressure = $p1 mf = $mf\n" if $verbose ;
}
```

A user_global_data type uses the current value of the global data variable given by the user_global_data parameter as the value for the multiplier function.

```
MULTIPLIER_FUNCTION( "Mod MF" ) {
type = modifiable
constant_value = 2 #in case not modified
dependencies = { "main" }
}
MULTIPLIER_FUNCTION( "main" ) {
type = user_function
user_function = "usrSomeMf"
}
```

`udfSetMfData( udfHd, "Mod MF", 12. );`

See the AcuSolve User-Defined Functions Manual for a detailed description of user-defined functions.

The result of MULTIPLIER_FUNCTION may be modified in two ways. The evaluation parameter controls when the multiplier function is updated. For example, setting this to once_per_time_step freezes the value for the rest of the time step.

The filter parameter controls how much smoothing is applied to the multiplier function. If relaxation is specified then the multiplier function is given by the following:

where $\alpha $
is given by filter_relaxation_factor,
M_{n} is the final value of the
multiplier function at time step n, and
${\tilde{M}}_{n}$
is the value of the multiplier function without filtering
at time step n.

For an iir filter, an infinite impulse response (IIR) digital filter is applied. This is a generalization of the relaxation filter and is given by:

with the constraint that

```
MULTIPLIER_FUNCTION( "MF with digital filter" ) {
...
filter = iir
iir_input_coefficients = { 0.8, 0.8 }
iir_output_coefficients = { -0.6 }
}
```

```
MULTIPLIER_FUNCTION( "MIC_TMF" ) {
...
evaluation = often
filter = mic
}
```

The dependencies parameter does not modify the value of the multiplier function but ensures that it is evaluated correctly. If the current multiplier function is a modifiable type or depends on a user global data variable which in turn is set within a user-defined function of a second multiplier function, then it is necessary for the second multiplier function to be evaluated before the current one. However, AcuSolve has no way to detect this indirect dependency, hence you must list all such dependencies explicitly. Dependencies may be chained indefinitely, but any non-terminating recursive loop is flagged as an error.