Designing the FragmentedNuclei Class
This page describes the design of the FragmentedNuclei class.
Why Do We Need the FragmentedNuclei Class?
The need for the FragmentedNuclei class was motivated by the
chemical system hierarchy consideration of
Designing the Fragmenting Component. In short, each layer of the
ChemicalSystem class will require a corresponding container for holding
fragments. This is because each layer of the ChemicalSystem introduces new
state.
FragmentedNuclei Considerations
- nuclei to fragment map
The
FragmentedNucleimust track which nuclei are in which fragments.
- caps
Responsibility for satisfying the caps consideration from Designing the Fragmenting Component was given to the
FragmentedNucleiclass.The same cap may appear multiple times in a set of fragments. The
FragmentedNucleiobject should store a single set of caps and map each fragment to the caps it needs.
- non-disjoint
The non-disjoint fragments consideration from Designing the Fragmenting Component is ultimately the responsibility of the
FragmentedNucleiobject.
- fragments can be used as Nuclei objects
Once a
FragmentedNucleiobject has been created users will likely want to call routines expectingNucleiobjects in a loop. This is facilitated by ensuring that the fragments can be implicitly converted toNucleiobjects.
FragmentedNuclei API
To construct a FragmentedNuclei:
// It's assumed that users already have a Nuclei object
Nuclei some_nuclei = make_a_nuclei_object();
FragmentedNuclei null; // See FragmentedBase for more details
FragmentedNuclei empty(some_nuclei); // Empty
// Two fragments, first contains nuclei 0, 1, and 2, the second contains
// nuclei 3, 4, and 5
auto nuclei_to_frag_map = {{0, 1, 2}, {3, 4, 5}};
FragmentedNuclei has_frags(some_nuclei, nuclei_to_frag_map);
// If the user already has caps they're in a CapSet
CapSet caps = make_a_cap_set_object();
// Same as "has_frags", but also has caps
FragmentedNuclei has_frags_and_caps(some_nuclei, nuclei_to_frag_map, caps);
A couple of notes on the above:
make_an_nuclei_objectandmake_cap_a_cap_set_objectare opaque functions meant to respectively encapsulate the process of creating aNucleiandCapSetobject. The state of theNucleiandCapSetobjects are largely irrelevant for our present purposes.We think most users will create an empty
FragmentedNucleiobject and then fill it as part of an algorithm versus having all the state already available at construction. By analogy think of fillingstd::vectorviapush_backvs. the initializer-list or range constructor.It is not necessary for the user to tell the
FragmentedNucleiobject which fragments have which caps. This is because theFragmentedNucleiobject can determine this mapping fromnuclei_to_frag_mapand theCapSetobject.
Following from the second note, users will need to be able to add fragments and
caps to the FragmentedNuclei object. To that end we propose the following
APIs:
// Create a fragment which contains nuclei with offsets 0, 1, and 2
empty.emplace_back({0, 1, 2});
// Can also be added as a range, and the user can use the actual nucleus
// objects (n.b., mapping to indices will involve floating point values so it
// is best to use the ``some_nuclei`` directly)
auto itr = some_nuclei.begin()
empty.emplace_back(itr, itr + 3);
// Adds a Cap
some_nuclei.add_cap(Cap(0, 1, Nucleus{...}));
// Short-hand for...
some_nuclei.cap_set().push_back(Cap(0, 1, Nucleus{...}));
Accessing the state:
// Range-based for loop over fragments
for(NucleiView frag_i : fragments){
// fragments are interchangeable with Nuclei
function_expecting_nuclei_object(frag_i);
}
// Offset access
NucleiView frag_0 = fragments[0];
Note that accessing fragments as NucleiView objects means that the user will
get an object which is the union of actual nuclei and the nuclei from the caps.
This is what is needed to satisfy the fragments can be used as Nuclei objects consideration.
As shown above, if the user needs to determine which nuclei in the
NucleiView are real vs. from a cap the user can directly access the
CapSet.
FragmentedNuclei Design
Fig. 12 The state of the FragmentedNuclei class and its relation to other
classes.
Fig. 12 shows the design of the
FragmentedNuclei class and how the FragmentedNuclei class relates to
other classes. Internally FragmentedNuclei stores each fragment’s members
by offset, which saves memory and satisfies nuclei to fragment map.
When a user requests a fragment they get back a NucleiView object (the
fragments can be used as Nuclei objects consideration). The remaining piece of state in the
FragmentedNuclei object is a CapSet object (stems from the
caps consideration).
FragmentedNuclei Summary
- nuclei to fragment map
Internally the
FragmentedNucleiclass tracks the nuclei in each fragment via their offset in the supersystem.- caps
Each
FragmentedNucleiobject will contain aCapSetobject. TheCapSetobject is responsible for managing the caps aFragmentedNucleiobject needs.- non-disjoint
The
FragmentedNucleiclass makes no assumptions about whether or not the fragments are disjoint.- fragments can be used as Nuclei objects
Fragments are returned as
NucleiViewobjects.NucleiViewobjects are implicitly convertible toNucleiobjects.