MAST
filter_base.cpp
Go to the documentation of this file.
1 /*
2 * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3 * Copyright (C) 2013-2019 Manav Bhatia
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 // C++ includes
21 #include <iomanip>
22 
23 // MAST includes
24 #include "level_set/filter_base.h"
25 
26 // libMesh includes
27 #include "libmesh/mesh_base.h"
28 #include "libmesh/node.h"
29 #include "libmesh/numeric_vector.h"
30 
31 
32 
33 MAST::FilterBase::FilterBase(libMesh::System& sys,
34  const Real radius,
35  const std::set<unsigned int>& dv_dof_ids):
36 _level_set_system (sys),
37 _radius (radius),
38 _level_set_fe_size (0.),
39 _dv_dof_ids (dv_dof_ids) {
40 
41  libmesh_assert_greater(radius, 0.);
42 
43  _init();
44 }
45 
46 
48 
49 }
50 
51 
52 void
53 MAST::FilterBase::compute_filtered_values(const libMesh::NumericVector<Real>& input,
54  libMesh::NumericVector<Real>& output) const {
55 
56  libmesh_assert_equal_to(input.size(), _filter_map.size());
57  libmesh_assert_equal_to(output.size(), _filter_map.size());
58 
59  output.zero();
60 
61  std::vector<Real> input_vals(input.size(), 0.);
62  input.localize(input_vals);
63 
64  std::map<unsigned int, std::vector<std::pair<unsigned int, Real>>>::const_iterator
65  map_it = _filter_map.begin(),
66  map_end = _filter_map.end();
67 
68  for ( ; map_it != map_end; map_it++) {
69 
70  std::vector<std::pair<unsigned int, Real>>::const_iterator
71  vec_it = map_it->second.begin(),
72  vec_end = map_it->second.end();
73 
74  for ( ; vec_it != vec_end; vec_it++) {
75  if (map_it->first >= input.first_local_index() &&
76  map_it->first < input.last_local_index()) {
77 
78  if (_dv_dof_ids.count(map_it->first))
79  output.add(map_it->first, input_vals[vec_it->first] * vec_it->second);
80  else
81  output.set(map_it->first, input_vals[map_it->first]);
82  }
83  }
84  }
85 
86  output.close();
87 }
88 
89 
90 
91 
92 void
93 MAST::FilterBase::compute_filtered_values(const std::vector<Real>& input,
94  std::vector<Real>& output) const {
95 
96  libmesh_assert_equal_to(input.size(), _filter_map.size());
97  libmesh_assert_equal_to(output.size(), _filter_map.size());
98 
99  std::fill(output.begin(), output.end(), 0.);
100 
101  std::map<unsigned int, std::vector<std::pair<unsigned int, Real>>>::const_iterator
102  map_it = _filter_map.begin(),
103  map_end = _filter_map.end();
104 
105  for ( ; map_it != map_end; map_it++) {
106 
107  std::vector<std::pair<unsigned int, Real>>::const_iterator
108  vec_it = map_it->second.begin(),
109  vec_end = map_it->second.end();
110 
111  for ( ; vec_it != vec_end; vec_it++) {
112  if (_dv_dof_ids.count(map_it->first))
113  output[map_it->first] += input[vec_it->first] * vec_it->second;
114  else
115  output[map_it->first] += input[map_it->first];
116  }
117  }
118 }
119 
120 
121 bool
123 if_elem_in_domain_of_influence(const libMesh::Elem& elem,
124  const libMesh::Node& level_set_node) const {
125 
126  Real
127  d = 1.e12; // arbitrarily large value to initialize the search
128 
129  libMesh::Point
130  pt;
131 
132  // first get the smallest distance from the node to the element nodes
133  for (unsigned int i=0; i<elem.n_nodes(); i++) {
134  pt = elem.point(i);
135  pt -= level_set_node;
136 
137  if (pt.norm() < d)
138  d = pt.norm();
139  }
140 
141  // if this distance is outside the domain of influence, then this
142  // element is not influenced by the design variable
143  if (d > _radius + _level_set_fe_size)
144  return false;
145  else
146  return true;
147 }
148 
149 
150 
151 void
153 
154  libmesh_assert(!_filter_map.size());
155 
156  libMesh::MeshBase& mesh = _level_set_system.get_mesh();
157 
158  // currently implemented for replicated mesh
159  libmesh_assert(mesh.is_replicated());
160 
161  // iterate over all nodes to compute the
162  libMesh::MeshBase::const_node_iterator
163  node_it_1 = mesh.nodes_begin(),
164  node_it_2 = mesh.nodes_begin(),
165  node_end = mesh.nodes_end();
166 
167  libMesh::Point
168  d;
169 
170  Real
171  d_12 = 0.,
172  sum = 0.;
173 
174  unsigned int
175  dof_1,
176  dof_2;
177 
178  for ( ; node_it_1 != node_end; node_it_1++) {
179 
180  dof_1 = (*node_it_1)->dof_number(_level_set_system.number(), 0, 0);
181 
182  node_it_2 = mesh.nodes_begin();
183  sum = 0.;
184 
185  for ( ; node_it_2 != node_end; node_it_2++) {
186 
187  // compute the distance between the two nodes
188  d = (**node_it_1) - (**node_it_2);
189  d_12 = d.norm();
190 
191  // if the nodes is within the filter radius, add it to the map
192  if (d_12 <= _radius) {
193 
194  sum += _radius - d_12;
195  dof_2 = (*node_it_2)->dof_number(_level_set_system.number(), 0, 0);
196 
197  _filter_map[dof_1].push_back(std::pair<unsigned int, Real>(dof_2, _radius - d_12));
198  }
199  }
200 
201  libmesh_assert_greater(sum, 0.);
202 
203  // with the coefficients computed for dof_1, divide each coefficient
204  // with the sum
205  std::vector<std::pair<unsigned int, Real>>& vec = _filter_map[dof_1];
206  for (unsigned int i=0; i<vec.size(); i++) {
207 
208  vec[i].second /= sum;
209  libmesh_assert_less_equal(vec[i].second, 1.);
210  }
211  }
212 
213  // compute the largest element size
214  libMesh::MeshBase::const_element_iterator
215  e_it = mesh.elements_begin(),
216  e_end = mesh.elements_end();
217 
218  for ( ; e_it != e_end; e_it++) {
219  const libMesh::Elem* e = *e_it;
220  d_12 = e->hmax();
221 
222  if (_level_set_fe_size < d_12)
223  _level_set_fe_size = d_12;
224  }
225 }
226 
227 
228 void
229 MAST::FilterBase::print(std::ostream& o) const {
230 
231  o << "Filter radius: " << _radius << std::endl;
232 
233  o
234  << std::setw(20) << "Filtered ID"
235  << std::setw(20) << "Dependent Vars" << std::endl;
236 
237  std::map<unsigned int, std::vector<std::pair<unsigned int, Real>>>::const_iterator
238  map_it = _filter_map.begin(),
239  map_end = _filter_map.end();
240 
241  for ( ; map_it != map_end; map_it++) {
242 
243  o
244  << std::setw(20) << map_it->first;
245 
246  std::vector<std::pair<unsigned int, Real>>::const_iterator
247  vec_it = map_it->second.begin(),
248  vec_end = map_it->second.end();
249 
250  for ( ; vec_it != vec_end; vec_it++) {
251 
252  if (_dv_dof_ids.count(map_it->first))
253  o
254  << " : " << std::setw(8) << vec_it->first
255  << " (" << std::setw(8) << vec_it->second << " )";
256  else
257  libMesh::out << " : " << map_it->first;
258  }
259  libMesh::out << std::endl;
260  }
261 }
262 
virtual void print(std::ostream &o) const
prints the filter data.
libMesh::System & _level_set_system
system on which the level set discrete function is defined
Definition: filter_base.h:88
std::map< unsigned int, std::vector< std::pair< unsigned int, Real > > > _filter_map
Algebraic relation between filtered level set values and the design variables .
Definition: filter_base.h:111
bool if_elem_in_domain_of_influence(const libMesh::Elem &elem, const libMesh::Node &level_set_node) const
function identifies if the given element is within the domain of influence of this specified level se...
Real _level_set_fe_size
largest element size in the level set mesh
Definition: filter_base.h:99
libMesh::Real Real
const std::set< unsigned int > & _dv_dof_ids
dof ids that are design variables.
Definition: filter_base.h:105
Real _radius
radius of the filter.
Definition: filter_base.h:93
void compute_filtered_values(const libMesh::NumericVector< Real > &input, libMesh::NumericVector< Real > &output) const
computes the filtered output from the provided input.
Definition: filter_base.cpp:53
void _init()
initializes the algebraic data structures
FilterBase(libMesh::System &sys, const Real radius, const std::set< unsigned int > &dv_dof_ids)
Definition: filter_base.cpp:33
virtual ~FilterBase()
Definition: filter_base.cpp:47