The TDomain class
Main author: Simon Rohou
A TDomain is the temporal partition shared by one or more sliced tubes.
It stores an ordered list of TSlice objects. Each stored element is either
a non-degenerate temporal slice \([t_i,t_{i+1}]\), or
a degenerate temporal slice \([t_i,t_i]\), called a gate.
Gates are optional. When they are explicitly represented, the partition may alternate between
gate / slice / gate / slice / .... This is the structure created by
create_tdomain(t0_tf, dt, True).
Although optional, gates are useful when one needs to represent tube values explicitly at specific time instants. This is particularly relevant for guaranteed integration.
Creating temporal domains
A temporal domain can be created in three common ways:
from the default constructor helper
create_tdomain();from a single time interval
create_tdomain([t0,tf]);from a sampled interval
create_tdomain([t0,tf], dt, with_gates).
The following examples show the expected structures for the sampled cases above, both with and without gates.
td0 = create_tdomain() # one unbounded slice [-oo,oo]
td1 = create_tdomain([0,1]) # one slice [0,1]
td2 = create_tdomain([0,1], 0.5, False) # [0,0.5],[0.5,1]
td3 = create_tdomain([0,1], 0.5, True) # [0],[0,0.5],[0.5],[0.5,1],[1]
auto td0 = create_tdomain(); // one unbounded slice [-oo,oo]
auto td1 = create_tdomain({0,1}); // one slice [0,1]
auto td2 = create_tdomain({0,1}, 0.5, false); // [0,0.5],[0.5,1]
auto td3 = create_tdomain({0,1}, 0.5, true); // [0],[0,0.5],[0.5],[0.5,1],[1]
Inspecting the partition
A temporal domain exposes:
its global time interval
t0_tf(),the number of stored temporal elements
nb_tslices(),the number of attached tubes
nb_tubes(),the temporal slice containing a given time
tslice(t),and a vector copy of the stored temporal slices
tslices_vector().
td = create_tdomain([0,1], 0.5, True)
dom = td.t0_tf() # [0,1]
n = td.nb_tslices() # 5
m = td.nb_tubes() # 0 initially
td.tslice(0.0) # [0]
td.tslice(0.1) # [0,0.5]
td.tslice(0.5) # [0.5]
td.tslice(0.6) # [0.5,1]
td.tslice(1.0) # [1]
auto td = create_tdomain({0,1}, 0.5, true); // returns a std::shared_ptr<TDomain>
Interval dom = td->t0_tf(); // [0,1]
size_t n = td->nb_tslices(); // 5
size_t m = td->nb_tubes(); // 0 initially
auto it = td->tslice(0.0); // [0]
it = td->tslice(0.1); // [0,0.5]
it = td->tslice(0.5); // [0.5]
it = td->tslice(0.6); // [0.5,1]
it = td->tslice(1.0); // [1]
Note that tslice(t) returns the gate when t matches an explicit gate, and
otherwise returns the unique non-degenerate slice containing t.
Sampling and refinement
The temporal partition can be refined dynamically with:
sample(t, with_gate=False)for one time value,sample([ta,tb], dt, with_gates=False)for repeated sampling over an interval.
Sampling can occur:
inside the current domain, which splits an existing slice;
outside the current domain, which extends the partition;
with gates, which inserts a degenerate temporal slice at the sampling time.
td = create_tdomain()
td.sample(1.0, False) # [-oo,1],[1,oo]
td.sample(10.0, True) # [-oo,1],[1,10],[10],[10,oo]
auto td = create_tdomain(); // returns a std::shared_ptr<TDomain>
td->sample(1., false); // [-oo,1],[1,oo]
td->sample(10., true); // [-oo,1],[1,10],[10],[10,oo]
One important implementation detail is that refinement preserves the attached tubes by cloning the
corresponding slice objects onto the new temporal elements. The new slices are then reattached to
the newly inserted TSlice iterators.
Gates
Explicit gates are useful when you want to represent endpoint values separately from the interior codomain of a slice. The current API provides:
all_gates_defined()to detect a fully gate-augmented partition,delete_gates()to remove all explicit gates.
Therefore, a \(t\)-domain built from create_tdomain([0,1], 0.5, True) contains five temporal elements and is a
typical example of a gate-augmented partition.
In this implementation, a gate is not a separate data type: it is simply a degenerate
TSlice, i.e., an interval \([t,t]\).