Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NuLaplacian.C
Go to the documentation of this file.
1 /* *******************************************************************
2  * Rocstar Simulation Suite *
3  * Copyright@2015, Illinois Rocstar LLC. All rights reserved. *
4  * *
5  * Illinois Rocstar LLC *
6  * Champaign, IL *
7  * www.illinoisrocstar.com *
8  * sales@illinoisrocstar.com *
9  * *
10  * License: See LICENSE file in top level of distribution package or *
11  * http://opensource.org/licenses/NCSA *
12  *********************************************************************/
13 /* *******************************************************************
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *
16  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR *
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
21  * USE OR OTHER DEALINGS WITH THE SOFTWARE. *
22  *********************************************************************/
23 // $Id: NuLaplacian.C,v 1.8 2008/12/06 08:45:27 mtcampbe Exp $
24 
25 #include "FaceOffset_3.h"
26 #include "../Rocblas/include/Rocblas.h"
27 #include "../Rocsurf/include/Generic_element_2.h"
28 #include "../Rocsurf/include/Rocsurf.h"
29 
31 
32 // At input, vcenters contains displacements due to Laplacian smoothing,
33 // disps is used as buffer space during smoothing.
34 // At output, vcenters contains the tangential motion.
35 void FaceOffset_3::
36 nulaplacian_smooth( const COM::Attribute *vert_normals,
37  const COM::Attribute *tangranks,
38  const COM::Attribute *disps,
39  COM::Attribute *vcenters,
40  COM::Attribute *buf,
41  COM::Attribute *vert_weights_buf,
42  const COM::Attribute *edge_weights) {
43  const double alpha = 0.03;
44 
45  // First, sum up weights for each vertex.
46  double eps = 1.e-100;
47  Rocblas::copy_scalar( &eps, vert_weights_buf);
48 
49  // Loop through the panes and its real faces
50  std::vector< COM::Pane*>::iterator it = _panes.begin();
51  for ( int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
52  COM::Pane *pane = *it;
53 
54  // Obtain address for buffer space for vertex weights
55  double *vws = reinterpret_cast<double*>
56  (pane->attribute(vert_weights_buf->id())->pointer());
57  // Obtain address for edge weights
58  const double *ews = edge_weights ? reinterpret_cast<const double*>
59  (pane->attribute(edge_weights->id())->pointer()) : NULL;
60 
61  Element_node_enumerator ene( pane, 1);
62  // Loop through the real elements of the pane
63  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
64  int ne = ene.size_of_edges();
65 
66  COM_assertion_msg( ne==4, "NuLapacian supports only quadrilateral meshes");
67 
68  // Loop through the vertices of the element to compute weights
69  for ( int k=0; k<ne; ++k) {
70  vws[ene[k]-1] += ews ? ews[j*4+k] + ews[j*4+(k+3)%4] : 1;
71  }
72  }
73  }
74  _surf->reduce_on_shared_nodes( vert_weights_buf, Manifold::OP_SUM);
75 
76  // Zero out buf
77  double zero=0;
78  Rocblas::copy_scalar( &zero, buf);
79 
80  // Loop through the panes and its real faces
81  it = _panes.begin();
82  for ( int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
83  COM::Pane *pane = *it;
84 
85  // Obtain nodal coordinates of current pane, assuming contiguous layout
86  const Vector_3 *pnts = reinterpret_cast<Vector_3*>
87  (pane->attribute(COM_NC)->pointer());
88  const Vector_3 *ds = reinterpret_cast<Vector_3*>
89  (pane->attribute(disps->id())->pointer());
90  const Vector_3 *nrms = reinterpret_cast<Vector_3*>
91  (pane->attribute(vert_normals->id())->pointer());
92  const Vector_3 *vcnt = reinterpret_cast<Vector_3*>
93  (pane->attribute(vcenters->id())->pointer());
94 
95  // Obtain address for output displacements
96  Vector_3 *dbuf = reinterpret_cast<Vector_3*>
97  (pane->attribute(buf->id())->pointer());
98  // Obtain address for buffer space for vertex weights
99  const double *vws = reinterpret_cast<const double*>
100  (pane->attribute(vert_weights_buf->id())->pointer());
101  // Obtain address for edge weights
102  const double *ews = edge_weights ? reinterpret_cast<const double*>
103  (pane->attribute(edge_weights->id())->pointer()) : NULL;
104 
105  // pnts_buf stores difference between center and perturbed position.
106  Vector_3 pnts_buf[4];
107  int is_regular[4];
108 
109  Element_node_enumerator ene( pane, 1);
110  // Loop through the real elements of the pane
111  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
112  int ne = ene.size_of_edges();
113 
114  COM_assertion_msg( ne==4,
115  "NuLapacian now supports only quadrilateral meshes");
116 
117  // Compute face center of the face perturbed along normal direction.
118  Vector_3 cnt(0,0,0);
119  for ( int k=0; k<ne; ++k) {
120  int uindex = ene[k]-1;
121 
122  is_regular[k] = std::abs(vws[uindex]-4)<1.e-6;
123  pnts_buf[k] = pnts[uindex] + ds[uindex];
124 
125  cnt += pnts_buf[k];
126  }
127  cnt *= 0.25; // Divide cnt by ne
128 
129  // pnts_buf contains the displacements from the face center to the vertex
130  for ( int k=0; k<ne; ++k) pnts_buf[k] -= cnt;
131 
132  // Loop through the edges of the element
133  int uindex=ene[ne-1]-1, vindex=ene[0]-1;
134  for ( int k=0; k<ne; ++k, uindex=vindex, vindex=ene[(k==ne)?0:k]-1) {
135  // Compute normal of the perturbed edge as the cross product
136  // of the vertex normal and edge tangent
137  Vector_3 tng = pnts[uindex]-pnts[vindex]+ vcnt[uindex]-vcnt[vindex];
138  double w = ews ? ews[j*4+k] : 0.5;
139 
140  int k_1 = (k+3)%4;
141  if ( is_regular[k_1]) {
142  // Accumulate buf and vert_weights for vertex uindex
143  Vector_3 nrm_e=Vector_3::cross_product(tng, nrms[uindex]).normalize();
144 
145  dbuf[uindex] -= w * ( pnts_buf[k_1] * nrm_e * nrm_e +
146  alpha * pnts_buf[k_1]);
147  }
148 
149  if ( is_regular[k]) {
150  // Accumulate buf and vert_weights for vertex vindex
151  Vector_3 nrm_e=Vector_3::cross_product(tng, nrms[vindex]).normalize();
152 
153  dbuf[vindex] -= w * ( pnts_buf[k] * nrm_e * nrm_e +
154  alpha * pnts_buf[k]);
155  }
156  }
157  }
158  }
159 
160  // Reduce on shared nodes for buf and vert_weights_buf
161  _surf->reduce_on_shared_nodes( buf, Manifold::OP_SUM);
162 
163  // Loop through all real vertices to update displacement vector
164  it = _panes.begin();
165  for (int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
166  COM::Pane *pane = *it;
167 
168  const char *tranks = reinterpret_cast<const char*>
169  ( pane->attribute( tangranks->id())->pointer());
170  const double *vws = reinterpret_cast<const double*>
171  ( pane->attribute( vert_weights_buf->id())->pointer());
172 
173  Vector_3 *vcnt = reinterpret_cast<Vector_3*>
174  ( pane->attribute( vcenters->id())->pointer());
175  Vector_3 *dbuf = reinterpret_cast<Vector_3*>
176  ( pane->attribute( buf->id())->pointer());
177 
178  const Vector_3 *es = reinterpret_cast<const Vector_3*>
179  ( pane->attribute(_eigvecs->id())->pointer());
180 
181  // Loop through all real nodes of the pane
182  for ( int j=0, nj=pane->size_of_real_nodes(); j<nj; ++j) {
183  // If vertex is unmasked and is regular
184  if ( std::abs(vws[j]-4) < 1.e-6) {
185  // Assign the displacement to be the weighted average of projections
186  vcnt[j] = dbuf[j] / vws[j];
187 
188  if ( tranks[j] == 1) // Project onto the direction
189  vcnt[j] = (vcnt[j]*es[3*j+2])*es[3*j+2];
190  else if ( tranks[j] == 2) // Project onto the plane
191  vcnt[j] -= (vcnt[j]*es[3*j])*es[3*j];
192  else
193  vcnt[j] = Vector_3(0,0,0);
194  }
195  }
196  }
197 }
198 
200 
201 
202 
203 
204 
205 
An adaptor for enumerating node IDs of an element.
#define PROP_END_NAMESPACE
Definition: propbasic.h:29
j indices k indices k
Definition: Indexing.h:6
#define PROP_BEGIN_NAMESPACE
Definition: propbasic.h:28
#define COM_assertion_msg(EX, msg)
SURF::Vector_3< Real > Vector_3
Definition: rfc_basic.h:42
Vector_3 & normalize()
Definition: mapbasic.h:114
std::vector< COM::Pane * > _panes
COM::Attribute * _eigvecs
Definition: FaceOffset_3.h:407
int size_of_edges() const
Number of edges per element.
blockLoc i
Definition: read.cpp:79
Manifold * _surf
static Vector_3 cross_product(const Vector_3 &v, const Vector_3 &w)
Definition: mapbasic.h:104
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
j indices j
Definition: Indexing.h:6
NT abs(const NT &x)
Definition: number_utils.h:130
void next()
Go to the next element within the connectivity tables of a pane.
void int * nj
Definition: read.cpp:74
Some basic geometric data types.
Definition: mapbasic.h:54
void nulaplacian_smooth(const COM::Attribute *vert_normals, const COM::Attribute *tangranks, const COM::Attribute *disps, COM::Attribute *vcenters, COM::Attribute *buf, COM::Attribute *vert_weights_buf, const COM::Attribute *edge_weights=NULL)
Redistribute smooth vertices by NuLaplacian smoothing.
Definition: NuLaplacian.C:36