English Français

Documentation / Manuel utilisateur en Python : PDF version

IV.2. Analytic function

IV.2. Analytic function

The analytic functions compatible with Uranie must follow the prototype:

void MyFunction(Double_t *x, Double_t *y)

where:

  • MyFunction is the name of the function;

  • x is an array of Double_t which represents inputs;

  • y is an array of Double_t which represents outputs or targets.

So, this prototype allows us to execute any function of on .

The example below is the content of the file UserFunctions.C in which the definition of the flowrate function seen in Section IV.1.2.1 has been copied:

#include "TMath.h"

void flowrateModel(double *x, Double_t *y)
{
  Double_t drw = x[0], dr  = x[1];
  Double_t dtu = x[2], dtl = x[3];
  Double_t dhu = x[4], dhl = x[5];
  Double_t dl  = x[6], dkw = x[7];

  Double_t dnum = 2.0 * TMath::Pi() * dtu * ( dhu -dhl);
  Double_t dlnronrw = TMath::Log( dr / drw);
  Double_t dden = dlnronrw * ( 1.0 +  ( 2.0 * dl * dtu ) / ( dlnronrw * drw * drw * dkw) + dtu / dtl );

  y[0] = dnum / dden;
}

In a Uranie script, after having defined the TDataServer object and created a sample, we load the previously defined function and create a TLauncherFunction object with its name as second argument, as shown below:

# Create a TDataServer
tds = DataServer.TDataServer("tdsFlowrate","TDS for flowrate")  1
# Add the eight attributes of the study with uniform laws
tds.addAttribute(DataServer.TUniformDistribution("rw", 0.05, 0.15))         2
tds.addAttribute(DataServer.TUniformDistribution("r", 100.0, 50000.0))
tds.addAttribute(DataServer.TUniformDistribution("tu", 63070.0, 115600.0))
tds.addAttribute(DataServer.TUniformDistribution("tl", 63.1, 116.0))
tds.addAttribute(DataServer.TUniformDistribution("hu", 990.0, 1110.0))
tds.addAttribute(DataServer.TUniformDistribution("hl", 700.0, 820.0))
tds.addAttribute(DataServer.TUniformDistribution("l", 1120.0, 1680.0))
tds.addAttribute(DataServer.TUniformDistribution("kw", 9855.0, 12045.0))

# Generate the sampling from the TDataServer
sampling = Sampler.TSampling(tds, "lhs", 1000)                   3
sampling.generateSample()

# Load the function in the UserFunction macros file
ROOT.gROOT.LoadMacro("UserFunctions.C")                                     4

# Create a TLauncherFunction from a TDataServer and an analytic function
FuncName = "flowrateModel"
tlf = Launcher.TLauncherFunction(tds, FuncName, "",FuncName)     5

# Define whether a progress bar should be drawn
tlf.setDrawProgressBar(False)                                         6

# Evaluate the function on all the design-of-experiments
tlf.run()                                                              7

tds.drawProfile("flowrateModel:rw")

Evaluate an analytic function

1

Create a TDataServer;

2

Add attributes to the TDataServer;

3

Create and generate a sample;

4

Load the file UserFunctions.C, that allows to use the function flowrateModel;

5

Create a TLauncherFunction object from the TDataServer and the analytic function flowrateModel. The inputs are all the TAttribute objects of the TDataServer, taken in the order of the calls to the addAttribute methods (, , , , , , , ). WARNING WITH ROOT6: the second argument should be either a string or a pointer if the function is defined in the same file (see Section I.2.5) and the last argument that gives the name of the output attribute cannot be omitted anymore.

6

Define whether a progress bar should be drawn (here we switch it off).

7

Evaluate the function on the design-of-experiments contained in the TDataServer and store the output in a new TAttribute whose name is the name of the function flowrateModel (we can see the use of the flowrateModel variable in the last drawProfile line).

At any moment, if one wants to verify the name of the function used, a call to the method GetName will return the name of the TLauncherFunction function:

print(tlf.GetName())  # will print "flowrateModel"

If the attributes have not been defined in the order they will be used in the function, the user must specify them in the right order in the third argument of the function as a string that contains the variables names separated by colons. In similar manner, if there are attributes that are defined but not useful for a launcher definition, in order Uranie not to take them into account, just specify the list of the useful attributes in the definition of the TLauncherFunction. The following example will produce the same result as the previous one:

