@@ -67,6 +67,9 @@ namespace detail
6767// -----------------------------------------------------------------------------
6868
6969// -----------------------------------------------------------------------------
70+ // for each element:
71+ // for each material:
72+ // do_for_each_material()
7073template <class ForEachValue >
7174void
7275walk_matset_value_by_element (const MatsetAccessor &m_acc,
@@ -86,6 +89,10 @@ walk_matset_value_by_element(const MatsetAccessor &m_acc,
8689}
8790
8891// -----------------------------------------------------------------------------
92+ // for each element:
93+ // for each material:
94+ // do_for_each_material()
95+ // do_for_each_elem()
8996template <class ForEachValue , class ForEachElement >
9097void
9198walk_matset_by_element (const MatsetAccessor &m_acc,
@@ -142,6 +149,12 @@ walk_matset_by_element(const MatsetAccessor &m_acc,
142149}
143150
144151// -----------------------------------------------------------------------------
152+ // for each element:
153+ // for each material:
154+ // for each species:
155+ // do_for_each_species()
156+ // do_for_each_material()
157+ // do_for_each_elem()
145158template <class ForEachSpeciesValue , class ForEachValue , class ForEachElement >
146159void
147160walk_matset_species_by_element (const MatsetAccessor &m_acc,
@@ -164,6 +177,7 @@ walk_matset_species_by_element(const MatsetAccessor &m_acc,
164177 for (index_t elem_idx = 0 ; elem_idx < num_elems; elem_idx ++)
165178 {
166179 index_t nmats_in_elem = 0 ;
180+ index_t nspec_in_elem = 0 ;
167181 for (index_t mat_idx = 0 ; mat_idx < nmats; mat_idx ++)
168182 {
169183 const float64 vol_frac = m_acc.get_vol_frac (elem_idx, mat_idx);
@@ -180,9 +194,10 @@ walk_matset_species_by_element(const MatsetAccessor &m_acc,
180194 // nmats_in_elem is running count of materials in the current zone
181195 for_each_value (elem_idx, mat_idx, nmats_in_elem);
182196 nmats_in_elem ++;
197+ nspec_in_elem += num_spec_for_mat;
183198 }
184199 }
185- for_each_element (elem_idx, nmats_in_elem);
200+ for_each_element (elem_idx, nmats_in_elem, nspec_in_elem );
186201 }
187202 }
188203 // sparse by element
@@ -191,6 +206,7 @@ walk_matset_species_by_element(const MatsetAccessor &m_acc,
191206 for (index_t elem_idx = 0 ; elem_idx < num_elems; elem_idx ++)
192207 {
193208 const index_t nmats_in_elem = m_acc.num_mats_for_elem (elem_idx);
209+ index_t nspec_in_elem = 0 ;
194210 for (index_t mat_idx = 0 ; mat_idx < nmats_in_elem; mat_idx ++)
195211 {
196212 const index_t num_spec_for_mat = m_acc.num_spec_for_mat (elem_idx, mat_idx);
@@ -204,13 +220,18 @@ walk_matset_species_by_element(const MatsetAccessor &m_acc,
204220 // we pass it twice because it is also the running count of materials
205221 // in the current zone
206222 for_each_value (elem_idx, mat_idx, mat_idx);
223+
224+ nspec_in_elem += num_spec_for_mat;
207225 }
208- for_each_element (elem_idx, nmats_in_elem);
226+ for_each_element (elem_idx, nmats_in_elem, nspec_in_elem );
209227 }
210228 }
211229}
212230
213231// -----------------------------------------------------------------------------
232+ // for each material:
233+ // for each element:
234+ // do_for_each_elem()
214235template <class ForEachValue >
215236void
216237walk_matset_value_by_material (const MatsetAccessor &m_acc,
@@ -230,6 +251,10 @@ walk_matset_value_by_material(const MatsetAccessor &m_acc,
230251}
231252
232253// -----------------------------------------------------------------------------
254+ // for each material:
255+ // for each element:
256+ // do_for_each_elem()
257+ // do_for_each_material()
233258template <class ForEachValue , class ForEachMaterial >
234259void
235260walk_matset_by_material (const MatsetAccessor &m_acc,
@@ -247,13 +272,13 @@ walk_matset_by_material(const MatsetAccessor &m_acc,
247272 // we *can* walk this elem-dom representation by material, and sometimes
248273 // we have to. But it is not very efficient.
249274
250- const index_t num_zones = m_acc.num_elems ();
275+ const index_t num_elems = m_acc.num_elems ();
251276 // Material ids need not be within in the range [0, N-1), so we iterate
252277 // over the order materials appear in the matset.
253278 for (index_t mat_idx = 0 ; mat_idx < num_materials; mat_idx ++)
254279 {
255280 index_t num_elems_for_mat = 0 ;
256- for (index_t elem_idx = 0 ; elem_idx < num_zones ; elem_idx ++)
281+ for (index_t elem_idx = 0 ; elem_idx < num_elems ; elem_idx ++)
257282 {
258283 const float64 vol_frac = m_acc.get_vol_frac (elem_idx, mat_idx);
259284 if (vol_frac > epsilon)
@@ -281,7 +306,7 @@ walk_matset_by_material(const MatsetAccessor &m_acc,
281306 {
282307 // Material ids need not be within in the range [0, N-1), so we iterate
283308 // over the order materials appear in the matset.
284- for (int mat_idx = 0 ; mat_idx < num_materials; mat_idx ++)
309+ for (index_t mat_idx = 0 ; mat_idx < num_materials; mat_idx ++)
285310 {
286311 const index_t num_elems_for_mat = m_acc.num_elems_for_mat (mat_idx);
287312 for (index_t elem_idx = 0 ; elem_idx < num_elems_for_mat; elem_idx ++)
@@ -304,6 +329,12 @@ walk_matset_by_material(const MatsetAccessor &m_acc,
304329}
305330
306331// -----------------------------------------------------------------------------
332+ // for each material:
333+ // for each element:
334+ // for each species:
335+ // do_for_each_species()
336+ // do_for_each_elem()
337+ // do_for_each_material()
307338template <class ForEachSpeciesValue , class ForEachValue , class ForEachMaterial >
308339void
309340walk_matset_species_by_material (const MatsetAccessor &m_acc,
@@ -322,13 +353,13 @@ walk_matset_species_by_material(const MatsetAccessor &m_acc,
322353 // we *can* walk this elem-dom representation by material, and sometimes
323354 // we have to. But it is not very efficient.
324355
325- const index_t num_zones = m_acc.num_elems ();
356+ const index_t num_elems = m_acc.num_elems ();
326357 // Material ids need not be within in the range [0, N-1), so we iterate
327358 // over the order materials appear in the matset.
328359 for (index_t mat_idx = 0 ; mat_idx < num_materials; mat_idx ++)
329360 {
330361 index_t num_elems_for_mat = 0 ;
331- for (index_t elem_idx = 0 ; elem_idx < num_zones ; elem_idx ++)
362+ for (index_t elem_idx = 0 ; elem_idx < num_elems ; elem_idx ++)
332363 {
333364 const float64 vol_frac = m_acc.get_vol_frac (elem_idx, mat_idx);
334365 if (vol_frac > epsilon)
@@ -362,7 +393,7 @@ walk_matset_species_by_material(const MatsetAccessor &m_acc,
362393 {
363394 // Material ids need not be within in the range [0, N-1), so we iterate
364395 // over the order materials appear in the matset.
365- for (int mat_idx = 0 ; mat_idx < num_materials; mat_idx ++)
396+ for (index_t mat_idx = 0 ; mat_idx < num_materials; mat_idx ++)
366397 {
367398 const index_t num_elems_for_mat = m_acc.num_elems_for_mat (mat_idx);
368399 for (index_t elem_idx = 0 ; elem_idx < num_elems_for_mat; elem_idx ++)
@@ -390,6 +421,101 @@ walk_matset_species_by_material(const MatsetAccessor &m_acc,
390421 }
391422}
392423
424+ // -----------------------------------------------------------------------------
425+ // for each material:
426+ // for each species:
427+ // for each element:
428+ // do_for_each_elem()
429+ // do_for_each_species()
430+ // do_for_each_material()
431+ template <class ForEachElementValue ,
432+ class ForEachMaterialSpecies ,
433+ class ForEachMaterial >
434+ void
435+ walk_matset_element_by_material_species (const MatsetAccessor &m_acc,
436+ ForEachElementValue &&for_each_element_value,
437+ ForEachMaterialSpecies &&for_each_material_species,
438+ ForEachMaterial &&for_each_material,
439+ const float64 epsilon = CONDUIT_EPSILON)
440+ {
441+ const index_t num_materials = m_acc.num_mats ();
442+
443+ if (m_acc.is_element_dominant ())
444+ {
445+ // elem-dom multi-buffer "full"
446+ if (m_acc.is_multi_buffer ())
447+ {
448+ // we *can* walk this elem-dom representation by material, and sometimes
449+ // we have to. But it is not very efficient.
450+
451+ const index_t num_elems = m_acc.num_elems ();
452+ // Material ids need not be within in the range [0, N-1), so we iterate
453+ // over the order materials appear in the matset.
454+ for (index_t mat_idx = 0 ; mat_idx < num_materials; mat_idx ++)
455+ {
456+ const index_t num_spec_for_mat = m_acc.num_spec_for_mat (0 , mat_idx);
457+ for (index_t spec_idx = 0 ; spec_idx < num_spec_for_mat; spec_idx ++)
458+ {
459+ index_t num_elems_for_spec = 0 ;
460+ for (index_t elem_idx = 0 ; elem_idx < num_elems; elem_idx ++)
461+ {
462+ const float64 vol_frac = m_acc.get_vol_frac (elem_idx, mat_idx);
463+ if (vol_frac > epsilon)
464+ {
465+ // mat_idx is an index over all materials
466+ // spec_idx is an index over all species for material mat_idx
467+ // elem_idx is an index over all elements
468+ // num_elems_for_spec is running count of elements for the current species
469+ for_each_element_value (mat_idx, spec_idx, elem_idx, num_elems_for_spec);
470+ num_elems_for_spec ++;
471+ }
472+ }
473+ for_each_material_species (mat_idx, spec_idx, num_elems_for_spec);
474+ }
475+ for_each_material (mat_idx, num_spec_for_mat);
476+ }
477+ }
478+ // elem-dom uni-buffer "sparse by element"
479+ else
480+ {
481+ CONDUIT_ERROR (" Walking by material is not supported for element-dominant uni-buffer material sets." );
482+ }
483+ }
484+ else
485+ {
486+ // mat-dom multi-buffer "sparse by material"
487+ if (m_acc.is_multi_buffer ())
488+ {
489+ // Material ids need not be within in the range [0, N-1), so we iterate
490+ // over the order materials appear in the matset.
491+ for (index_t mat_idx = 0 ; mat_idx < num_materials; mat_idx ++)
492+ {
493+ const index_t num_spec_for_mat = m_acc.num_spec_for_mat (0 , mat_idx);
494+ for (index_t spec_idx = 0 ; spec_idx < num_spec_for_mat; spec_idx ++)
495+ {
496+ const index_t num_elems_for_spec = m_acc.num_elems_for_mat (mat_idx);
497+ for (index_t elem_idx = 0 ; elem_idx < num_elems_for_spec; elem_idx ++)
498+ {
499+ // mat_idx is an index over all materials
500+ // spec_idx is an index over all species for material mat_idx
501+ // elem_idx is an index over all elements the material is in
502+ // we pass elem_idx twice because it is also the running count of
503+ // elements for the current material species
504+ for_each_element_value (mat_idx, spec_idx, elem_idx, elem_idx);
505+ }
506+ for_each_material_species (mat_idx, spec_idx, num_elems_for_spec);
507+ }
508+ for_each_material (mat_idx, num_spec_for_mat);
509+ }
510+ }
511+ // mat-dom uni-buffer - currently unsupported
512+ else
513+ {
514+ CONDUIT_ERROR (" material-dominant uni-buffer material set is unsupported." );
515+ }
516+ }
517+ }
518+
393519// -------------------------------------------------------------------------
394520// helper for multi-buffer material sets that do not have
395521// material maps.
@@ -408,6 +534,27 @@ create_material_map(const conduit::Node &matset,
408534 }
409535}
410536
537+ // -------------------------------------------------------------------------
538+ // helper for multi-buffer species sets that do not have
539+ // species_names.
540+ void
541+ create_species_names (const conduit::Node &specset,
542+ conduit::Node &species_names)
543+ {
544+ // We must be multi-buffer, so we can assume we have a
545+ // "matset_values" child that is an object.
546+ const std::vector<std::string> &matnames = specset[" matset_values" ].child_names ();
547+ for (const auto &matname : matnames)
548+ {
549+ const std::vector<std::string> &specnames =
550+ specset[" matset_values" ][matname].child_names ();
551+ for (const auto &specname : specnames)
552+ {
553+ species_names[matname][specname];
554+ }
555+ }
556+ }
557+
411558// -----------------------------------------------------------------------------
412559// Single implementation that supports the case where just matset
413560// is passed, and the case where the field is passed.
@@ -2510,6 +2657,56 @@ get_material_names(const conduit::Node &specset,
25102657 }
25112658}
25122659
2660+ // -------------------------------------------------------------------------
2661+ // this will use set external if the species_names already exist
2662+ void
2663+ create_or_reuse_species_names (const conduit::Node &specset,
2664+ conduit::Node &species_names)
2665+ {
2666+ // extra seat belt here
2667+ if (! specset.dtype ().is_object ())
2668+ {
2669+ CONDUIT_ERROR (" blueprint::mesh::specset::create_or_reuse_species_names"
2670+ " passed specset node must be a valid specset tree." );
2671+ }
2672+
2673+ species_names.reset ();
2674+
2675+ if (specset.has_child (" species_names" ))
2676+ {
2677+ species_names.set_external (specset[" species_names" ]);
2678+ }
2679+ else
2680+ {
2681+ conduit::blueprint::mesh::matset::detail::create_species_names (specset, species_names);
2682+ }
2683+ }
2684+
2685+ // -------------------------------------------------------------------------
2686+ // this will use set if the species_names already exist
2687+ void
2688+ create_or_copy_species_names (const conduit::Node &specset,
2689+ conduit::Node &species_names)
2690+ {
2691+ // extra seat belt here
2692+ if (! specset.dtype ().is_object ())
2693+ {
2694+ CONDUIT_ERROR (" blueprint::mesh::specset::create_or_copy_species_names"
2695+ " passed specset node must be a valid specset tree." );
2696+ }
2697+
2698+ species_names.reset ();
2699+
2700+ if (specset.has_child (" species_names" ))
2701+ {
2702+ species_names.set (specset[" species_names" ]);
2703+ }
2704+ else
2705+ {
2706+ conduit::blueprint::mesh::matset::detail::create_species_names (specset, species_names);
2707+ }
2708+ }
2709+
25132710// -------------------------------------------------------------------------
25142711index_t
25152712count_materials_from_specset (const conduit::Node &specset)
0 commit comments