This notebook is interactive, and contains both code and text. To run a piece of code, click on the box, and then hit Ctrl-Enter. To edit a piece of text, just double click.
In these exercises, we're going to walk through the creation of a simple Regent application: a circuit simulation on an unstructured graph. We'll describe the differential equations we're solving in the next part of the exercise. First, let's look at the data structures we're going to be using in our simulation.
In Regent, data structures are stored in regions. Regions are like arrays in other languages: they contain elements indexed by keys, and each element stores a set of fields. We call the set of keys the index space and the set of fields the field space. A region is just the cross product of these two spaces.
Regent has two kinds of index spaces: structured and unstructured. We'll be using mostly unstructured index spaces in these exercises. Unstructured index spaces are initially empty; the elements inside must be allocated explicitly (either individually or in bulk).
This stage of the exercise has four goals:
Along with each section, we'll include a syntax guide to help teach you the syntax required in each part. The following snippets will help you get started with creating regions.
In [ ]:
var V = E -- Creates a variable named V, with initial value E.
ispace(ptr, N) -- Creates an empty index space with room for N pointers.
fspace { F1: T1, ... } -- Creates a field space with fields F1 (of type T1), etc.
region(IS, FS) -- Creates a region with index space IS and field space FS.
new(ptr(T, R)) -- Allocates a pointer in R. Points to a value of type T.
new(ptr(T, R), N) -- As above, but allocates a block of N pointers.
In [ ]:
-- Every Regent program starts with the following line, which loads
-- the language definition.
import "regent"
-- We're going to need access to a few C functions (e.g. printf).
local c = regentlib.c
-- These two field spaces hold currents and voltages,
-- respectively. You'll need to reference them below.
struct Currents {
_0 : float,
_1 : float,
_2 : float,
}
struct Voltages {
_1 : float,
_2 : float,
}
-- TODO: Add the following fields to the 'Node' field space:
-- * 'capacitance' of type float
-- * 'leakage' of type float
-- * 'charge' of type float
-- * 'voltage' of type float
fspace Node
{
}
-- TODO: Add the following fields to the 'Wire' field space:
-- * 'in_node' of pointer type to region(Node)
-- * 'out_node' of pointer type to region(Node)
-- * 'capacitance' of type float
-- * 'inductance' of type float
-- * 'resistance' of type float
-- * 'current' of structure type 'Currents'
-- * 'voltage' of structure type 'Voltages'
fspace Wire(rn : region(Node))
{
}
-- These are some helper modules for the exercise.
local CktConfig = require("session1/circuit_config")
local helper = require("session1/circuit_helper")
task toplevel()
-- Variable 'conf' contains the configuration of the circuit we're simulating.
var conf : CktConfig
conf:initialize_from_command()
conf:show()
-- TODO: Create two logical regions for nodes and wires. The index
-- spaces should be large enough to hold the nodes and wires.
-- The sizes can be computed from the following fields of conf:
-- * conf.num_pieces (the number of pieces in the graph)
-- * conf.nodes_per_piece (the number of nodes per piece)
-- * conf.wires_per_piece (the number of wires per piece)
var rn
var rw
-- TODO: Allocate enough number of elements in the two regions. Use
-- the 'new' operator to allocate the elements. (Hint: Refer to the
-- syntax guide for the syntax.)
c.printf("Generating a random circuit...\n")
helper.generate_random_circuit(rn, rw, conf)
-- Once you've filled in the code above, this will print out the graph.
helper.dump_graph(conf, rn, rw)
end
regentlib.start(toplevel)
Next up: add tasks to complete the simulation.