# Create a TDataServer
tds = DataServer.TDataServer("tdsFlowrate","TDS for flowrate")
# Add the eight attributes of the study with uniform laws
tds.addAttribute(DataServer.TUniformDistribution("a", 0., 1.))           1
tds.addAttribute(DataServer.TUniformDistribution("b", 0., 1.))
tds.addAttribute(DataServer.TUniformDistribution("c", 0., 1.))

tds.addAttribute(DataServer.TUniformDistribution("rw", 0.05, 0.15))
tds.addAttribute(DataServer.TUniformDistribution("r", 100.0, 50000.0))
tds.addAttribute(DataServer.TUniformDistribution("hu", 990.0, 1110.0))
tds.addAttribute(DataServer.TUniformDistribution("hl", 700.0, 820.0))    2
tds.addAttribute(DataServer.TUniformDistribution("tl", 63.1, 116.0))
tds.addAttribute(DataServer.TUniformDistribution("tu", 63070.0, 115600.0))
tds.addAttribute(DataServer.TUniformDistribution("l", 1120.0, 1680.0))
tds.addAttribute(DataServer.TUniformDistribution("kw", 9855.0, 12045.0))

# Generate the sampling from the TDataServer
sampling = Sampler.TSampling(tds, "lhs", 1000)
sampling.generateSample()

# Load the function in the UserFunction macros file
ROOT.gROOT.LoadMacro("UserFunctions.C")

# Create a TLauncherFunction from a TDataServer and an analytic function
fName = "flowrateModel"
tlf = Launcher.TLauncherFunction(tds, fName, "rw:r:tu:tl:hu:hl:l:kw", fName)   3

# Evaluate the function on all the design-of-experiments
tlf.setDrawProgressBar(False)
tlf.run()

tds.drawProfile("flowrateModel:rw") 

Specification of the input variables for an analytic function

1

Three useless attributes have been added to the TDataServer;

2

The creation order of the other attributes have been mixed up;

3

In order for Uranie to treat only the wanted attributes (not a, b, c), and in the right order, we add the string "rw:r:tu:tl:hu:hl:l:kw" in the definition of the TLauncherFunction.

Tip

Note that if the third argument is the empty string (""), the behaviour is the same as if the argument is not specified. That is useful to specify a fourth argument (see below) without having to specify the third.

By default, Uranie assumes the function returns only one value. In case the function returns several values and one wants to precise their name explicitely, it is necessary to specify their number to Uranie to create the different attributes in the TDataServer, by using the setNOutput method. For example if we use the following definition in the previous example:

tlf.setNOutput(2)

then, after running, two outputs would be available: flowrateModel_1 and flowrateModel_2, whose names are created automatically from the function name and an index.

Finally, it is possible to specify the names of the output variables as the fourth argument of the TLauncherFunction. This is highly recommended, and mainly useful in two cases:

  • for renaming the output variable in order to ease its manipulation (e.g. y instead of flowrateModel);

  • for getting more than one output variable if the function returns several, without using the setNOutput method. As an example, assuming that the function returns two values (i.e. it defines y[0] and y[1]), we can have the following call, that will produce values for outputs named y0, y1:

    tlf2out = Launcher.TLauncherFunction(tds, "flowrateModel", "rw:r:tu:tl:hu:hl:l:kw", "y0:y1")

As seen previously, the TLauncherFunction::run can be called without argument to run the function with the default inputs and outputs, but the method can also be called with arguments that specify the inputs and outputs to use for a specific computation. For example, assuming that we have added two sets of input attributes, [ , , , , , , , ] and [ , , , , , , , ], to the dataserver, then we could get the result of the computation on the first set, y1, and on the second set, y2, by using the following code:

tlf.run("rw1:r1:tu1:tl1:hu1:hl1:l1:kw1", "y1")
tlf.run("rw2:r2:tu2:tl2:hu2:hl2:l2:kw2", "y2")

More example of running functions with a TLauncherFunction object, are shown in the use-case chapter, from Section XIV.5.1 to Section XIV.5.3.

/language/en