MAST3
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
volume.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_topology_simp_libmesh_volume_h__
21 #define __mast_optimization_topology_simp_libmesh_volume_h__
22 
23 // MAST includes
25 #include <mast/base/exceptions.hpp>
28 
29 // libMesh includes
30 #include <libmesh/nonlinear_implicit_system.h>
31 #include <libmesh/dof_map.h>
32 #include <libmesh/elem.h>
33 
34 
35 namespace MAST {
36 namespace Optimization {
37 namespace Topology {
38 namespace SIMP {
39 namespace libMeshWrapper {
40 
41 template <typename ScalarType>
42 class Volume {
43 
44 public:
45 
46  Volume() {}
47  virtual ~Volume() {}
48 
49  template <typename VecType, typename ContextType>
50  inline ScalarType compute(ContextType& c,
51  const VecType &density) const {
52 
53  ScalarType
54  volume = 0.,
55  rho = 0.;
56 
57  uint_t
58  sys_num = c.rho_sys->number(),
59  n_nodes = 0;
60 
62  density_accessor (*c.rho_sys, density);
63 
64  libMesh::MeshBase::element_iterator
65  it = c.mesh->active_local_elements_begin(),
66  end = c.mesh->active_local_elements_end();
67 
68  for ( ; it != end; it++) {
69 
70  const libMesh::Elem& e = **it;
71 
72  // compute the average element density value
73  rho = 0.;
74 
76 
77  for (uint_t i=0; i<n_nodes; i++) {
78 
79  const libMesh::Node& n = *e.node_ptr(i);
80 
81  rho +=
83  n.dof_number(sys_num, 0, 0));
84  }
85 
86  rho /= (1. * n_nodes);
87 
88  // use this density value to compute the volume
89  volume += e.volume() * rho;
90  }
91 
92  MAST::Numerics::Utility::comm_sum(c.rho_sys->comm(), volume);
93 
94  return volume;
95  }
96 
97 
98  template <typename VecType, typename ContextType, typename DensityFilterType>
99  inline ScalarType compute(ContextType &c,
100  const VecType &density,
101  const DensityFilterType &filter) const {
102 
103  ScalarType
104  volume = 0.,
105  rho = 0.;
106 
107  uint_t
108  sys_num = c.rho_sys->number(),
109  n_nodes = 0;
110 
112  density_accessor (*c.rho_sys, density);
113 
114  libMesh::MeshBase::element_iterator
115  it = c.mesh->active_local_elements_begin(),
116  end = c.mesh->active_local_elements_end();
117 
118  for ( ; it != end; it++) {
119 
120  const libMesh::Elem& e = **it;
121 
122  // compute the average element density value
123  rho = 0.;
124 
126 
127  for (uint_t i=0; i<n_nodes; i++) {
128 
129  const libMesh::Node& n = *e.node_ptr(i);
130 
131  rho += filter.filter(MAST::Numerics::Utility::get
132  (density, n.dof_number(sys_num, 0, 0)));
133  }
134 
135  rho /= (1. * n_nodes);
136 
137  // use this density value to compute the volume
138  volume += e.volume() * rho;
139  }
140 
141  MAST::Numerics::Utility::comm_sum(c.rho_sys->comm(), volume);
142 
143  return volume;
144  }
145 
146 
147 
148 
149  template <typename VecType,
150  typename ContextType,
151  typename GeometricFilterType>
152  inline void derivative(ContextType &c,
153  const VecType &density,
154  const GeometricFilterType &filter,
156  std::vector<ScalarType> &sens) {
157 
158  Assert2(dvs.size() == sens.size(),
159  dvs.size(), sens.size(),
160  "DV and sensitivity vectors must have same size");
161 
162  uint_t
163  n_density_dofs = c.rho_sys->n_dofs(),
164  n_nodes = 0;
165 
167  std::unique_ptr<VecType>
168  v (MAST::Numerics::Utility::build<VecType>(*c.rho_sys).release()),
169  v_filtered (MAST::Numerics::Utility::build<VecType>(*c.rho_sys).release());
170 
171  // iterate over each element, initialize it and get the relevant
172  // analysis quantities
174  density_accessor (*c.rho_sys, density);
175 
176  libMesh::MeshBase::const_element_iterator
177  el = c.mesh->active_local_elements_begin(),
178  end_el = c.mesh->active_local_elements_end();
179 
180  // first compute the sensitivity information assuming unfiltered
181  // density variables.
182  real_t
183  e_vol = 0.;
184 
185  for ( ; el != end_el; ++el) {
186 
187  // set element in the context, which will be used for
188  // the initialization routines
189  c.elem = *el;
190  e_vol = c.elem->volume();
191 
192  density_accessor.init(*c.elem);
193 
194  const std::vector<libMesh::dof_id_type>
195  &density_dof_ids = density_accessor.dof_indices();
196 
198 
199  for (uint_t i=0; i<n_nodes; i++) {
200 
201  // each density coefficient shoudl appear only once
202  // for each element. So, if the dof was found for this
203  // element, then we will simply set the element sensitivity
204  // to be the averaged value
206  density_dof_ids[i],
207  e_vol/(1. * n_nodes));
208  }
209  }
210 
212 
213  // Now, combine the sensitivty with the filtering data
214  filter.compute_reverse_filtered_values(*v, *v_filtered);
215 
216  uint_t
217  idx = 0;
218 
219  // copy the results back to sens
220  for (uint_t i=dvs.local_begin(); i<dvs.local_end(); i++) {
221 
222  idx = dvs.get_data_for_parameter(dvs[i]).template get<int>("dof_id");
223  sens[i] = MAST::Numerics::Utility::get(*v_filtered, idx);
224  }
225 
226  MAST::Numerics::Utility::comm_sum(c.rho_sys->comm(), sens);
227  }
228 
229 
230 
231  template <typename VecType,
232  typename ContextType,
233  typename DensityFilterType,
234  typename GeometricFilterType>
235  inline void derivative(ContextType &c,
236  const VecType &density,
237  const DensityFilterType &density_filter,
238  const GeometricFilterType &geom_filter,
240  std::vector<ScalarType> &sens) {
241 
242  Assert2(dvs.size() == sens.size(),
243  dvs.size(), sens.size(),
244  "DV and sensitivity vectors must have same size");
245 
246  uint_t
247  sys_num = c.rho_sys->number(),
248  n_density_dofs = c.rho_sys->n_dofs(),
249  n_nodes = 0;
250 
252 
253  std::unique_ptr<VecType>
254  v (MAST::Numerics::Utility::build<VecType>(*c.rho_sys).release()),
255  v_filtered (MAST::Numerics::Utility::build<VecType>(*c.rho_sys).release());
256 
257  // iterate over each element, initialize it and get the relevant
258  // analysis quantities
260  density_accessor (*c.rho_sys, density);
261 
262  libMesh::MeshBase::const_element_iterator
263  el = c.mesh->active_local_elements_begin(),
264  end_el = c.mesh->active_local_elements_end();
265 
266  // first compute the sensitivity information assuming unfiltered
267  // density variables.
268  real_t
269  e_vol = 0.;
270 
271  for ( ; el != end_el; ++el) {
272 
273  // set element in the context, which will be used for
274  // the initialization routines
275  c.elem = *el;
276  e_vol = c.elem->volume();
277 
278  density_accessor.init(*c.elem);
279 
280  const std::vector<libMesh::dof_id_type>
281  &density_dof_ids = density_accessor.dof_indices();
282 
284 
285  for (uint_t i=0; i<n_nodes; i++) {
286 
287  const libMesh::Node& n = *c.elem->node_ptr(i);
288 
289  // each density coefficient shoudl appear only once
290  // for each element. So, if the dof was found for this
291  // element, then we will simply set the element sensitivity
292  // to be the averaged value
294  (*v,
295  density_dof_ids[i],
296  e_vol/(1. * n_nodes) *
297  density_filter.filter_derivative(MAST::Numerics::Utility::get
298  (density, n.dof_number(sys_num, 0, 0)),
299  1.));
300  }
301  }
302 
304 
305  // Now, combine the sensitivty with the filtering data
306  geom_filter.compute_reverse_filtered_values(*v, *v_filtered);
307 
308  uint_t
309  idx = 0;
310 
311  // copy the results back to sens
312  for (uint_t i=dvs.local_begin(); i<dvs.local_end(); i++) {
313 
314  idx = dvs.get_data_for_parameter(dvs[i]).template get<int>("dof_id");
315  sens[i] = MAST::Numerics::Utility::get(*v_filtered, idx);
316  }
317 
318  MAST::Numerics::Utility::comm_sum(c.rho_sys->comm(), sens);
319  }
320 
321 private:
322 
323 };
324 
325 } // namespace libMeshWrapper
326 } // namespace SIMP
327 } // namespace Topology
328 } // namespace Optimization
329 } // namespace MAST
330 
331 
332 #endif // __mast_optimization_topology_simp_libmesh_volume_h__
ScalarType get(const std::vector< ScalarType > &v, uint_t i)
Definition: utility.hpp:232
ScalarType compute(ContextType &c, const VecType &density, const DensityFilterType &filter) const
Definition: volume.hpp:99
void derivative(ContextType &c, const VecType &density, const GeometricFilterType &filter, const MAST::Optimization::DesignParameterVector< ScalarType > &dvs, std::vector< ScalarType > &sens)
Definition: volume.hpp:152
void setZero(ValType &m)
Definition: utility.hpp:44
ScalarType compute(ContextType &c, const VecType &density) const
Definition: volume.hpp:50
void finalize(ValType &m)
Definition: utility.hpp:252
const MAST::Base::ParameterData & get_data_for_parameter(const MAST::Optimization::DesignParameter< ScalarType > &p) const
void derivative(ContextType &c, const VecType &density, const DensityFilterType &density_filter, const GeometricFilterType &geom_filter, const MAST::Optimization::DesignParameterVector< ScalarType > &dvs, std::vector< ScalarType > &sens)
Definition: volume.hpp:235
uint_t n_linear_basis_nodes_on_elem(const libMesh::Elem &e)
identifies number of ndoes on element
Definition: utility.hpp:39
unsigned int uint_t
void add(std::vector< ScalarType > &v, uint_t i, ScalarType s)
Definition: utility.hpp:188
#define Assert2(cond, v1, v2, msg)
Definition: exceptions.hpp:152
void comm_sum(const libMesh::Parallel::Communicator &comm, real_t &v)
Definition: utility.hpp:328
double real_t