OpenSim/EngineOutput

From OLPC
Jump to navigation Jump to search

OpenSim isn't quite at the JIT compilation stage, but we do have some pretty exciting output already.


Input forms

OpenSim currently reads in models stored in an XML format, like this:

<?xml version="1.0" encoding="UTF-8"?>

<opensim markup="1.0">
<model>
  <name>Simple Population</name>
  
    <name>population</name>
    <type>stock</type>
    <equation>
      births - deaths
    </equation>
    <initial>30</initial>
    <units>individuals</units>
  
  
    <name>births</name>
    <type>auxiliary</type>
    <equation>
      birth_rate * population
    </equation>
    <units>individuals</units>
  
  
    <name>birth_rate</name>
    <type>constant</type>
    <equation>
      .3
    </equation>
    <units>individuals</units>
  
  
    <name>deaths</name>
    <type>auxiliary</type>
    <equation>
      .1 * population
    </equation>
    <units>individuals</units>
  
  
    <name>OS_start</name>
    <type>constant</type>
    <equation>
      0
    </equation>
  
  
    <name>OS_end</name>
    <type>constant</type>
    <equation>
      50
    </equation>
  
  
    <name>OS_timestep</name>
    <type>constant</type>
    <equation>
      1
    </equation>
  
</model> 
</opensim>

This might be a handful for humans to read, but in the long run XML formatted models will be easier to create and edit over the web, and easier to share between modeling programs. Eventually we would like to read in Vensim and PowerSim model formats as well.


Python Output

OpenSim can already take basic models, like the one above, and output valid Python code. In fact, when you run the above model through OpenSim you get the following

OS_end = 50
OS_start = 0 
OS_timestep = 1
birth_rate = .3
population = 30.0

#using euler integration
for time in range(OS_start, OS_end, OS_timestep):
    births = birth_rate * population
    deaths = 0.1 * population
    population_NEXT = population + births - deaths

    #generally put print statements here

    #updating stocks
    population = population_NEXT

The Python output is nice and short, much more human readable than XML. For now the comments in there are inserted in the output, to let you know where modeling software generally records and outputs its time series data when it runs the model itself. The model will run like this, but you won't see any output (there are no print statements, and there are no Python errors), you would probably want to just print some variables to the terminal and pipe them into a file.


LLVM IR Output

Before we can JIT code using LLVM, we need to construct the model in LLVM IR format. The following is what you get when you run OpenSim and output LLVM IR:

define void @simulate() {
entry:
	%time = alloca double		; <double*> [#uses=4] 
	%population = alloca double		; <double*> [#uses=1]
	%deaths = alloca double		; <double*> [#uses=0]
	%births = alloca double		; <double*> [#uses=0]
	%birth_rate = alloca double		; <double*> [#uses=1]
	%OS_timestep = alloca double		; <double*> [#uses=2]
	%OS_start = alloca double		; <double*> [#uses=2]
	%OS_end = alloca double		; <double*> [#uses=2]
	store double 5.000000e+01, double* %OS_end
	store double 0.000000e+00, double* %OS_start
	store double 1.000000e+00, double* %OS_timestep
	store double 3.000000e-01, double* %birth_rate
	store double 3.000000e+01, double* %population
	%OS_start1 = load double* %OS_start		; <double> [#uses=1]
	store double %OS_start1, double* %time
	br label %forcond

forcond:		; preds = %forinc, %entry
	%time2 = load double* %time		; <double> [#uses=1]
	%OS_end3 = load double* %OS_end		; <double> [#uses=1]
	%forcond4 = fcmp olt double %time2, %OS_end3		; <i1> [#uses=1]
	br i1 %forcond4, label %forbody, label %forafter

forbody:		; preds = %forcond
	br label %forinc

forinc:		; preds = %forbody
	%time5 = load double* %time		; <double> [#uses=1]
	%OS_timestep6 = load double* %OS_timestep		; <double> [#uses=1]
	%new_time = add double %time5, %OS_timestep6		; <double> [#uses=1]
	store double %new_time, double* %time
	br label %forcond

forafter:		; preds = %forcond
} 

This is a work in progress - it allocates space for variables at the start of the function, sets initial values for constants and stocks, and sets up the for loop. Right after the forbody label is where all the equations will go, soon... Also in the near future I'll be removing the alloca calls and setting variable pointers to a malloc'd block of memory somewhere else, so that we can log all of our data from this function and when it completes still have access.