2.3. Example: workflow with two models

The executable representation of simulation workflow in MuPIF is a Python script in Python language implemented using basic bulding blocks (called components) defined by MuPIF. These components represent fundamental entities in the model space (such as individual models (simulation tools), instances of data types, solution steps, etc). The top level abstract classes are defind in MuPIF to represent these components, defining a common interface allowing to manipulate individual representations using a single common interface. The top level classes and their interfaces are described in Section 2.4.

In this section, we present a simple, minimum working example, illustrating the basic concept. The example presented in this section is assumed to be executed locally. How to extend this and other examples into distributed version is discussed in Section 2.7.

The following example illustrates the so-called weak-coupling, where for each solution step, the first model (m1) evaluates the value of concentration that is passed to the second model (m2) which, based on provided concentration values (DataID.PID_Concentration), evaluates the average cumulative concentration (DataID.PID_CumulativeConcentration). This is repeated for each solution step. The example also illustrates, how solution steps can be generated in order to satisfy time step stability requirements of individual applications.

# Simple example illustrating simulation scenario

 import mupif as mp
 import model1
 import model2

 time = 0*mp.U.s
 timestepnumber = 0
 targetTime = 1.0*mp.U.s

 m1 = model1.Model1()  # create an instance of model #1
 m2 = model2.Model2()  # create an instance of model #2

 m1.initialize()
 m2.initialize()

 # loop over time steps
 while abs(time.inUnitsOf(mp.U.s).getValue() - targetTime.inUnitsOf(mp.U.s).getValue()) > 1.e-6:
     #determine critical time step
     dt2 = m2.getCriticalTimeStep()
     dt = min(m1.getCriticalTimeStep(), dt2)
     # update time
     time = time+dt
     if (time > targetTime):
         # make sure we reach targetTime at the end
         time = targetTime
     timestepnumber = timestepnumber + 1

     # create a time step
     istep = mp.TimeStep.TimeStep(time, dt, timestepnumber)

     try:
         #solve problem 1
         m1.solveStep(istep)
         #request temperature field from m1
         c = m1.get(mp.DataID.PID_Concentration, istep)
         # register temperature field in m2
         m2.set(c)
         # solve second sub-problem
         m2.solveStep(istep)
         prop = m2.get(mp.DataID.PID_CumulativeConcentration, istep)
         print ("Time: %5.2f concentraion %5.2f, running average %5.2f" % (istep.getTime(), c.getValue(), prop.getValue()))

     except APIError.APIError as e:
         logger.error("Following API error occurred: %s" % e )
         break

 # terminate the models
 m1.terminate();
 m2.terminate();

The full listing of this example can be found in examples/Example01. The output is illustrated in Fig. 2.1.

../_images/ex1-out.png

Fig. 2.1 Output from Example01.py

The platform installation comes with many examples, located in examples subdirectory of platform installation and also accessible online in the platform repository. They illustrate various aspects, including field mapping, vtk output, etc.