faceted_setup.h
Go to the documentation of this file.
1 /*
2  This file is part of the Ristra portage project.
3  Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/portage/blob/master/LICENSE
5 */
6 
7 #ifndef FACETED_SETUP_H
8 #define FACETED_SETUP_H
9 
10 #include <vector>
11 #include <algorithm>
12 #include <stdexcept>
13 
14 #include "wonton/mesh/AuxMeshTopology.h"
15 #include "wonton/support/Point.h"
16 #include "portage/support/weight.h"
18 
19 namespace Portage { namespace Meshfree { namespace Weight {
20 
37 template<int dim, class Mesh>
38 void faceted_setup_cell(Mesh const& mesh,
39  Portage::vector<std::vector<std::vector<double>>>& smoothing_lengths,
40  Portage::vector<Wonton::Point<dim>>& extents,
41  double smoothing_factor, double boundary_factor) {
42 
43  if (smoothing_factor < 0.) {
44  throw std::runtime_error("smoothing_factor must be non-negative");
45  } else if (boundary_factor < 0.) {
46  throw std::runtime_error("boundary_factor must be non-negative");
47  }
48 
49  int ncells = mesh.num_owned_cells();
50  smoothing_lengths.resize(ncells);
51  extents.resize(ncells);
52 
53  // get face normal and distance information
54  for (int i = 0; i < ncells; i++) {
55  std::vector<int> faces, fdirs;
56  mesh.cell_get_faces_and_dirs(i, &faces, &fdirs);
57 
58  int nfaces = faces.size();
59  std::vector<std::vector<double>> h = smoothing_lengths[i];
60  h.resize(nfaces);
61 
62  Wonton::Point<dim> fcent, ccent, normal, distance;
63  std::vector<int> fnodes;
64  std::vector<Wonton::Point<dim>> fncoord;
65  for (int j = 0; j < nfaces; j++) {
66  // get face data
67  mesh.face_centroid(faces[j], &fcent);
68  mesh.cell_centroid(i, &ccent);
69  mesh.face_get_nodes(faces[j], &fnodes);
70  int const num_face_nodes = fnodes.size();
71  fncoord.resize(num_face_nodes + 1);
72  for (int k = 0; k < num_face_nodes; k++) {
73  mesh.node_get_coordinates(fnodes[k], &(fncoord[k]));
74  }
75  fncoord[num_face_nodes] = fncoord[0];
76 
77  if (dim == 2) {
78  // Get 2d face normal
79  std::vector<double> delta(2);
80  for (int k = 0; k < 2; k++) delta[k] = fncoord[1][k] - fncoord[0][k];
81  normal[0] = delta[1];
82  normal[1] = -delta[0];
83  if (fdirs[j] < 0) normal *= -1.0;
84  double norm = sqrt(normal[0] * normal[0] + normal[1] * normal[1]);
85  normal /= norm;
86  h[j].resize(3);
87  h[j][0] = normal[0];
88  h[j][1] = normal[1];
89  } else if (dim == 3) {
90  // Get 3d face normal using average cross product, in case face is not flat
91  // or has nodes close together.
92  std::vector<std::vector<double>> bivec(2, std::vector<double>(3, 0.));
93  for (int k = 0; k < 3; k++) {
94  bivec[0][k] = fncoord[0][k] - fcent[k];
95  normal[k] = 0.;
96  }
97 
98  //int const num_face_nodes = fnodes.size();
99  for (int k = 1; k <= num_face_nodes; k++) {
100  for (int m = 0; m < 3; m++) bivec[1][m] = fncoord[k][m] - fcent[m];
101  std::vector<double> cross(3, 0.);
102  cross[0] = bivec[1][2] * bivec[0][1] - bivec[1][1] * bivec[0][2];
103  cross[1] = -bivec[1][2] * bivec[0][0] + bivec[1][0] * bivec[0][2];
104  cross[2] = bivec[1][1] * bivec[0][0] - bivec[1][0] * bivec[0][1];
105  double norm = sqrt(cross[0] * cross[0] + cross[1] * cross[1] + cross[2] * cross[2]);
106  for (int m = 0; m < 3; m++) {
107  cross[m] /= norm;
108  }
109  normal += cross;
110  bivec[0] = bivec[1];
111  }
112  if (fdirs[j] < 0) normal *= -1.0;
113  double norm = 0.;
114  for (int k = 0; k < 3; k++) norm += normal[k] * normal[k];
115  norm = sqrt(norm);
116  normal /= norm;
117  h[j].resize(4);
118  for (int k = 0; k < 3; k++) h[j][k] = normal[k];
119  }
120 
121  distance = Wonton::Point<dim>(fcent - ccent);
122  double smoothing = 0.0;
123  for (int k = 0; k < dim; k++) smoothing += 2 * distance[k] * normal[k];
124  if (smoothing < 0.0) { // when nodes are ordered backwards
125  normal = -normal;
126  smoothing = -smoothing;
127  }
128  if (mesh.on_exterior_boundary(Wonton::FACE, faces[j]) and boundary_factor > 0.) {
129  h[j][dim] = boundary_factor * smoothing;
130  } else {
131  h[j][dim] = smoothing_factor * smoothing;
132  }
133  }
134  smoothing_lengths[i] = h;
135  }
136 
137  // get extent information
138  for (int i = 0; i < ncells; i++) {
139  // calculate the min and max of coordinates
140  std::vector<int> node_indices;
141  mesh.cell_get_nodes(i, &node_indices);
142  Wonton::Point<dim> cmin, cmax, first_coords;
143  mesh.node_get_coordinates(node_indices[0], &first_coords);
144 
145  for (int k = 0; k < dim; k++) {
146  cmin[k] = first_coords[k];
147  cmax[k] = first_coords[k];
148  }
149 
150  int const num_node_indices = node_indices.size();
151  for (int j = 1; j < num_node_indices; j++) {
152  Wonton::Point<dim> node_coords;
153  mesh.node_get_coordinates(node_indices[j], &node_coords);
154  for (int k = 0; k < dim; k++) {
155  cmin[k] = std::min(node_coords[k], cmin[k]);
156  cmax[k] = std::max(node_coords[k], cmax[k]);
157  }
158  }
159 
160  // subtract to get extents
161  Wonton::Point<dim> dx;
162  for (int k = 0; k < dim; k++) { dx[k] = cmax[k] - cmin[k]; }
163 
164  // multiply by smoothing_factor
165  for (int k = 0; k < dim; k++) { dx[k] *= 2. * smoothing_factor; }
166 
167  extents[i] = dx;
168  }
169 }
170 
171 
189 template<int dim, class Mesh>
190 void faceted_setup_cell(std::vector<Mesh*> meshes,
191  Portage::vector<std::vector<std::vector<double>>>& smoothing_lengths,
192  Portage::vector<Wonton::Point<dim>>& extents,
193  double smoothing_factor, double boundary_factor) {
194 
195  int total_cells = 0;
196  int offset = 0;
197 
198  for (auto&& mesh : meshes)
199  total_cells += mesh->num_owned_cells();
200 
201  smoothing_lengths.resize(total_cells);
202  extents.resize(total_cells);
203 
204  for (auto&& mesh : meshes) {
205  int ncells = mesh->num_owned_cells();
208  faceted_setup_cell<dim, Mesh>(*mesh, sl, ex, smoothing_factor, boundary_factor);
209  for (int i = 0; i < ncells; i++) {
210  smoothing_lengths[offset + i] = sl[i];
211  extents[offset + i] = ex[i];
212  }
213  offset += ncells;
214  }
215 }
216 
217 
251 template<int dim, class Mesh, class State>
252 void faceted_setup_cell(const Mesh& mesh, const State& state,
253  std::string field, double tolerance,
254  Portage::vector<std::vector<std::vector<double>>>& smoothing_lengths,
255  Portage::vector<Wonton::Point<dim>>& extents,
256  double smoothing_factor, double boundary_factor) {
257 
258  faceted_setup_cell(mesh, smoothing_lengths, extents,
259  smoothing_factor, smoothing_factor);
260 
261  double *fval;
262  const_cast<State&>(state).mesh_get_data(Wonton::CELL, field, &fval);
263 
264  for (int i = 0; i < mesh.num_owned_cells(); i++) {
265  std::vector<int> faces, dirs, fcells;
266  mesh.cell_get_faces_and_dirs(i, &faces, &dirs);
267  std::vector<std::vector<double>> h = smoothing_lengths[i];
268  int const num_faces = faces.size();
269  for (int j = 0; j < num_faces; j++) {
270  mesh.face_get_cells(faces[j], Wonton::PARALLEL_OWNED, &fcells);
271  for (int k : fcells) {
272  if (k == i) continue;
273  if (std::fabs(fval[i] - fval[k]) > tolerance) {
274  h[j][dim] *= (boundary_factor / smoothing_factor);
275  }
276  }
277  }
278  smoothing_lengths[i] = h;
279  }
280 }
281 
282 }}} // namespace Portage::Meshfree::Weight
283 #endif
std::vector< T > vector
Definition: portage.h:238
Definition: coredriver.h:42