27 #include "libmesh/mesh_base.h" 28 #include "libmesh/node.h" 29 #include "libmesh/numeric_vector.h" 30 #ifdef LIBMESH_HAVE_NANOFLANN 31 #include "libmesh/nanoflann.hpp" 37 const std::set<unsigned int>& dv_dof_ids):
38 _level_set_system (sys),
40 _level_set_fe_size (0.),
41 _dv_dof_ids (dv_dof_ids) {
43 libmesh_assert_greater(radius, 0.);
45 #ifdef LIBMESH_HAVE_NANOFLANN 60 libMesh::NumericVector<Real>& output,
61 bool close_vector)
const {
63 libmesh_assert_equal_to(input.size(),
_filter_map.size());
64 libmesh_assert_equal_to(output.size(),
_filter_map.size());
68 std::vector<Real> input_vals(input.size(), 0.);
69 input.localize(input_vals);
71 std::map<unsigned int, std::vector<std::pair<unsigned int, Real>>>::const_iterator
75 for ( ; map_it != map_end; map_it++) {
77 std::vector<std::pair<unsigned int, Real>>::const_iterator
78 vec_it = map_it->second.begin(),
79 vec_end = map_it->second.end();
81 for ( ; vec_it != vec_end; vec_it++) {
82 if (map_it->first >= input.first_local_index() &&
83 map_it->first < input.last_local_index()) {
86 output.add(map_it->first, input_vals[vec_it->first] * vec_it->second);
88 output.set(map_it->first, input_vals[map_it->first]);
101 libMesh::NumericVector<Real>& output,
102 bool close_vector)
const {
104 libmesh_assert_equal_to(output.size(),
_filter_map.size());
108 std::map<unsigned int, std::vector<std::pair<unsigned int, Real>>>::const_iterator
112 for ( ; map_it != map_end; map_it++) {
114 std::vector<std::pair<unsigned int, Real>>::const_iterator
115 vec_it = map_it->second.begin(),
116 vec_end = map_it->second.end();
118 for ( ; vec_it != vec_end; vec_it++) {
119 if (nonzero_input.count(vec_it->first)) {
121 if (output.type() == libMesh::SERIAL ||
122 (map_it->first >= output.first_local_index() &&
123 map_it->first < output.last_local_index())) {
126 output.add(map_it->first, nonzero_input[vec_it->first] * vec_it->second);
128 output.set(map_it->first, nonzero_input[map_it->first]);
143 std::vector<Real>& output)
const {
145 libmesh_assert_equal_to(input.size(),
_filter_map.size());
146 libmesh_assert_equal_to(output.size(),
_filter_map.size());
148 std::fill(output.begin(), output.end(), 0.);
150 std::map<unsigned int, std::vector<std::pair<unsigned int, Real>>>::const_iterator
154 for ( ; map_it != map_end; map_it++) {
156 std::vector<std::pair<unsigned int, Real>>::const_iterator
157 vec_it = map_it->second.begin(),
158 vec_end = map_it->second.end();
160 for ( ; vec_it != vec_end; vec_it++) {
162 output[map_it->first] += input[vec_it->first] * vec_it->second;
164 output[map_it->first] += input[map_it->first];
173 const libMesh::Node& level_set_node)
const {
182 for (
unsigned int i=0; i<elem.n_nodes(); i++) {
184 pt -= level_set_node;
199 #ifdef LIBMESH_HAVE_NANOFLANN 201 template <
unsigned int Dim>
202 class NanoflannMeshAdaptor
206 const libMesh::MeshBase & _mesh;
209 NanoflannMeshAdaptor (
const libMesh::MeshBase & mesh) :
216 typedef Real coord_t;
222 kdtree_get_point_count()
const {
return _mesh.n_nodes(); }
229 kdtree_distance(
const coord_t * p1,
233 libmesh_assert_equal_to (size, Dim);
237 libMesh::Point point1(p1[0],
238 size > 1 ? p1[1] : 0.,
239 size > 2 ? p1[2] : 0.);
242 const libMesh::Point & point2 = _mesh.point(idx_p2);
245 return (point1 - point2).norm_sq();
254 kdtree_get_pt(
const size_t idx,
int dim)
const 256 libmesh_assert_less (dim, (
int) Dim);
257 libmesh_assert_less (idx, _mesh.n_nodes());
258 libmesh_assert_less (dim, 3);
260 return _mesh.point(idx)(dim);
269 template <
class BBOX>
270 bool kdtree_get_bbox(BBOX & )
const {
return false; }
282 libmesh_assert(mesh.is_replicated());
291 typedef nanoflann::L2_Simple_Adaptor<Real, NanoflannMeshAdaptor<3> > adatper_t;
294 typedef nanoflann::KDTreeSingleIndexAdaptor<adatper_t, NanoflannMeshAdaptor<3>, 3> kd_tree_t;
297 NanoflannMeshAdaptor<3> mesh_adaptor(mesh);
298 kd_tree_t kd_tree(3, mesh_adaptor, nanoflann::KDTreeSingleIndexAdaptorParams(10));
301 kd_tree.buildIndex();
311 libMesh::MeshBase::const_node_iterator
312 node_it = mesh.nodes_begin(),
313 node_end = mesh.nodes_end();
318 for (; node_it != node_end; node_it++) {
320 const libMesh::Node* node = *node_it;
324 Real query_pt[3] = {(*node)(0), (*node)(1), (*node)(2)};
326 std::vector<std::pair<size_t, Real>>
328 nanoflann::RadiusResultSet<Real, size_t>
331 kd_tree.findNeighbors(resultSet, query_pt, nanoflann::SearchParams());
335 for (
unsigned r=0; r<indices_dists.size(); ++r) {
337 d_12 = std::sqrt(indices_dists[r].second);
341 libmesh_assert_less_equal(d_12, _radius);
343 sum += _radius - d_12;
344 dof_2 = mesh.node_ptr(indices_dists[r].first)->dof_number(
_level_set_system.number(), 0, 0);
346 _filter_map[dof_1].push_back(std::pair<unsigned int, Real>(dof_2, _radius - d_12));
349 libmesh_assert_greater(sum, 0.);
353 std::vector<std::pair<unsigned int, Real>>& vec =
_filter_map[dof_1];
354 for (
unsigned int i=0; i<vec.size(); i++) {
356 vec[i].second /= sum;
357 libmesh_assert_less_equal(vec[i].second, 1.);
362 libMesh::MeshBase::const_element_iterator
363 e_it = mesh.elements_begin(),
364 e_end = mesh.elements_end();
366 for ( ; e_it != e_end; e_it++) {
367 const libMesh::Elem* e = *e_it;
385 libmesh_assert(mesh.is_replicated());
388 libMesh::MeshBase::const_node_iterator
389 node_it_1 = mesh.nodes_begin(),
390 node_it_2 = mesh.nodes_begin(),
391 node_end = mesh.nodes_end();
404 for ( ; node_it_1 != node_end; node_it_1++) {
408 node_it_2 = mesh.nodes_begin();
411 for ( ; node_it_2 != node_end; node_it_2++) {
414 d = (**node_it_1) - (**node_it_2);
427 libmesh_assert_greater(sum, 0.);
431 std::vector<std::pair<unsigned int, Real>>& vec =
_filter_map[dof_1];
432 for (
unsigned int i=0; i<vec.size(); i++) {
434 vec[i].second /= sum;
435 libmesh_assert_less_equal(vec[i].second, 1.);
440 libMesh::MeshBase::const_element_iterator
441 e_it = mesh.elements_begin(),
442 e_end = mesh.elements_end();
444 for ( ; e_it != e_end; e_it++) {
445 const libMesh::Elem* e = *e_it;
457 o <<
"Filter radius: " <<
_radius << std::endl;
460 << std::setw(20) <<
"Filtered ID" 461 << std::setw(20) <<
"Dependent Vars" << std::endl;
463 std::map<unsigned int, std::vector<std::pair<unsigned int, Real>>>::const_iterator
467 for ( ; map_it != map_end; map_it++) {
470 << std::setw(20) << map_it->first;
472 std::vector<std::pair<unsigned int, Real>>::const_iterator
473 vec_it = map_it->second.begin(),
474 vec_end = map_it->second.end();
476 for ( ; vec_it != vec_end; vec_it++) {
480 <<
" : " << std::setw(8) << vec_it->first
481 <<
" (" << std::setw(8) << vec_it->second <<
" )";
483 libMesh::out <<
" : " << map_it->first;
485 libMesh::out << std::endl;
libMesh::System & _level_set_system
system on which the level set discrete function is defined
std::map< unsigned int, std::vector< std::pair< unsigned int, Real > > > _filter_map
Algebraic relation between filtered level set values and the design variables .
Real _level_set_fe_size
largest element size in the level set mesh
void compute_filtered_values(const libMesh::NumericVector< Real > &input, libMesh::NumericVector< Real > &output, bool close_vector=true) const
computes the filtered output from the provided input.
const std::set< unsigned int > & _dv_dof_ids
dof ids that are design variables.
Real _radius
radius of the filter.
void _init()
initializes the algebraic data structures
FilterBase(libMesh::System &sys, const Real radius, const std::set< unsigned int > &dv_dof_ids)
virtual void print(std::ostream &o) const
prints the filter data.
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...