2.9.4.1. Configuring CustomUQ Engine

In order to use the CustomUQ engine option, the following two tasks need to be performed:

  • Configure UQ tab to accept the required inputs

  • Add UQ engine to customized UQ backend

These two steps are explained in more detail next.

Configuring UQ tab

The quoFEM interface can be customized to accept the required inputs for user-specified UQ engines. The “CustomUQ” option should be selected, as shown in Fig. 2.9.4.1.1. The UQ application name should then be input as “Other-UQ” as this will direct quoFEM to invoke the customized UQ backend where users can plug in their own functionality.

../../../../_images/CustomUQEngine.png

Fig. 2.9.4.1.1 Custom UQ Engine Configuration

Next, users must configure the interface to accept inputs required to run their UQ engine. This is done through a JSON configuration file that is specified through “Configuration Input File”. Once this file is input, the user interface will be automatically updated to accept the inputs specified in the JSON configuration. An example JSON configuration is shown below. This configuration file generates the interface shown in Fig. 2.9.4.1.1.

// Example JSON Configuration for Custom UQ Engine

{
    "Parameters" :  [
	{
	    "type" : "ComboBox",
	    "name" : "Combo Box Input",
	    "values" : ["Choice 1", "Choice 2", "Choice 3"]
	},
	{
	    "type" : "SpinBox",
	    "name" : "An Integer Input"
	},	
	{
	    "type" : "DoubleSpinBox",
	    "name" : "A Real Number Input"
	},
	{
	    "type" : "FileInput",
	    "name" : "A File Input"
	},	
	{
	    "type" : "LineEdit",
	    "name" : "UQ Driver"
	}
    ]
}

Currently, users are able to specify the following types of inputs:

  1. ComboBox: Allows selection of a particular option from a specified set

  2. Spin Box: Used to input integer values

  3. Double Spin Box: Used to input floating point numbers

  4. File Input: Used for inputting file locations

  5. Line Edit: Used to input text values

Lastly, users must specify the UQ driver name. This is required to direct the customized UQ backend to the correct UQ driver. The driver name must correspond the name provided in the customized backend, as described below.

Adding UQ Engine to Customized Backend

In addition to configuring the user interface to accept the required inputs, it is necessary to make the custom UQ engine accessible to the customized UQ backend in quoFEM. This is achieved by providing a UQ runner class in Python that follows the defined interface. Users must create a UQ runner class that inherits from the UqRunner class, which is shown below

# written: Michael Gardner @ UNR

# DO NOT CHANGE THE FACTORY, JUST IMPORT IT INTO ADDITIONAL DERIVED CLASSES
# Polymorhophic factory for running UQ apps
class UqRunnerFactory:
    factories = {}
    def addFactory(id, runnerFactory):
        UqRunnerFactory.factories.put[id] = runnerFactory
    addFactory = staticmethod(addFactory)
    # A Template Method:
    def createRunner(id):
        if id not in UqRunnerFactory.factories:
            UqRunnerFactory.factories[id] = \
              eval(id + '.Factory()')
        return UqRunnerFactory.factories[id].create()
    
    createRunner = staticmethod(createRunner)

# Abstract base class
class UqRunner(object):
    def runUQ(self, uqData, simulationData, randomVarsData, demandParams,
              workingDir, runType, localAppDir, remoteAppDir):
        """
        This function configures and runs a UQ simulation based on the 
        input UQ configuration, simulation configuration, random variables,
        and requested demand parameters
        
        Input:
        uqData:         JsonObject that UQ options as input into the quoFEM GUI
        simulationData: JsonObject that contains information on the analysis package to run and its
                    configuration as input in the quoFEM GUI
        randomVarsData: JsonObject that specifies the input random variables, their distributions,
                    and associated parameters as input in the quoFEM GUI
        demandParams:   JsonObject that specifies the demand parameters as input in the quoFEM GUI
        workingDir:     Directory in which to run simulations and store temporary results
        runType:        Specifies whether computations are being run locally or on an HPC cluster
        localAppDir:    Directory containing apps for local run
        remoteAppDir:   Directory containing apps for remote run
        """    
        pass

    # Factory for creating UQ runner
    class Factory:
        def create(self):
            pass

This runner class only needs to provide a runUQ method and a factory class that creates an instance of this class. The runUQ method is where the customized inputs from the user interface can be accessed and passed to the custom UQ driver.

Note

The parameters generated by the UQ engine must be stored in a file named params.in and placed in the current working directory. The file must follow the format shown in the example params.in file shown below. The first line specifies the number of random variables while the subsequent lines first contain the name of the random variable and the value of the current realization separated by a space.

2
randomVariable 2.719191180014362e+02
anotherRandomVariable 7.518852020241320e+01

As an example, UQpy has been implemented in the customized backend–the source code for the customized UqRunner class can be found in the quoFEM repository in the repositoryRoot/applications/performUQ/other directory.

Lastly, the name of the UQ driver needs to be added to configureAndRunUQ.py in the list of UQ driver options–this corresponds to the UQ driver name provided in the customized user interface. The configureAndRunUQ.py file is also located in repositoryRoot/applications/performUQ/other. With the derived UQ runner class and the name of the UQ driver added to the list of UQ driver options, the custom UQ engine has been plugged into the quoFEM backend and can now be invoked from the quoFEM user interface