Data Model¶
FleCSI provides a data model that integrates with the task and kernel abstractions to provide easy registration and access to various data types with automatic dependency tracking.
Example 1: Global data¶
Global fields are used to store global variables/objects that can
be accessed by any task.
Since there is only one value for each field, it is natural to use the data::single
layout.
template<typename T>
using single = field<T, data::single>;
const single<double>::definition<global> lue;
Writing to a global field requires a single task launch.
void
init(double v, single<double>::accessor<wo> gv) {
gv = v;
}
void
print(single<double>::accessor<ro> gv) {
flog(trace) << "global value: " << gv << std::endl;
}
int
advance() {
const auto v = lue(global_topology);
execute<init>(42.0, v);
execute<print>(v);
return 0;
}
Example 2: Index data¶
Index field is a field that is local to a color or process (MPI rank or Legion shard). It is defined as a filed on an index topology.
using namespace flecsi;
template<typename T>
using single = field<T, data::single>;
const single<std::size_t>::definition<topo::index> lue;
inline topo::index::slot custom_topology;
void
init(single<std::size_t>::accessor<wo> iv) {
flog(trace) << "initializing value on color " << color() << " of " << colors()
<< std::endl;
iv = color();
}
void
print(single<std::size_t>::accessor<ro> iv) {
flog(trace) << "index value: " << iv << " (color " << color() << " of "
<< colors() << ")" << std::endl;
}
int
advance() {
custom_topology.allocate(4);
execute<init>(lue(process_topology));
execute<print>(lue(process_topology));
execute<init>(lue(custom_topology));
execute<print>(lue(custom_topology));
return 0;
}
Example 3: Dense data¶
Dense field is a field defined on a dense topology index space. In this example we allocate pressure field on the cells index space of canonical topology.
const field<double>::definition<canon, canon::cells> pressure;
One can access the field inside of the FLeCSI task through passing topology and field accessors with access permissions (wo/rw/ro).
void
init(canon::accessor<wo> t, field<double>::accessor<wo> p) {
std::size_t off{0};
for(const auto c : t.entities<canon::cells>()) {
p[c] = (off++) * 2.0;
} // for
} // init
void
print(canon::accessor<ro> t, field<double>::accessor<ro> p) {
std::size_t off{0};
for(auto c : t.entities<canon::cells>()) {
flog(info) << "cell " << off++ << " has pressure " << p[c] << std::endl;
} // for
} // print
int
advance() {
coloring.allocate("test.txt");
canonical.allocate(coloring.get());
auto pf = pressure(canonical);
execute<init>(canonical, pf);
execute<print>(canonical, pf);
return 0;
}