Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
compute_bounded_volumes.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: compute_bounded_volumes.C,v 1.6 2008/12/06 08:43:23 mtcampbe Exp $
24 
31 /* Author: Phillip Alexander
32  * Dates: Dec. 13, 2002
33  */
34 
35 #include "Rocsurf.h"
36 #include "roccom_devel.h"
37 #include "Element_accessors.h"
38 #include "Generic_element_2.h"
39 #include <math.h>
40 #include <vector>
41 
43 
44 void arrange(Point_3<Real> ps_face[4],
45  Point_3<Real> ps[8],
46  int ind1,
47  int ind2,
48  int ind3,
49  int ind4){
50  ps_face[0] = ps[ind1];
51  ps_face[1] = ps[ind2];
52  ps_face[2] = ps[ind3];
53  ps_face[3] = ps[ind4];
54 }
55 
56 void arrange(Point_3<Real> ps_face[3],
57  Point_3<Real> ps[8],
58  int ind1,
59  int ind2,
60  int ind3){
61  ps_face[0] = ps[ind1];
62  ps_face[1] = ps[ind2];
63  ps_face[2] = ps[ind3];
64 }
65 
66 
67 Real get_face_volume(Point_3<Real> ps_face[], int ne) {
68 
69  Generic_element_2 e(ne);
70  Vector_2<Real> nc(0,0);
71  Vector_3<Real> J[2];
72  int order = 1;
73 
74  int size = e.get_num_gp(order);
75  Real volume = 0;
76  for (int k = 0; k<size; k++){
77  Real weight = e.get_gp_weight( k, order);
78  e.get_gp_nat_coor(k, nc, order);
79 
81  e.interpolate(ps_face,nc,&x);
82 
83  e.Jacobian( ps_face,nc,J);
84  // Get the normal to the face
86 
87  Real t = weight * (n*(Vector_3<Real>&)x);
88 
89  // compute the volume, and add to running total
90  volume += t;
91  }
92  return volume;
93 }
94 
95 void normalize_coor( Point_3<Real> ps_face[], int n, int k) {
96  Vector_3<Real> c(0,0,0);
97 
98  for ( int i=0; i<n; ++i) {
99  c += (Vector_3<Real>&)ps_face[i];
100  }
101  c /= k;
102 
103  for ( int i=0; i<n; ++i) {
104  ps_face[i] -= c;
105  }
106 }
107 
108 void Rocsurf::compute_bounded_volumes( const COM::Attribute *old_location,
109  const COM::Attribute *new_location,
110  COM::Attribute *element_volume,
111  void *flag) {
112 
113  assert( element_volume != NULL && element_volume ->size_of_components() == 1);
114  assert( element_volume->window() == old_location->window());
115  assert( element_volume->window() == new_location->window());
116 
117  std::vector< COM:: Pane*> panes;
118  element_volume->window() -> panes( panes);
119 
120  Point_3<Real> ps_face4[4];
121  Point_3<Real> ps_face3[3];
122  Point_3<Real> ps[8];
123 
124  // ps is used as a container for both the old and new coordinates
125  // the following ordering convention is used:
126  // the coordinates of the new surface occupy indexes 0 to 3
127  // the coordinates of the old surface occupy indexes 4 to 7
128  // both surfaces have coordinates listed in the same order
129  // i.e. ps[0] and ps[4] are new and old coordinates for the same node
130  // under these conventions, ps[3] and ps[7] are not used for triangular faces
131 
132  std::vector< COM::Pane*>::const_iterator it = panes.begin();
133  // Loop through the elements of the pane.
134  for (int i=0, local_npanes = panes.size(); i<local_npanes; ++i, ++it){
135  const COM::Pane &pane = **it;
136  Real *ptr_ev = (Real *)(pane.attribute( element_volume->id())->pointer());
137  const Point_3<Real> *ptr_new =
138  (const Point_3<Real>*)(pane.attribute( new_location->id())->pointer());
139  const Point_3<Real> *ptr_old =
140  (const Point_3<Real>*)(pane.attribute( old_location->id())->pointer());
141 
143 
144  Element_node_enumerator ene( &pane, 1);
145  for ( int j=pane.size_of_elements(); j>0; --j, ene.next(), ++ptr_ev) {
146  if ( flag!=NULL && *ptr_ev==0.) continue;
147 
148  Real volume = 0;
149  // if mesh is triangular, we have two triangular faces, 3 quadrilaterals
150  ps_new.set( ptr_new, ene, 1);
151  ps_old.set( ptr_old, ene, 1);
152 
153  ps[0]=ps_new[0];ps[1]=ps_new[1];ps[2]=ps_new[2];
154  ps[4]=ps_old[0];ps[5]=ps_old[1];ps[6]=ps_old[2];
155 
156  if (ene.size_of_edges()==3) {
157 
158  if ( ps[0]==ps[4] && ps[1]==ps[5] && ps[2]==ps[6])
159  { *ptr_ev = 0.; continue; }
160  ps[3] = Point_3<Real>(0,0,0);
161  normalize_coor( ps, 7, 6);
162 
163  // solid has two triangular faces
164  arrange(ps_face3,ps,0,2,1);
165  volume += get_face_volume(ps_face3, 3);
166  arrange(ps_face3,ps,4,5,6);
167  volume += get_face_volume(ps_face3, 3);
168  // quadrilateral faces
169  arrange(ps_face4,ps,0,4,6,2);
170  volume += get_face_volume(ps_face4, 4);
171  }
172  else{ // if not triangular, mesh is quadrilateral
173  ps[3]=ps_new[3]; ps[7]=ps_old[3];
174  if ( ps[0]==ps[4] && ps[1]==ps[5] && ps[2]==ps[6] && ps[3]==ps[7])
175  { *ptr_ev = 0.; continue; }
176  normalize_coor( ps, 8, 8);
177 
178  arrange(ps_face4,ps,0,3,2,1);
179  volume += get_face_volume(ps_face4, 4);
180  arrange(ps_face4,ps,4,5,6,7);
181  volume += get_face_volume(ps_face4, 4);
182  arrange(ps_face4,ps,3,7,6,2);
183  volume += get_face_volume(ps_face4, 4);
184  arrange(ps_face4,ps,0,4,7,3);
185  volume += get_face_volume(ps_face4, 4);
186  }
187  // Two quarilateral faces are the same in either case
188  arrange(ps_face4,ps,1,2,6,5);
189  volume += get_face_volume(ps_face4, 4);
190  arrange(ps_face4,ps,0,1,5,4);
191  volume += get_face_volume(ps_face4, 4);
192 
193  volume /= 3.;
194  *ptr_ev = -volume;
195  }
196  }
197 }
198 
199 void Rocsurf::compute_swept_volumes( const COM::Attribute *location,
200  const COM::Attribute *disps,
201  COM::Attribute *element_volume,
202  void *flag) {
203 
204  assert( element_volume != NULL && element_volume ->size_of_components() == 1);
205  assert( element_volume->window() == location->window());
206  assert( element_volume->window() == disps->window());
207 
208  std::vector< COM:: Pane*> panes;
209  element_volume->window() -> panes( panes);
210 
211  Point_3<Real> ps_face4[4];
212  Point_3<Real> ps_face3[3];
213  Point_3<Real> ps[8];
214 
215  // ps is used as a container for both the old and new coordinates
216  // the following ordering convention is used:
217  // the coordinates of the new surface occupy indexes 0 to 3
218  // the coordinates of the old surface occupy indexes 4 to 7
219  // both surfaces have coordinates listed in the same order
220  // i.e. ps[0] and ps[4] are new and old coordinates for the same node
221  // under these conventions, ps[3] and ps[7] are not used for triangular faces
222 
223  std::vector< COM::Pane*>::const_iterator it = panes.begin();
224  // Loop through the elements of the pane.
225  for (int i=0, local_npanes = panes.size(); i<local_npanes; ++i, ++it){
226  const COM::Pane &pane = **it;
227  Real *ptr_ev = (Real *)(pane.attribute( element_volume->id())->pointer());
228  const Point_3<Real> *ptr_pos =
229  (const Point_3<Real>*)(pane.attribute( location->id())->pointer());
230  const Vector_3<Real> *ptr_disp =
231  (const Vector_3<Real>*)(pane.attribute( disps->id())->pointer());
232 
235 
236  Element_node_enumerator ene( &pane, 1);
237  for ( int j=pane.size_of_elements(); j>0; --j, ene.next(), ++ptr_ev) {
238  if ( flag!=NULL && *ptr_ev==0.) continue;
239 
240  Real volume = 0;
241  // if mesh is triangular, we have two triangular faces, 3 quadrilaterals
242  ds.set( ptr_disp, ene, 1);
243  pnts.set( ptr_pos, ene, 1);
244 
245  ps[0]=pnts[0]+ds[0];ps[1]=pnts[1]+ds[1];ps[2]=pnts[2]+ds[2];
246  ps[4]=pnts[0];ps[5]=pnts[1];ps[6]=pnts[2];
247 
248  if (ene.size_of_edges()==3) {
249 
250  if ( ps[0]==ps[4] && ps[1]==ps[5] && ps[2]==ps[6])
251  { *ptr_ev = 0.; continue; }
252  ps[3] = Point_3<Real>(0,0,0);
253  normalize_coor( ps, 7, 6);
254 
255  // solid has two triangular faces
256  arrange(ps_face3,ps,0,2,1);
257  volume += get_face_volume(ps_face3, 3);
258  arrange(ps_face3,ps,4,5,6);
259  volume += get_face_volume(ps_face3, 3);
260  // quadrilateral faces
261  arrange(ps_face4,ps,0,4,6,2);
262  volume += get_face_volume(ps_face4, 4);
263  }
264  else{ // if not triangular, mesh is quadrilateral
265  ps[3]=pnts[3]+ds[3]; ps[7]=pnts[3];
266  if ( ps[0]==ps[4] && ps[1]==ps[5] && ps[2]==ps[6] && ps[3]==ps[7])
267  { *ptr_ev = 0.; continue; }
268  normalize_coor( ps, 8, 8);
269 
270  arrange(ps_face4,ps,0,3,2,1);
271  volume += get_face_volume(ps_face4, 4);
272  arrange(ps_face4,ps,4,5,6,7);
273  volume += get_face_volume(ps_face4, 4);
274  arrange(ps_face4,ps,3,7,6,2);
275  volume += get_face_volume(ps_face4, 4);
276  arrange(ps_face4,ps,0,4,7,3);
277  volume += get_face_volume(ps_face4, 4);
278  }
279  // Two quarilateral faces are the same in either case
280  arrange(ps_face4,ps,1,2,6,5);
281  volume += get_face_volume(ps_face4, 4);
282  arrange(ps_face4,ps,0,1,5,4);
283  volume += get_face_volume(ps_face4, 4);
284 
285  volume /= 3.;
286  *ptr_ev = -volume;
287  }
288  }
289 }
290 
291 void Rocsurf::compute_center( const COM::Attribute *mesh,
292  Vector_3<Real> &cnt) {
293  std::vector< const COM:: Pane*> panes;
294  mesh->window() -> panes( panes);
295 
296  struct Accumulator {
297  Accumulator() : cnt(Vector_3<Real>(0,0,0)), count(0) {}
298 
299  Vector_3<Real> cnt;
300  double count;
301  };
302  Accumulator global;
303 
304  std::vector< const COM::Pane*>::const_iterator it = panes.begin();
305  // Loop through the elements of the pane.
306  for (int i=0, local_npanes = panes.size(); i<local_npanes; ++i, ++it){
307  const COM::Pane &pane = **it;
308  const Vector_3<Real> *ptr =
309  (const Vector_3<Real>*)(pane.attribute( COM::COM_NC)->pointer());
310 
311  for ( int j=pane.size_of_real_nodes(); j>0; --j, ++ptr) {
312  global.cnt += *ptr;
313  global.count += 1.;
314  }
315  }
316 
317  // Perform reduction on cnt and count
318  Accumulator local=global;
319 
320  if ( COMMPI_Initialized()) {
321  MPI_Allreduce( &local.cnt[0], &global.cnt[0], 4, MPI_DOUBLE, MPI_SUM,
322  mesh->window()->get_communicator());
323  }
324  cnt = global.cnt/global.count;
325 }
326 
327 
328 void Rocsurf::
329 compute_signed_volumes( const COM::Attribute *mesh, double *vol) {
330  std::vector< const COM:: Pane*> panes;
331  mesh->window() -> panes( panes);
332 
333  Vector_3<Real> cnt;
334  // First, obtain the center
335  compute_center( mesh, cnt);
336 
337  Point_3<Real> normalized_face[4];
338 
339  *vol = 0;
340  std::vector< const COM::Pane*>::const_iterator it = panes.begin();
341  // Loop through the elements of the pane.
342  for (int i=0, local_npanes = panes.size(); i<local_npanes; ++i, ++it){
343  const COM::Pane &pane = **it;
344  const Point_3<Real> *ptr =
345  (const Point_3<Real>*)(pane.attribute( COM::COM_NC)->pointer());
346 
348 
349  Element_node_enumerator ene( &pane, 1);
350  for ( int j=pane.size_of_elements(); j>0; --j, ene.next()) {
351  ps.set( ptr, ene, 1);
352 
353  normalized_face[0]=ps[0]-cnt;
354  normalized_face[1]=ps[1]-cnt;
355  normalized_face[2]=ps[2]-cnt;
356 
357  if (ene.size_of_edges()==3) {
358  *vol += get_face_volume(normalized_face, 3);
359  }
360  else{ // if not triangular, element is quadrilateral
361  normalized_face[3]=ps[3]-cnt;
362  *vol += get_face_volume(normalized_face, 4);
363  }
364  }
365  }
366 
367  // Divide the signed volume by 3.
368  *vol /= 3.;
369 }
370 
371 
373 
374 
375 
376 
377 
378 
An adaptor for enumerating node IDs of an element.
j indices k indices k
Definition: Indexing.h:6
void normalize_coor(Point_3< Real > ps_face[], int n, int k)
#define SURF_END_NAMESPACE
Definition: surfbasic.h:29
void get_gp_nat_coor(const Size i, Nat_coor &nc, const Size doa=0) const
Get the natrual coordinate associated with a Gauss point.
Encapsulation of the element-wise computations for two-dimensional elements.
Real get_gp_weight(const Size i, const Size doa=0) const
Get the weight associated with a Gauss point.
double Real
Definition: mapbasic.h:322
static void compute_bounded_volumes(const COM::Attribute *old_location, const COM::Attribute *new_location, COM::Attribute *volumes, void *flag=NULL)
Computes the volume bounded between two different locations of each face of the surface mesh of windo...
void interpolate(const Field &f, const Nat_coor &nc, Value *v) const
Interpolates the field data at a given point.
static void compute_signed_volumes(const COM::Attribute *mesh, double *vol)
Computes the signed volume of a body.
#define SURF_BEGIN_NAMESPACE
Definition: surfbasic.h:28
This is a helper class for accessing nodal data.
int volume(const block *b)
Definition: split.cpp:181
int size_of_edges() const
Number of edges per element.
blockLoc i
Definition: read.cpp:79
void int int REAL * x
Definition: read.cpp:74
SURF_BEGIN_NAMESPACE void arrange(Point_3< Real > ps_face[4], Point_3< Real > ps[8], int ind1, int ind2, int ind3, int ind4)
const NT & n
static Vector_3 cross_product(const Vector_3 &v, const Vector_3 &w)
Definition: mapbasic.h:104
Real get_face_volume(Point_3< Real > ps_face[], int ne)
j indices j
Definition: Indexing.h:6
static void compute_center(const COM::Attribute *mesh, Vector_3< double > &cnt)
Computes the center of a body.
static void compute_swept_volumes(const COM::Attribute *location, const COM::Attribute *disps, COM::Attribute *volumes, void *flag=NULL)
Computes the swept volume by a given displacement of each face of the surface mesh of window volumes-...
Size get_num_gp(const Size doa=0) const
Get the number of Gauss points.
void set(const Value *p, Element_node_enumerator &ene, int strd)
initialize the accessor with a pointer and a specific stride.
void Jacobian(const Field &f, const Nat_coor &nc, Vector_3 J[2]) const
Evaluates the Jacobian at a given point.
void next()
Go to the next element within the connectivity tables of a pane.
int COMMPI_Initialized()
Definition: commpi.h:168
here we put it at the!beginning of the common block The point to point and collective!routines know about but MPI_TYPE_STRUCT as yet does not!MPI_STATUS_IGNORE and MPI_STATUSES_IGNORE are similar objects!Until the underlying MPI library implements the C version of these are declared as arrays of MPI_STATUS_SIZE!The types and are OPTIONAL!Their values are zero if they are not available Note that!using these reduces the portability of MPI_IO INTEGER MPI_BOTTOM INTEGER MPI_DOUBLE_PRECISION INTEGER MPI_LOGICAL INTEGER MPI_2REAL INTEGER MPI_2DOUBLE_COMPLEX INTEGER MPI_LB INTEGER MPI_WTIME_IS_GLOBAL INTEGER MPI_GROUP_EMPTY INTEGER MPI_SUM