state_manager.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 #ifndef WONTON_STATE_STATE_MANAGER_H_
8 #define WONTON_STATE_STATE_MANAGER_H_
9 
10 #include <cassert>
11 #include <string>
12 #include <iostream>
13 #include <unordered_map>
14 #include <unordered_set>
15 #include <vector>
16 #include <memory>
17 #include <stdexcept>
18 #include <iterator>
19 #include <algorithm>
20 
21 #include "wonton/support/wonton.h"
25 
26 namespace Wonton {
27 
28 template <class MeshWrapper>
29 class StateManager {
30  public:
41 StateManager(const MeshWrapper& mesh,
42  std::unordered_map<std::string, int> names = {},
43  std::unordered_map<int, std::vector<int>> material_cells = {})
44  :mesh_(mesh) {
46  add_material_cells(material_cells);
47  }
48 
49 
51  // state manager level API functions and material names
53 
54 
61  void add_material_names( const std::unordered_map<std::string, int>& names) {
62  for (auto& kv : names) {
63 
64  // this will update, not overwrite
65  material_ids_[kv.first]=kv.second;
66 
67  // likewise
68  material_names_[kv.second] = kv.first;
69  }
70  }
71 
72 
79  std::vector<std::string> const names() const {
80  std::vector<std::string> keys;
81  for (auto& kv : state_vectors_) {
82  keys.push_back(kv.first);
83  }
84  return keys;
85  }
86 
87 
95  std::string material_name(int m) const {return material_names_.at(m); }
96 
97 
105  int get_material_id(std::string const& name) const {
106  return material_ids_.at(name);}
107 
108 
116  void add_material_cells(std::unordered_map<int, std::vector<int>> cells) {
117  // make sure all materials are known by index
118  for (auto &kv : cells) {
119  if (material_names_.find(kv.first) == material_names_.end()) {
120  throw std::runtime_error(
121  "Tried to add cells for an unknown material: "
122  + std::to_string(kv.first));
123  }
124 
125  // create the inverse map
126  for (int cell : kv.second) {
127  // add the material to the cell
128  cell_materials_[cell].insert(kv.first);
129  }
130 
131  // compute the cell index in material inverse map
132  for (unsigned i = 0; i < kv.second.size(); i++)
133  cell_index_in_mat_[kv.first][kv.second[i]]=i;
134  }
135 
136  // set the cells of the material
137  material_cells_ = cells;
138 
139  }
140 
141 
149  std::unordered_map<int, std::vector<int>> const& get_material_cells() const {
150  return material_cells_;
151  }
152 
160  std::unordered_map<int, std::unordered_set<int>> const& get_cell_materials() const {
161  return cell_materials_;
162  }
163 
171  std::unordered_map<int, int> const get_material_shape() const {
172 
173  std::unordered_map<int, int> shape;
174  for (auto& kv : material_cells_) shape[kv.first] = kv.second.size();
175 
176  return shape;
177  }
178 
179 
188  int num_materials() const {return material_names_.size();}
189 
190 
192  // state vector metadata
194 
195 
196 
205  Entity_kind get_entity(std::string const& name) const {
206  auto v=state_vectors_.find(name);
207  return (v != state_vectors_.end()) ? v->second->get_kind() : Entity_kind::UNKNOWN_KIND;
208  }
209 
210 
227  Field_type field_type(Entity_kind kind, std::string const& name) const {
228  return state_vectors_.at(name)->get_type();
229  }
230 
231 
235  int get_data_size(Entity_kind on_what, std::string const& name) const {
236  return std::static_pointer_cast<StateVectorUni<>>(
237  state_vectors_.at(name))->get_data().size();
238  }
239 
245  const std::type_info& get_data_type(std::string var_name) {
246 
247  // get a shared state vector base class pointer and cast it to whatever
248  std::shared_ptr<StateVectorBase> pv = get<StateVectorBase>(var_name);
249 
250  // define the data type
251  const std::type_info & info = pv->data_type();
252 
253  // get the data type
254  return info;
255  }
256 
257 
258 
260  // methods to register or access a complete state vector
262 
263 
271  void add(std::shared_ptr<StateVectorBase> sv) {
272  // create the key
273  std::string key{sv->get_name()};
274 
275  // if the map entry for this key already exists, throw an error
276  if (state_vectors_.find(key) != state_vectors_.end())
277  throw std::runtime_error("Field " + sv->get_name() +
278  " already exists in the state manager");
279 
280  // copies the shared pointer
281  state_vectors_[key] = sv;
282  }
283 
284 
295  template <class T>
296  void add(std::shared_ptr<StateVectorUni<T>> sv) {
297  // create the key
298  std::string key{sv->get_name()};
299 
300  // if the map entry for this key already exists, throw an error
301  if (state_vectors_.find(key) != state_vectors_.end())
302  throw std::runtime_error("Field " + sv->get_name() +
303  " already exists in the state manager");
304 
305  // check that the size is correct
306  if ((int) sv->get_data().size() != mesh_.num_entities(sv->get_kind()))
307  throw std::runtime_error(
308  "The added data did not have the same number of elements (" +
309  std::to_string(sv->get_data().size()) +") as the number of cells ("+
310  std::to_string(mesh_.num_owned_cells())+")");
311 
312  // copies the shared pointer
313  state_vectors_[key] = sv;
314  }
315 
316 
326  template <class T>
327  void add(std::shared_ptr<StateVectorMulti<T>> sv) {
328  // create the key
329  std::string key{sv->get_name()};
330 
331  // if the map entry for this key already exists, throw an error
332  // Note: we shouldn't use (state_vectors_[key] != nullptr) as []creates the
333  // key even if the key doesn't exist
334  if (state_vectors_.find(key) != state_vectors_.end())
335  throw std::runtime_error("Field " + sv->get_name() +
336  " already exists in the state manager");
337 
338  // check that the size is correct
339  if (!shape_is_good<T>(sv)) throw std::runtime_error(
340  "The shape of the data was not the same as the shape of the"
341  "material cells");
342 
343  // copies the shared pointer
344  state_vectors_[key] = sv;
345  }
346 
347 
359  std::shared_ptr<StateVectorBase> get(std::string name) {
360 
361  // create the key
362  std::string key{name};
363 
364  if (state_vectors_.find(key) == state_vectors_.end()) {
365  return nullptr;
366  }
367 
368  // do the return all in one step
369  return state_vectors_[key];
370 
371  }
372 
373 
385  std::shared_ptr<StateVectorBase const> get(std::string name) const {
386 
387  // create the key
388  std::string key{name};
389 
390  if (state_vectors_.find(key) == state_vectors_.end()) {
391  return nullptr;
392  }
393 
394  // do the return all in one step
395  return state_vectors_.at(key);
396 
397  }
398 
399 
413  template <typename T>
414  std::shared_ptr<T> get(std::string name) {
415  // create the key
416  std::string key{name};
417 
418  if (state_vectors_.find(key) == state_vectors_.end()) {
419  return nullptr;
420  }
421 
422  // do the return all in one step
423  return std::dynamic_pointer_cast<T>(state_vectors_[key]);
424 
425  }
426 
427 
442  template <typename T>
443  std::shared_ptr<T> get(std::string name) const {
444  // create the key
445  std::string key{name};
446 
447  if (state_vectors_.find(key) == state_vectors_.end()) {
448  return nullptr;
449  }
450 
451  // do the return all in one step
452  return std::dynamic_pointer_cast<T>(state_vectors_.at(key));
453  }
454 
455 
456 
458  // material dominant accessor methods
460 
461 
462 
470  int num_material_cells(int m) const {return material_cells_.at(m).size();}
471 
472 
481  std::vector<int> const& get_material_cells(int m) const {
482  return material_cells_.at(m);
483  }
484 
485 
495  void mat_get_cells(int m, std::vector<int> *matcells) const {
496  // the "this" is for a gcc compiler error about assert and templates
497  assert(this->material_cells_.find(m) != this->material_cells_.end());
498  matcells->clear();
499  *matcells = material_cells_.at(m);
500  }
501 
502 
514  template <class T>
515  void mat_get_celldata(std::string const& name, int m,
516  T const **data) const {
517  *data = get<StateVectorMulti<T>>(name)->get_data(m).data();
518  }
519 
520 
534  int cell_index_in_material(int c, int m) const {
535  auto const& cell_index_map = cell_index_in_mat_.at(m);
536  auto const it = cell_index_map.find(c);
537  return it == cell_index_map.end() ? -1 : it->second;
538  }
539 
540 
572  template <class T>
573  void mat_get_celldata(std::string const& name, int m,
574  T **data) {
575 
576  // get the correct row of the ragged right data structure
577  // NOTE: (this bit me) the &, the local reference needs to refer to the
578  // actual data in the state manager, not a copy
579  std::vector<T>& material_data = get<StateVectorMulti<T>>(name)->get_data(m);
580 
581  int n = material_cells_[m].size();
582 
583  // if the space in the row isn't already allocated, fix this
584  if (material_data.size() != unsigned(n))
585  material_data.resize(n);
586 
587  *data = material_data.data();
588  }
589 
590 
591 
593  // cell dominant accessor methods
595 
596 
597 
609  int cell_get_num_mats(int c) const {
610  // if a mesh field problem, then there will be no cell_materials_ defined
611  if (cell_materials_.size() == 0) return 0;
612 
613  // a true multimaterial field
614  return cell_materials_.at(c).size();
615  }
616 
617 
628  std::unordered_set<int> get_cell_materials(int c) const {
629  return cell_materials_.at(c);
630  }
631 
651  void cell_get_mats(int c, std::vector<int> *cellmats) const {
652  cellmats->clear();
653 
654  // if a mesh field problem, then there will be no cell_materials_ defined
655  if (cell_materials_.size() == 0) return;
656 
657  auto& mats = cell_materials_.at(c);
658  *cellmats = std::vector<int>{mats.begin(), mats.end()};
659  }
660 
661 
662 
664  // single material accessor methods
666 
667 
668 
681  template <class T>
682  void mesh_get_data(Entity_kind on_what, std::string const& name,
683  T const **data) const {
684  *data = get<StateVectorUni<T>>(name)->get_data().data();
685  }
686 
687 
700  template <class T>
701  void mesh_get_data(Entity_kind on_what, std::string const& name,
702  T **data) {
703  *data = get<StateVectorUni<T>>(name)->get_data().data();
704  }
705 
706 
707 
709  // material dominant mutator methods
711 
712 
723  void mat_add_cells(int m, std::vector<int> const& newcells) {
724  // assign the cell ids to the material (copy constructor
725  material_cells_[m] = newcells;
726 
727  // need to update cell_materials_ inverse map
728  for (int c : newcells)
729  cell_materials_[c].insert(m);
730 
731  int i = 0;
732  for (auto const& c : material_cells_[m])
733  cell_index_in_mat_[m][c] = i++;
734  }
735 
736 
750  template <class T>
751  void mat_add_celldata(std::string const& name, int m,
752  T const * values) {
753  // get the number of cells for this material
754  // should use api, but I'm going to change it
755  int ncells = material_cells_[m].size();
756 
757  // could use a std::copy, but I'll get to it later
758  // need a reference, because we are modifying the data in place
759  std::vector<T>& data = get<StateVectorMulti<T>>(name)->get_data(m);
760  data.clear();
761  for (int i = 0; i < ncells; ++i) data.push_back(*(values+i));
762  }
763 
764 
781  std::string const& matname, std::vector<int> const& matcells) {
782  std::cout << "in add_material: " << matname << std::endl;
783  throw std::runtime_error("StateManager::add_material is not implemented");
784  }
785 
786 
787 
788 
790  // utility functions
792 
802  template <class T = double>
803  bool shape_is_good(const std::shared_ptr<StateVectorMulti<T>> sv) {
804 
805  // get the data shape
806  std::unordered_map<int, int> shape{get_material_shape()};
807 
808  // if we don't have cells yet, and don't know the shape, assume the
809  // user knows what they are doing and the shape is good.
810  if (shape.size() == 0) return true;
811 
812  // get the actual data out of the state vector
813  const auto& data = sv->get_data();
814 
815  // this one is tricky, but if we build up the state vector material
816  // we may start with no data, so for the moment, let's pass this
817  if (data.size() == 0) return true;
818 
819  // check first that there are the correct number of materials
820  if (shape.size() != data.size()) return false;
821 
822  for (const auto& kv : data) {
823  if (shape.find(kv.first) == shape.end() ||
824  shape[kv.first] != (int) kv.second.size()
825  ) return false;
826  }
827 
828  return true;
829  }
830 
835  material_cells_.clear();
836  cell_materials_.clear();
837  }
838 
839  protected:
840 
841  // underlying mesh reference
842  const MeshWrapper& mesh_;
843 
844  // state vectors
845  std::unordered_map<std::string, std::shared_ptr<StateVectorBase>>
847 
848  // material name to id
849  std::unordered_map<std::string, int> material_ids_;
850 
851  // material id to name
852  std::unordered_map<int, std::string> material_names_;
853 
854  // cell ids for a material
855  std::unordered_map<int, std::vector<int>> material_cells_;
856 
857  // cell indices for a material
858  std::unordered_map<int, std::unordered_map<int,int>> cell_index_in_mat_;
859 
860  // material id's for a cell
861  std::unordered_map<int, std::unordered_set<int>> cell_materials_;
862 
863  // clear all the protected data structures
864  void clear() {
865  state_vectors_.clear();
866  material_ids_.clear();
867  material_names_.clear();
868  material_cells_.clear();
869  cell_materials_.clear();
870  }
871 
872 };
873 
874 } // namespace Wonton
875 
876 #endif // WONTON_STATE_STATE_MANAGER_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::unordered_set< int > > const & get_cell_materials() const
Return the cell materials.
Definition: state_manager.h:160
std::unordered_set< int > get_cell_materials(int c) const
Return the unordered set of materials in this cell.
Definition: state_manager.h:628
void add(std::shared_ptr< StateVectorUni< T >> sv)
Add a StateVectorUni<T> to the state manager.
Definition: state_manager.h:296
void cell_get_mats(int c, std::vector< int > *cellmats) const
Return the materials in this cell.
Definition: state_manager.h:651
std::unordered_map< int, std::vector< int > > const & get_material_cells() const
Return the material cells.
Definition: state_manager.h:149
Factorize a number N into D equal (or nearly equal) factors.
Definition: adaptive_refinement_mesh.h:31
Definition: state_vector_multi.h:28
int cell_index_in_material(int c, int m) const
Return the cell index in this material id.
Definition: state_manager.h:534
int cell_get_num_mats(int c) const
Return the number of materials in this cell.
Definition: state_manager.h:609
int get_data_size(Entity_kind on_what, std::string const &name) const
Return the data size .
Definition: state_manager.h:235
std::unordered_map< int, std::unordered_map< int, int > > cell_index_in_mat_
Definition: state_manager.h:858
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
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
const MeshWrapper & mesh_
Definition: state_manager.h:842
void add_material_cells(std::unordered_map< int, std::vector< int >> cells)
Add the material cells.
Definition: state_manager.h:116
void mesh_get_data(Entity_kind on_what, std::string const &name, T **data)
Return the cell data for this material id.
Definition: state_manager.h:701
const std::type_info & get_data_type(std::string var_name)
Get the data type of the given field.
Definition: state_manager.h:245
std::unordered_map< std::string, std::shared_ptr< StateVectorBase > > state_vectors_
Definition: state_manager.h:846
int num_material_cells(int m) const
Return the number of cells for this material id.
Definition: state_manager.h:470
Field_type
Field type - whether it is mesh field or multi-material field.
Definition: wonton.h:187
void add_material(std::string const &matname, std::vector< int > const &matcells)
Add cell data for a new material in a state vector to the state manager.
Definition: state_manager.h:780
std::vector< int > const & get_material_cells(int m) const
Return the cell ids for this material id.
Definition: state_manager.h:481
void mat_get_celldata(std::string const &name, int m, T **data)
Return the cell data for this material id.
Definition: state_manager.h:573
Entity_kind
The type of mesh entity.
Definition: wonton.h:81
std::unordered_map< int, std::vector< int > > material_cells_
Definition: state_manager.h:855
Definition: state_manager.h:29
void add(std::shared_ptr< StateVectorMulti< T >> sv)
Add a StateVectorMulti<T> to the state manager.
Definition: state_manager.h:327
Entity_kind get_entity(std::string const &name) const
Return the entity kind for a state vector.
Definition: state_manager.h:205
std::unordered_map< int, int > const get_material_shape() const
Return the number of cells for each material.
Definition: state_manager.h:171
int get_material_id(std::string const &name) const
Return the material id from its name.
Definition: state_manager.h:105
StateManager(const MeshWrapper &mesh, std::unordered_map< std::string, int > names={}, std::unordered_map< int, std::vector< int >> material_cells={})
Constructor.
Definition: state_manager.h:41
std::unordered_map< std::string, int > material_ids_
Definition: state_manager.h:849
std::vector< std::string > const names() const
Return the names registered by the state manager.
Definition: state_manager.h:79
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
int num_materials() const
Return the number of materials in the problem.
Definition: state_manager.h:188
Field_type field_type(Entity_kind kind, std::string const &name) const
Return the field type of a state vector.
Definition: state_manager.h:227
void clear()
Definition: state_manager.h:864
bool shape_is_good(const std::shared_ptr< StateVectorMulti< T >> sv)
Check that a StateVectorMulti<T> has a shape consistent with the state manager.
Definition: state_manager.h:803
std::unordered_map< int, std::unordered_set< int > > cell_materials_
Definition: state_manager.h:861
void mat_get_cells(int m, std::vector< int > *matcells) const
Return the cell ids for this material id.
Definition: state_manager.h:495
std::string to_string(Entity_kind entkind)
Definition: wonton.h:99
std::unordered_map< int, std::string > material_names_
Definition: state_manager.h:852
void mat_get_celldata(std::string const &name, int m, T const **data) const
Return the cell data for this material id.
Definition: state_manager.h:515
void mesh_get_data(Entity_kind on_what, std::string const &name, T const **data) const
Return the const cell data for this material id.
Definition: state_manager.h:682
void clear_material_cells()
Clear material cells and the inverse map of cell materials.
Definition: state_manager.h:834