A helper interface for requesting mesh modifications from the device. This is intended to be used in a three-stage command pattern:
More...
template<typename NgpMemSpace>
class mundy::mesh::NgpModRequestsT< NgpMemSpace >
Manages all modification requests in a given NGP memory space.
Stage 1. Claim tickets
Just like a ticketing system at a deli counter, you first claim tickets from a ticketing machine. You haven't actually made any purchases yet but you have stated your intent to make a certain number of orders (requests).
Stage 2. Make requests
After all of your claims are in and you've finalized the counts, you can then use your claimed tickets to make requests.
Stage 3. Fetch
After all requests are processed, use the same ticket to fetch the result of your request (if any).
During each stage, there are multiple types of requests you can make (requesting entities, requesting connections, destroying entities, etc). Each type of request has its own interface and its own ticket issuer. For example, if you want to request 10 new entities and 10 new connections, you would claim 10 tickets from the entity ticket issuer and 10 tickets from the connection ticket issuer. You would then use the entity tickets to make your entity requests and the connection tickets to make your connection requests (potentially requesting connections to requested entities), allowing you to mix and match requests as needed.
- Note
- For the time being, you must use each ticket you claim (aka, you cannot over-claim).
-
You can claim tickets and make requests from either the host or device, but not both simultaneously.
Example usage 1: Create N spheres (N elems + N nodes) and connect each sphere to its node
size_t num_spheres = ...;
stk::mesh::Part& sphere_part = ...;
req_spheres.element_tickets().claim(num_spheres);
req_spheres.node_tickets().claim(num_spheres);
req_conns.tickets().claim(num_spheres);
Kokkos::parallel_for(
"RequestSpheres", Kokkos::RangePolicy<size_t>(0, num_spheres), KOKKOS_LAMBDA(size_t ticket) {
FutureEntity future_sphere = req_spheres.request_element(ticket);
FutureEntity future_node = req_spheres.request_node(ticket);
req_conns.request(ticket, future_sphere, future_node, 0);
});
Kokkos::parallel_for(
"UseSpheres", Kokkos::RangePolicy<size_t>(0, num_spheres), KOKKOS_LAMBDA(size_t ticket) {
stk::mesh::Entity sphere = req_spheres.get_entity(ticket, stk::topology::ELEMENT_RANK);
stk::mesh::Entity node = req_spheres.get_entity(ticket, stk::topology::NODE_RANK);
});
void process_requests(stk::mesh::BulkData &bulk_data)
Process all requests in all request classes. The order goes: 1) Entity requests 2) Connection request...
Definition NgpModRequests.hpp:1733
void activate_host()
Sets the active memory space to host for all request helpers and ticket issuers.
Definition NgpModRequests.hpp:1654
void activate_device()
Sets the active memory space to device for all request helpers and ticket issuers.
Definition NgpModRequests.hpp:1670
void finalize_counts()
Finalize counts for all request classes. Users may no longer claim tickets after this call.
Definition NgpModRequests.hpp:1706
NgpRequestEntitiesNewIdsT< NgpMemSpace > request_entities_new_ids(const stk::mesh::PartVector &parts) const
Get the entity request class for the given partition key (for requests of entities with new Ids).
Definition NgpModRequests.hpp:1583
NgpRequestConnectionsT< NgpMemSpace > request_connections() const
Get the connection request class.
Definition NgpModRequests.hpp:1631
NgpModRequestsT< stk::ngp::MemSpace > NgpModRequests
Definition NgpModRequests.hpp:2230
Definition NgpModRequests.hpp:461
Example usage 2: Divide all bacteria that exceeds twice the starting length into two bacteria Bacteria are spherocylinder segments (PARTICLE topology elements with a single node at their center) They have a "length", "radius", and "orientation" field Their center nodes have a "coords" field
Because division is delayed, we also need bacteria to store the ticket for fetching their new child later
We will assume that these are already declared and that you have wrapped them into a single bacteria aggregate
auto ngp_mesh = ;
size_t num_bacteria = ...;
double starting_length = ...;
stk::mesh::Part& bacteria_part = ...;
stk::mesh::for_each_entity_run(
ngp_mesh, stk::topology::ELEM_RANK, ngp_bacteria_data.get<SELECTOR>(),
KOKKOS_LAMBDA(stk::mesh::FastMeshIndex bacteria_index) {
double centerline_length = ngp_bacteria_data.get<LENGTH>(bacteria_index);
double radius = ngp_bacteria_data.get<RADIUS>(bacteria_index);
double total_length = centerline_length + 2.0 * radius;
if (total_length > 2.0 * starting_length) {
size_t ticket = req_bacteria.element_tickets().claim();
req_bacteria.node_tickets().claim();
req_conns.tickets().claim();
ngp_bacteria_data.get<CHILD_TICKET>(bacteria_index) = ticket;
}
});
stk::mesh::for_each_entity_run(
ngp_mesh, stk::topology::ELEM_RANK, ngp_bacteria_data.get<SELECTOR>(),
KOKKOS_LAMBDA(stk::mesh::FastMeshIndex bacteria_index) {
double centerline_length = ngp_bacteria_data.get<LENGTH>(bacteria_index);
double radius = ngp_bacteria_data.get<RADIUS>(bacteria_index);
double total_length = centerline_length + 2.0 * radius;
if (total_length > 2.0 * starting_length) {
size_t ticket = ngp_bacteria_data.get<CHILD_TICKET>(bacteria_index);
FutureEntity future_bacteria = req_bacteria.request_element(ticket);
FutureEntity future_node = req_bacteria.request_node(ticket);
req_conns.request(ticket, future_bacteria, future_node, 0);
}
});
stk::mesh::for_each_entity_run(
ngp_mesh, stk::topology::ELEM_RANK, ngp_bacteria_data.get<SELECTOR>(),
KOKKOS_LAMBDA(stk::mesh::FastMeshIndex bacteria_index) {
double centerline_length = ngp_bacteria_data.get<LENGTH>(bacteria_index);
double radius = ngp_bacteria_data.get<RADIUS>(bacteria_index);
double total_length = centerline_length + 2.0 * radius;
if (total_length > 2.0 * starting_length) {
size_t ticket = ngp_bacteria_data.get<CHILD_TICKET>(bacteria_index);
stk::mesh::Entity new_bacteria = req_bacteria.get_entity(ticket, stk::topology::ELEMENT_RANK);
stk::mesh::Entity center_node = req_bacteria.get_entity(ticket, stk::topology::NODE_RANK);
}
});
auto get_updated_ngp_aggregate(const Aggregate< TaggedComponents... > &aggregate)
A helper function for getting the NGP aggregate from a regular aggregate.
Definition Aggregate.hpp:743
The above design is amicable to a future python interface:
num_spheres = ...
our_proc_id = bulk_data.parallel_rank()
reqs = NgpModRequests()
req_spheres = reqs.request_entities(sphere_part)
req_nodes = reqs.request_entities()
req_conns = reqs.request_connections()
with reqs.host():
req_spheres.tickets().claim(num_spheres)
req_nodes.tickets().claim(num_spheres)
req_conns.tickets().claim(num_spheres)
reqs.finalize_counts()
with reqs.device():
plan = reqs.plan()
t = req_spheres.tickets().range(num_spheres)
future_spheres = req_spheres.request(t, our_proc_id)
future_nodes = req_nodes.request(t, our_proc_id)
req_conns.request(t, future_spheres, future_nodes)
ticket_expr1.exec()
reqs.process_requests();
with reqs.device():
ticket_expr2 = make_ticket_expr(0, num_spheres)
spheres = req_spheres.get_entity(ticket_expr2)
nodes = req_nodes.get_entity(ticket_expr2)
center(nodes) = ...
radius(spheres) = ...
ticket_expr2.exec()