flat_state_mm_wrapper.h
Go to the documentation of this file.
1 /*
2 This file is part of the Ristra wonton project.
3 Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/wonton/blob/master/LICENSE
5 */
6 
7 
8 #ifndef WONTON_STATE_FLAT_FLAT_STATE_MM_WRAPPER_H_
9 #define WONTON_STATE_FLAT_FLAT_STATE_MM_WRAPPER_H_
10 
11 #include <vector>
12 #include <string>
13 #include <unordered_map>
14 #include <memory>
15 #include <type_traits>
16 
18 #include "wonton/support/wonton.h"
20 
25 namespace Wonton {
26 
32 template <class MeshWrapper>
33 class Flat_State_Wrapper: public StateManager<MeshWrapper> {
34  public:
45  explicit Flat_State_Wrapper(const MeshWrapper& mesh,
46  std::unordered_map<std::string, int> const& names = {},
47  std::unordered_map<int, std::vector<int>> const& material_cells = {})
48  : StateManager<MeshWrapper>(mesh, names, material_cells) { }
49 
50 
53 
54 
56  ~Flat_State_Wrapper() = default;
57 
58 
76  template <class State_Wrapper>
77  void initialize(State_Wrapper const & input,
78  std::vector<std::string> const& var_names) {
79 
80  // clear any existing state data
82 
83  // get the number of materials
84  int nmats = input.num_materials();
85 
86  // we may need to add volume fraction an centroid data to the list of
87  // distributed fields, so define a temp variable for these fields
88  std::vector<std::string> distribute_var_names(var_names.begin(), var_names.end());
89 
90  // is this a multimaterial problem, if so, add material names and cell indices
91  // to the flat state. Do this only once regardless of the number of fields.
92  if (nmats>0){
93 
94  // create the name to id map
95  std::unordered_map<std::string, int> name_map;
96  for (int i=0; i<nmats; ++i){
97 
98  // get the material name
99  std::string material_name = input.material_name(i);
100 
101  // add to the temp name map
102  name_map[material_name]=i;
103  }
104 
105  // add the names to the state manager
107 
108  // copy cell indices
109  for (int m=0; m<nmats; ++m){
110 
111  // get the cells for this material from the input state wrapper
112  std::vector<int> mat_cells;
113  input.mat_get_cells(m, &mat_cells);
114 
115  // add the cells to the flat state
117  }
118 
119  // if this is a multimaterial problem we will also need to distribute
120  // volume fraction and potentially centroids if they are defined
121  distribute_var_names.emplace_back("mat_volfracs");
122  if (input.get_entity("mat_centroids") != Entity_kind::UNKNOWN_KIND)
123  distribute_var_names.emplace_back("mat_centroids");
124 
125  }
126 
127  // add material fields to the flat state
128  for (std::string varname : distribute_var_names) {
129 
130  // get the entity kind
131  Entity_kind entity = input.get_entity(varname);
132 
133  // get the field type
134  Field_type type = input.field_type(entity, varname);
135 
137 
138  // We need a non-const state wrapper for the get_data_type function
139  auto& input_nonconst = const_cast<State_Wrapper&>(input);
140 
141  // We need to create a state vector but the type is variable
142  const std::type_info& data_type = input_nonconst.get_data_type(varname);
143 
144  // construct the state vector type by if statement
145  // Is there a better/more idiomatic way to do this???
146  if (data_type == typeid(double)){
147 
148  // create a uni state vector
149  std::shared_ptr<StateVectorMulti<double>> pv =
150  std::make_shared<StateVectorMulti<double>> (varname);
151 
152  // add to database (inside loop, since pv is typed diffently below and
153  // pv has local scope
155 
156  // loop over materials
157  for (int m=0; m<nmats; ++m){
158 
159  // get the data from the input state wrapper
160  double const* data;
161  input.mat_get_celldata(varname, m, &data);
162 
163  // add the data to the flat state
165  auto pv1 = StateManager<MeshWrapper>::get(varname);
166  auto pv2 = std::dynamic_pointer_cast<StateVectorMulti<double>>(pv1);
167  }
168 
169  } else if (data_type == typeid(Wonton::Point<2>)){
170 
171  // create a uni state vector
172  std::shared_ptr<StateVectorMulti<Wonton::Point<2>>> pv =
173  std::make_shared<StateVectorMulti<Wonton::Point<2>>> (varname);
174 
175  // add to database (inside loop, since pv is typed diffently below and
176  // pv has local scope
178 
179  // loop over materials
180  for (int m=0; m<nmats; ++m){
181 
182  // get the data from the input state wrapper
183  Wonton::Point<2> const* data;
184  input.mat_get_celldata(varname, m, &data);
185 
186  // add the data to the flat state
188  auto pv1 = StateManager<MeshWrapper>::get(varname);
189  auto pv2 = std::dynamic_pointer_cast<StateVectorMulti<Wonton::Point<2>>>(pv1);
190  }
191  } else if (data_type == typeid(Wonton::Point<3>)){
192 
193  // create a uni state vector
194  std::shared_ptr<StateVectorMulti<Wonton::Point<3>>> pv =
195  std::make_shared<StateVectorMulti<Wonton::Point<3>>> (varname);
196 
197  // add to database (inside loop, since pv is typed diffently below and
198  // pv has local scope
200 
201  // loop over materials
202  for (int m=0; m<nmats; ++m){
203 
204  // get the data from the input state wrapper
205  Wonton::Point<3> const* data;
206  input.mat_get_celldata(varname, m, &data);
207 
208  // add the data to the flat state
210  auto pv1 = StateManager<MeshWrapper>::get(varname);
211  auto pv2 = std::dynamic_pointer_cast<StateVectorMulti<Wonton::Point<3>>>(pv1);
212  }
213  } else {
214  throw std::runtime_error("found an unknown field type!");
215  }
216 
217  } else {
218 
219  // AT THE MOMENT WE ARE ASSUMING SINGLE MATERIAL FIELDS ARE ALWAYS DOUBLES
220  // get pointer to data for state from input state wrapper
221  double const* data;
222  input.mesh_get_data(entity, varname, &data);
223 
224  // Note, this get_data_size is of the input wrapper, which is defined
225  // not the base class state manager get_data_size which is not implemented
226  size_t dataSize = input.get_data_size(entity, varname);
227 
228  // create a uni state vector
229  std::shared_ptr<StateVectorUni<double>> pv =
230  std::make_shared<StateVectorUni<double>> (varname, data,
231  data+dataSize, entity);
232  // add to database
234  }
235  }
236  }
237 
238 
243  size_t get_num_vectors() {
245 
246 
253  std::vector<double> pack(std::string field_name) {
254 
255  // get the state vector base class shared pointer
256  std::shared_ptr<StateVectorBase> pv =
257  StateManager<MeshWrapper>::get(field_name);
258 
259  // get the data type
260  const std::type_info& data_type = pv->data_type();
261 
262  // get the field type
263  const Wonton:: Field_type field_type = pv->get_type();
264 
265  if (field_type == Wonton::Field_type::MESH_FIELD){
266 
267  // this is a mesh field
268 
269  if ( data_type == typeid(double)){
270 
271  // field data is doubles
272  return std::static_pointer_cast<StateVectorUni<double>>(pv)->get_data();
273  }
274 
275  } else if (field_type == Wonton::Field_type::MULTIMATERIAL_FIELD){
276 
277  // this is a multimaterial field
278 
279  if ( data_type == typeid(Wonton::Point<2>)){
280 
281  // field data is wonton 2d points
282 
283  // get the ordered keys
284  std::vector<int> const ids = get_material_ids();
285 
286  // get the raw mm data
287  std::unordered_map<int, std::vector<Wonton::Point<2>>> mm_data =
288  std::static_pointer_cast<StateVectorMulti<Wonton::Point<2>>>(pv)->get_data();
289 
290  // define the result
291  std::vector<double> result;
292 
293  // loop over material ids in the mm state in sort order
294  for (int id : ids){
295  for (auto& d : mm_data.at(id)){
296  result.emplace_back(d[0]);
297  result.emplace_back(d[1]);
298  }
299  }
300 
301  return result;
302  } else if ( data_type == typeid(Wonton::Point<3>)){
303 
304  // field data is wonton 3d points
305 
306  // get the ordered keys
307  std::vector<int> const ids = get_material_ids();
308 
309  // get the raw mm data
310  std::unordered_map<int, std::vector<Wonton::Point<3>>> mm_data =
311  std::static_pointer_cast<StateVectorMulti<Wonton::Point<3>>>(pv)->get_data();
312 
313  // define the result
314  std::vector<double> result;
315 
316  // loop over material ids in the mm state in sort order
317  for (int id : ids){
318  for (auto& d : mm_data.at(id)){
319  result.emplace_back(d[0]);
320  result.emplace_back(d[1]);
321  result.emplace_back(d[2]);
322  }
323  }
324 
325  return result;
326  } else if (data_type == typeid(double)){
327 
328  // field data is doubles
329 
330  // get the ordered keys
331  std::vector<int> const ids = get_material_ids();
332 
333  // get the raw mm data
334  std::unordered_map<int, std::vector<double>> mm_data =
335  std::static_pointer_cast<StateVectorMulti<double>>(pv)->get_data();
336 
337  // define the result
338  std::vector<double> result;
339 
340  // loop over material ids in the mm state in sort order
341  for (int id : ids){
342  for (auto& d : mm_data.at(id)){
343  result.emplace_back(d);
344  }
345  }
346 
347  return result;
348  }
349  }
350 
351  throw std::runtime_error("invalid field type");
352  }
353 
354 
363  void unpack(std::string field_name, const std::vector<double> & flat_data,
364  const std::vector<int> & all_material_ids={},
365  const std::vector<int> & all_material_shapes={},
366  const std::map<int, std::vector<int>>& distributedMaterialCellIds_={} ) {
367 
368  // get the state vector base class shared pointer
369  std::shared_ptr<StateVectorBase> pv =
370  StateManager<MeshWrapper>::get(field_name);
371 
372  // get the data type
373  const std::type_info& data_type = pv->data_type();
374 
375  // get the field type
376  const Wonton:: Field_type field_type = pv->get_type();
377 
378  if (field_type == Wonton::Field_type::MESH_FIELD){
379 
380  // this is a mesh field
381 
382  if ( data_type == typeid(double)){
383 
384  // copy the mesh data into the state vector
385  std::static_pointer_cast<StateVectorUni<double>>(pv)->get_data()=flat_data;
386  }
387 
388  } else if (field_type == Wonton::Field_type::MULTIMATERIAL_FIELD){
389 
390  // THIS SHOULD BE MADE PRETTIER DURING A CLEANUP SPRINT. THE FOLLOWING
391  // THREE CODE BLOCKS POINT<2>, POINT<3>, AND DOUBLE ARE NEARLY IDENTICAL
392  // POINT<2> AND POINT<3> COULD OBVIOUSLY BE TEMPLATED, THE DOUBLE CASE
393  // MAY NEED IT'S OWN FUNCTION. BUT, THE CASE SHOULD BE WRITTEN AS FUNCTIONS
394  // RATHER THAN INLINE
395 
396  // this is a multimaterial field
397 
398  if ( data_type == typeid(Wonton::Point<2>)){
399 
400  // field data is 2d wonton points
401 
402  // allocate the vector data
403  std::vector<Wonton::Point<2>> correctly_typed_data(flat_data.size()/2);
404 
405  // convert to the correct type
406  int const num_flat_data = flat_data.size();
407  for (int i = 0; i < num_flat_data; i += 2) {
408  correctly_typed_data[i/2] = Wonton::Point<2>(flat_data[i], flat_data[i+1]);
409  }
410 
411  // allocate the data for unpacking
412  std::unordered_map<int,std::vector<Wonton::Point<2>>> material_data;
413 
414 
416  // We need to turn the flattened material cells into a correctly shaped
417  // ragged right structure for use as the material cells in the flat
418  // state wrapper. Just as in the flat state mesh field (and associated
419  // cell ids), we aren't removing duplicates, just concatnating by material
421 
422 
423  // reset the running counter
424  int running_counter=0;
425 
426  // loop over material ids on different nodes
427  int const num_all_material_ids = all_material_ids.size();
428  for (int i = 0; i < num_all_material_ids; ++i) {
429 
430  // get the current working material
431  int mat_id = all_material_ids[i];
432 
433  // get the current number of material cells for this material
434  int nmat_cells = all_material_shapes[i];
435 
436  // get or create a reference to the correct material cell vector
437  auto& these_material_data = material_data[mat_id];
438 
439  // loop over the correct number of material cells
440  for (int j=0; j<nmat_cells; ++j){
441  these_material_data.push_back(correctly_typed_data[running_counter++]);
442  }
443 
444  }
445 
446  // the underlying api mat_add_celldata clears the existing data
447  for ( auto& kv: material_data){
448 
449  // the data needs to be merged within each material
450 
451  // material id
452  int m = kv.first;
453 
454  // existing material data
455  std::vector<Wonton::Point<2>> & current_material_data=kv.second;
456 
457  // vector to merge material data
458  std::vector<int> distributedMaterialCellIds =distributedMaterialCellIds_.at(m);
459 
460  // merged material data
461  std::vector<Wonton::Point<2>> merged_material_data(distributedMaterialCellIds.size());
462 
463  // merge the data
464  int c=0;
465  for (auto id: distributedMaterialCellIds)
466  merged_material_data[c++]=current_material_data[id];
467 
468  // add this cell data to the state manager
469  StateManager<MeshWrapper>::mat_add_celldata(field_name, m, merged_material_data.data());
470  }
471 
472  } else if ( data_type == typeid(Wonton::Point<3>)){
473 
474  // field data is 2d wonton points
475 
476  // allocate the vector data
477  std::vector<Wonton::Point<3>> correctly_typed_data(flat_data.size()/3);
478 
479  // convert to the correct type
480  int const num_flat_data = flat_data.size();
481  for (int i = 0; i < num_flat_data; i += 3) {
482  correctly_typed_data[i/3] = Wonton::Point<3>(flat_data[i], flat_data[i+1], flat_data[i+2]);
483  }
484 
485  // allocate the data for unpacking
486  std::unordered_map<int,std::vector<Wonton::Point<3>>> material_data;
487 
488 
490  // We need to turn the flattened material cells into a correctly shaped
491  // ragged right structure for use as the material cells in the flat
492  // state wrapper. Just as in the flat state mesh field (and associated
493  // cell ids), we aren't removing duplicates, just concatenating by material
495 
496 
497  // reset the running counter
498  int running_counter=0;
499 
500  // loop over material ids on different nodes
501  int const num_all_material_ids = all_material_ids.size();
502  for (int i = 0; i < num_all_material_ids; ++i) {
503 
504  // get the current working material
505  int mat_id = all_material_ids[i];
506 
507  // get the current number of material cells for this material
508  int nmat_cells = all_material_shapes[i];
509 
510  // get or create a reference to the correct material cell vector
511  auto& these_material_data = material_data[mat_id];
512 
513  // loop over the correct number of material cells
514  for (int j=0; j<nmat_cells; ++j){
515  these_material_data.push_back(correctly_typed_data[running_counter++]);
516  }
517 
518  }
519 
520  // add the material indices by keys
521  // the underlying api mat_add_celldata clears the existing data
522  for ( auto& kv: material_data){
523 
524  // the data needs to be merged within each material
525 
526  // material id
527  int m = kv.first;
528 
529  // existing material data
530  std::vector<Wonton::Point<3>> & current_material_data=kv.second;
531 
532  // vector to merge material data
533  std::vector<int> distributedMaterialCellIds =distributedMaterialCellIds_.at(m);
534 
535  // merged material data
536  std::vector<Wonton::Point<3>> merged_material_data(distributedMaterialCellIds.size());
537 
538  // merge the data
539  int c=0;
540  for (auto id: distributedMaterialCellIds)
541  merged_material_data[c++]=current_material_data[id];
542 
543  // add this cell data to the state manager
544  StateManager<MeshWrapper>::mat_add_celldata(field_name, m, merged_material_data.data());
545  }
546 
547  } else if ( data_type == typeid(double)){
548 
549  // field data is doubles
550 
551  // allocate the data for unpacking
552  std::unordered_map<int,std::vector<double>> material_data;
553 
554 
556  // We need to turn the flattened material cells into a correctly shaped
557  // ragged right structure for use as the material cells in the flat
558  // state wrapper. Just as in the flat state mesh field (and associated
559  // cell ids), we aren't removing duplicates, just concatnating by material
561 
562 
563  // reset the running counter
564  int running_counter=0;
565 
566  // loop over material ids on different nodes
567  int const num_all_material_ids = all_material_ids.size();
568  for (int i = 0; i < num_all_material_ids; ++i) {
569 
570  // get the current working material
571  int mat_id = all_material_ids[i];
572 
573  // get the current number of material cells for this material
574  int nmat_cells = all_material_shapes[i];
575 
576  // get or create a reference to the correct material cell vector
577  auto& these_material_data = material_data[mat_id];
578 
579  // loop over the correct number of material cells
580  for (int j=0; j<nmat_cells; ++j){
581  these_material_data.push_back(flat_data[running_counter++]);
582  }
583 
584  }
585 
586  // add the material indices by keys
587  // the underlying api mat_add_celldata clears the existing data
588  for ( auto& kv: material_data){
589 
590  // material id
591  int m = kv.first;
592 
593  // existing material data
594  std::vector<double> & current_material_data=kv.second;
595 
596  // vector to merge material data
597  std::vector<int> distributedMaterialCellIds =distributedMaterialCellIds_.at(m);
598 
599  // merged material data
600  std::vector<double> merged_material_data(distributedMaterialCellIds.size());
601 
602  // merge the data
603  int c=0;
604  for (auto id: distributedMaterialCellIds)
605  merged_material_data[c++]=current_material_data[id];
606 
607  // add this cell data to the state manager
608  StateManager<MeshWrapper>::mat_add_celldata(field_name, m, merged_material_data.data());
609  }
610  }
611  }
612  else
613  throw std::runtime_error("invalid field type");
614  }
615 
619  size_t get_field_stride(std::string field_name) {
620 
621  // get the state vector base class shared pointer
622  std::shared_ptr<StateVectorBase> pv =
623  StateManager<MeshWrapper>::get(field_name);
624 
625  const std::type_info& data_type = pv->data_type();
626 
627  if ( data_type == typeid(double)) return 1;
628  else if ( data_type == typeid(Wonton::Point<2>)) return 2;
629  else if ( data_type == typeid(Wonton::Point<3>)) return 3;
630 
631  throw std::runtime_error("invalid data type");
632  }
633 
642  int num_material_cells() const {
643  int n=0;
645  n += kv.second.size();
646  }
647  return n;
648  }
649 
656  std::vector<int> get_material_ids() const {
657 
658  std::vector<int> material_ids;
659  for (auto& kv : StateManager<MeshWrapper>::material_cells_) material_ids.emplace_back(kv.first);
660 
661  std::sort(material_ids.begin(), material_ids.end());
662 
663  return material_ids;
664  }
665 
672  std::vector<int> get_material_shapes() const {
673 
674  std::vector<int> material_ids=get_material_ids();
675  std::vector<int> material_shapes;
676 
677  for (auto m : material_ids)
678  material_shapes.emplace_back(StateManager<MeshWrapper>::material_cells_.at(m).size());
679 
680  return material_shapes;
681  }
682 
683 
690  std::vector<int> get_material_cells() const {
691 
692  std::vector<int> material_ids=get_material_ids();
693  std::vector<int> material_cells;
694 
695  for (auto m : material_ids){
696  std::vector<int> this_material_cells = StateManager<MeshWrapper>::get_material_cells(m);
697  material_cells.insert(material_cells.end(), this_material_cells.begin(), this_material_cells.end());
698  }
699 
700  return material_cells;
701  }
702 
703 }; // class Flat_State_Wrapper
704 
705 } // namespace Wonton
706 
707 #endif // WONTON_STATE_FLAT_FLAT_STATE_MM_WRAPPER_H_
std::string material_name(int m) const
Return the name of a material from its material id.
Definition: state_manager.h:95
Definition: wonton.h:84
std::unordered_map< int, std::vector< int > > const & get_material_cells() const
Return the material cells.
Definition: state_manager.h:149
std::vector< int > get_material_ids() const
Return the sorted vector of material ids actually used in the cell mat data.
Definition: flat_state_mm_wrapper.h:656
Factorize a number N into D equal (or nearly equal) factors.
Definition: adaptive_refinement_mesh.h:31
std::vector< double > pack(std::string field_name)
Turn the field into a vector of doubles.
Definition: flat_state_mm_wrapper.h:253
Definition: state_vector_multi.h:28
A state manager wrapper that allows redistribution of data across nodes.
Definition: flat_state_mm_wrapper.h:33
std::vector< int > get_material_cells() const
Return the sorted vector of material shapes actually used in the cell mat data.
Definition: flat_state_mm_wrapper.h:690
void mat_add_celldata(std::string const &name, int m, T const *values)
Add cell data for a new material in a state vector to the state manager.
Definition: state_manager.h:751
std::vector< int > get_material_shapes() const
Return the sorted vector of material shapes actually used in the cell mat data.
Definition: flat_state_mm_wrapper.h:672
void mat_add_cells(int m, std::vector< int > const &newcells)
Add cells for a new material to the material cells.
Definition: state_manager.h:723
void add_material_names(const std::unordered_map< std::string, int > &names)
Add the names of the materials.
Definition: state_manager.h:61
int num_material_cells() const
Return the number of material cells for this node.
Definition: flat_state_mm_wrapper.h:642
Field_type
Field type - whether it is mesh field or multi-material field.
Definition: wonton.h:187
Represents a point in an N-dimensional space.
Definition: Point.h:50
size_t get_num_vectors()
Get the number of data vectors.
Definition: flat_state_mm_wrapper.h:243
void initialize(State_Wrapper const &input, std::vector< std::string > const &var_names)
Initialize the state wrapper with another state wrapper and a list of names.
Definition: flat_state_mm_wrapper.h:77
Entity_kind
The type of mesh entity.
Definition: wonton.h:81
Flat_State_Wrapper(const MeshWrapper &mesh, std::unordered_map< std::string, int > const &names={}, std::unordered_map< int, std::vector< int >> const &material_cells={})
Constructor for the state wrapper.
Definition: flat_state_mm_wrapper.h:45
Definition: state_manager.h:29
Field_type field_type(Entity_kind on_what, std::string const &var_name) const
Type of field (MESH_FIELD or MULTIMATERIAL_FIELD)
Definition: flat_state_wrapper.h:205
~Flat_State_Wrapper()=default
Destructor.
std::vector< std::string > const names() const
Return the names registered by the state manager.
Definition: state_manager.h:79
std::shared_ptr< StateVectorBase > get(std::string name)
Get a shared pointer to a StateVectorBase from the state manager.
Definition: state_manager.h:359
void add(std::shared_ptr< StateVectorBase > sv)
Add a StateVectorBase to the state manager.
Definition: state_manager.h:271
Definition: state_vector_uni.h:27
void clear()
Definition: state_manager.h:864
size_t get_field_stride(std::string field_name)
Get field stride.
Definition: flat_state_mm_wrapper.h:619
Flat_State_Wrapper & operator=(Flat_State_Wrapper const &)=delete
Assignment operator (disabled).
void unpack(std::string field_name, const std::vector< double > &flat_data, const std::vector< int > &all_material_ids={}, const std::vector< int > &all_material_shapes={}, const std::map< int, std::vector< int >> &distributedMaterialCellIds_={})
Turn a vector of doubles into the correct shape object.
Definition: flat_state_mm_wrapper.h:363