MAST3
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
design_parameter_vector.hpp
Go to the documentation of this file.
1 /*
2 * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3 * Copyright (C) 2013-2020 Manav Bhatia and MAST authors
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 
20 #ifndef __mast_optimization_design_parameter_vector_h__
21 #define __mast_optimization_design_parameter_vector_h__
22 
23 // MAST includes
25 #include <mast/base/exceptions.hpp>
28 
29 // libMesh includes
30 #include <libmesh/parallel.h>
31 #include <libmesh/dof_map.h>
32 
33 namespace MAST {
34 namespace Optimization {
35 
36 
37 template <typename ScalarType>
39 
40 public:
41 
42  using dv_id_param_map_t = std::map<uint_t, MAST::Optimization::DesignParameter<ScalarType>*>;
43 
44 
45  DesignParameterVector(const libMesh::Parallel::Communicator &comm):
46  _comm (comm)
47  { }
48 
49 
51 
52  {
53  typename std::map<const MAST::Optimization::DesignParameter<ScalarType>*,
54  MAST::Base::ParameterData*>::iterator
55  it = _data.begin(),
56  end = _data.end();
57 
58  for (; it != end; it++)
59  delete it->second;
60  }
61 
62  {
63  typename std::map<uint_t, MAST::Optimization::DesignParameter<ScalarType>*>::iterator
64  it = _parameters.begin(),
65  end = _parameters.end();
66 
67  for (; it != end; it++)
68  delete it->second;
69  }
70  }
71 
72 
73  inline uint_t size() const {
74 
76  "Data must be synchronized before call to size()");
77 
78  return _rank_end_index[_comm.size()-1];
79  }
80 
81 
82  inline uint_t local_begin() const {
83 
85  "Data must be synchronized before call to size()");
86 
87  return _rank_begin_index[_comm.rank()];
88  }
89 
90 
91  inline uint_t local_end() const {
92 
94  "Data must be synchronized before call to size()");
95 
96  return _rank_end_index[_comm.rank()];
97  }
98 
99 
102 
103  typename std::map<uint_t, MAST::Optimization::DesignParameter<ScalarType>*>::iterator
104  it = _parameters.find(i);
105 
106  Assert0(it != _parameters.end(), "Invalid parameter index for rank");
107 
108  return *it->second;
109  }
110 
111 
112 
114  operator[](uint_t i) const {
115 
116  typename std::map<uint_t, MAST::Optimization::DesignParameter<ScalarType>*>::const_iterator
117  it = _parameters.find(i);
118 
119  Assert0(it != _parameters.end(), "Invalid parameter index for rank");
120 
121  return *it->second;
122  }
123 
124 
125  inline const dv_id_param_map_t& get_dv_map() const {
126 
127  return _parameters;
128  }
129 
130 
131  inline uint_t get_dv_id_for_topology_dof(const uint_t id) const {
132 
133  std::map<uint_t, uint_t>::const_iterator
134  it = _dof_id_to_dv_id_map.find(id);
135 
136  Assert1(it != _dof_id_to_dv_id_map.end(),
137  id, "dof ID not in this vector");
138 
139  return it->second;
140  }
141 
142 
143 
144  inline bool
146 
147  return _dof_id_to_dv_id_map.count(i);
148  }
149 
150 
151  inline bool
153 
154  return _dv_index.count(i);
155  }
156 
157 
158  template <typename T>
159  inline T get_parameter_for_dv(uint_t i, const std::string& nm) const {
160 
161  return this->get_data_for_parameter((*this)[i]).template get<T>(nm);
162  }
163 
164 
167 
168  // make sure this does not exist
169  typename std::map<const MAST::Optimization::DesignParameter<ScalarType>*,
170  MAST::Base::ParameterData*>::iterator
171  it = _data.find(&p);
172 
173  Assert0(it == _data.end(), "Parameter already exists");
174 
175  _local_parameters.push_back(&p);
176 
178  _data[&p] = d;
179 
180  return *d;
181  }
182 
183 
190  const uint_t id) {
191 
192  // make sure this does not exist
193  typename std::map<const MAST::Optimization::DesignParameter<ScalarType>*,
194  MAST::Base::ParameterData*>::iterator
195  it = _data.find(&p);
196 
197  Assert0(it == _data.end(), "Parameter already exists");
198 
199  _local_parameters.push_back(&p);
200 
202  _data[&p] = d;
203 
204  d->add<int>("dof_id") = id;
205  _dv_index.insert(id);
206 
207  return *d;
208  }
209 
210 
213  const uint_t id) {
214 
215  // make sure this does not exist
216  typename std::map<const MAST::Optimization::DesignParameter<ScalarType>*,
217  MAST::Base::ParameterData*>::iterator
218  it = _data.find(&p);
219 
220  Assert0(it == _data.end(), "Parameter already exists");
221 
222  _ghosted_parameters.push_back(&p);
223 
225  _data[&p] = d;
226 
227  d->add<int>("dof_id") = id;
228  _dv_index.insert(id);
229 
230  return *d;
231  }
232 
233 
234 
235  inline const MAST::Base::ParameterData&
237 
238  // make sure this does not exist
239  typename std::map<const MAST::Optimization::DesignParameter<ScalarType>*,
240  MAST::Base::ParameterData*>::const_iterator
241  it = _data.find(&p);
242 
243  Assert0(it != _data.end(), "Parameter does not exists in vector");
244 
245  return *it->second;
246  }
247 
248 
251 
252  // make sure this does not exist
253  typename std::map<const MAST::Optimization::DesignParameter<ScalarType>*,
254  MAST::Base::ParameterData*>::iterator
255  it = _data.find(&p);
256 
257  Assert0(it != _data.end(), "Parameter does not exists in vector");
258 
259  return *it->second;
260  }
261 
262  inline void synchronize(const libMesh::DofMap &dof_map) {
263 
264  Assert0(!_rank_begin_index.size(), "Data already synchronized");
265  Assert0(_local_parameters.size(), "Parameters not initialized on this rank");
266 
267  std::vector<int_t>
268  rank_dvs(_comm.size(), 0);
269 
270  _rank_begin_index.resize(_comm.size());
271  _rank_end_index.resize(_comm.size());
272 
273  // initialize the number of DVs for the current rank
274  rank_dvs[_comm.rank()] = _local_parameters.size();
275 
276  // now obtain these values from each rank
277  _comm.sum(rank_dvs);
278 
279  // now identify the beginning IDs for each processor
280  _rank_begin_index[0] = 0;
281  _rank_end_index[0] = rank_dvs[0];
282 
283  for (uint_t i=1; i<_comm.size(); i++) {
284 
285  _rank_begin_index[i] = _rank_begin_index[i-1] + rank_dvs[i-1];
286  _rank_end_index[i] = _rank_end_index[i-1] + rank_dvs[i];
287  }
288 
289  // assign the DV Ids and populate the DofID map
290  uint_t
291  dof_id = 0,
292  owner = 0;
293 
294  std::map<uint_t, MAST::Optimization::DesignParameter<ScalarType>*>
295  dof_to_ghost_param_map;
296 
297  for (uint_t i=0; i<_local_parameters.size(); i++) {
298 
299  dof_id = this->get_data_for_parameter(*_local_parameters[i]).template get<int>("dof_id");
300  _local_parameters[i]->set_id(_rank_begin_index[_comm.rank()]+i);
301  _dof_id_to_dv_id_map[dof_id] = _local_parameters[i]->id();
302  }
303 
304 
305  // ghosted dofs indices needed from each rank
306  std::vector<std::vector<uint_t>>
307  ghosted_indices_on_rank_send(_comm.size()),
308  ghosted_indices_on_rank_recv(_comm.size()),
309  ghosted_dv_id_on_rank_recv(_comm.size());
310 
311  // figure out the DV IDs for the ghosted parameters
312  for (uint_t i=0; i<_ghosted_parameters.size(); i++) {
313 
314  dof_id = this->get_data_for_parameter(*_ghosted_parameters[i]).template get<int>("dof_id");
315  owner = dof_map.dof_owner(dof_id);
316 
317  dof_to_ghost_param_map[dof_id] = _ghosted_parameters[i];
318  ghosted_indices_on_rank_send[owner].push_back(dof_id);
319  }
320 
321  // now ask respective processors for the indices
322  for (uint_t i=0; i<_comm.size(); i++) {
323 
324  for (uint_t j=0; j<_comm.size(); j++) {
325 
326  if ( i != j) {
327 
328  // send to the j^th processor if it is my turn,
329  // else, receive from the ith processor
330  if (i == _comm.rank())
331  _comm.send(j, ghosted_indices_on_rank_send[j]);
332  else if (j == _comm.rank())
333  _comm.receive(i, ghosted_indices_on_rank_recv[i]);
334  }
335  }
336  }
337 
338  // now that we have received all the dof indices, we are going to send
339  // back to the respective processor the DV id that corresponds to the
340  // dof indices.
341 
342 
343  for (uint_t i=0; i<_comm.size(); i++) {
344 
345  for (uint_t k=0; k<ghosted_indices_on_rank_recv[i].size(); k++) {
346 
347  // make sure that the indices are all local
348  Assert2(ghosted_indices_on_rank_recv[i][k]
349  >= dof_map.first_dof(_comm.rank()),
350  ghosted_indices_on_rank_recv[i][k],
351  dof_map.first_dof(_comm.rank()),
352  "Requested dof does not belong to this processor");
353  Assert2(ghosted_indices_on_rank_recv[i][k]
354  < dof_map.end_dof(_comm.rank()),
355  ghosted_indices_on_rank_recv[i][k],
356  dof_map.end_dof(_comm.rank()),
357  "Requested dof does not belong to this processor");
358 
359  // now identify the DV Id number for these dofs
360  std::map<uint_t, uint_t>::const_iterator
361  it = _dof_id_to_dv_id_map.find(ghosted_indices_on_rank_recv[i][k]);
362 
363  Assert0(it != _dof_id_to_dv_id_map.end(),
364  "No DV Id found for this dof id");
365 
366  ghosted_indices_on_rank_recv[i][k] = it->second;
367  }
368  }
369 
370  // now we communicate this information back to the processors
371  for (uint_t i=0; i<_comm.size(); i++) {
372 
373  for (uint_t j=0; j<_comm.size(); j++) {
374 
375  if (( i == _comm.rank() && ghosted_indices_on_rank_recv[j].size()) ||
376  ( j == _comm.rank() && ghosted_indices_on_rank_send[i].size())) {
377 
378  // send to the i^th processor if it is my turn,
379  // else, receive from the j^th processor
380  if (i == _comm.rank())
381  _comm.send(j, ghosted_indices_on_rank_recv[j]);
382  else if (j == _comm.rank()) {
383 
384  _comm.receive(i, ghosted_dv_id_on_rank_recv[i]);
385 
386  Assert2(ghosted_indices_on_rank_send[i].size() ==
387  ghosted_dv_id_on_rank_recv[i].size(),
388  ghosted_indices_on_rank_send[i].size(),
389  ghosted_dv_id_on_rank_recv[i].size(),
390  "Dof and DV ID map sizes must be same");
391 
392  uint_t
393  dof_id = 0,
394  dv_id = 0;
395 
396  for (uint_t k=0; k<ghosted_dv_id_on_rank_recv[i].size(); k++) {
397 
398  dof_id = ghosted_indices_on_rank_send[i][k];
399  dv_id = ghosted_dv_id_on_rank_recv[i][k];
400  dof_to_ghost_param_map[dof_id]->set_id(dv_id);
401 
402  // also store this information in the map
403  _dof_id_to_dv_id_map[dof_id] = dv_id;
404  }
405  }
406  }
407  }
408  }
409 
410  // now, populate the parameters map
411  for (uint_t i=0; i<_local_parameters.size(); i++)
413 
414  for (uint_t i=0; i<_ghosted_parameters.size(); i++)
416 
417 
418  // we don't need these any more, so we clear them.
419  _local_parameters.clear();
420  _ghosted_parameters.clear();
421  }
422 
423 private:
424 
425  const libMesh::Parallel::Communicator& _comm;
426  std::map<uint_t, MAST::Optimization::DesignParameter<ScalarType>*> _parameters;
427  std::vector<MAST::Optimization::DesignParameter<ScalarType>*> _local_parameters;
428  std::vector<MAST::Optimization::DesignParameter<ScalarType>*> _ghosted_parameters;
429  std::map<const MAST::Optimization::DesignParameter<ScalarType>*,
431  std::set<uint_t> _dv_index;
432  std::map<uint_t, uint_t> _dof_id_to_dv_id_map;
433  std::vector<uint_t> _rank_begin_index;
434  std::vector<uint_t> _rank_end_index;
435 };
436 
437 } // namespace Optimization
438 } // namespace MAST
439 
440 
441 #endif // __mast_optimization_design_parameter_vector_h__
std::map< uint_t, MAST::Optimization::DesignParameter< ScalarType > * > _parameters
T get_parameter_for_dv(uint_t i, const std::string &nm) const
std::vector< MAST::Optimization::DesignParameter< ScalarType > * > _local_parameters
std::vector< MAST::Optimization::DesignParameter< ScalarType > * > _ghosted_parameters
std::map< uint_t, MAST::Optimization::DesignParameter< ScalarType > * > dv_id_param_map_t
MAST::Base::ParameterData & add_ghosted_topology_parameter(MAST::Optimization::DesignParameter< ScalarType > &p, const uint_t id)
std::map< const MAST::Optimization::DesignParameter< ScalarType > *, MAST::Base::ParameterData * > _data
#define Assert1(cond, v1, msg)
Definition: exceptions.hpp:143
T & add(const std::string &nm)
const dv_id_param_map_t & get_dv_map() const
MAST::Base::ParameterData & add_topology_parameter(MAST::Optimization::DesignParameter< ScalarType > &p, const uint_t id)
const libMesh::Parallel::Communicator & _comm
MAST::Base::ParameterData & get_data_for_parameter(const MAST::Optimization::DesignParameter< ScalarType > &p)
const MAST::Base::ParameterData & get_data_for_parameter(const MAST::Optimization::DesignParameter< ScalarType > &p) const
const MAST::Optimization::DesignParameter< ScalarType > & operator[](uint_t i) const
#define Assert0(cond, msg)
Definition: exceptions.hpp:134
unsigned int uint_t
#define Assert2(cond, v1, v2, msg)
Definition: exceptions.hpp:152
DesignParameterVector(const libMesh::Parallel::Communicator &comm)
MAST::Base::ParameterData & add_parameter(MAST::Optimization::DesignParameter< ScalarType > &p)
MAST::Optimization::DesignParameter< ScalarType > & operator[](uint_t i)
uint_t get_dv_id_for_topology_dof(const uint_t id) const
void synchronize(const libMesh::DofMap &dof_map)