Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Mesh.C
Go to the documentation of this file.
1 #include <iomanip>
6 #include <sstream>
7 #include <cstdlib>
8 #include <algorithm>
9 
10 #include "Mesh.H"
11 
12 namespace Mesh {
13 
15  {
16  ncdata = NULL;
17  nnodes = 0;
18  mydata = false;
19  };
21  {
22  if(n > 0){
23  ncdata = new double [3 * n];
24  nnodes = n;
25  mydata = true;
26  }
27  else {
28  ncdata = NULL;
29  nnodes = 0;
30  mydata = false;
31  }
32  };
34  {
35  if((n > 0) && (data != NULL)){
36  mydata = false;
37  nnodes = n;
38  ncdata = data;
39  }
40  else {
41  ncdata = NULL;
42  nnodes = 0;
43  mydata = false;
44  }
45  };
47  bool Mesh::NodalCoordinates::good() const { return(ncdata ? true : false);};
48  Mesh::IndexType Mesh::NodalCoordinates::size() const { return(nnodes);};
49  Mesh::IndexType Mesh::NodalCoordinates::Size() const { return(nnodes);};
51  if(ncdata && mydata){
52  delete [] ncdata;
53  nnodes = 0;
54  ncdata = NULL;
55  mydata = false;
56  }
57  };
58  void Mesh::NodalCoordinates::init(){destroy();};
60  {
61  destroy();
62  if(n > 0){
63  ncdata = new double [3 * n];
64  nnodes = n;
65  mydata = true;
66  }
67  };
69  {
70  destroy();
71  if(n > 0){
72  ncdata = data;
73  nnodes = n;
74  mydata = false;
75  }
76  };
77 
79  {
80  this->x(n) = point.x();
81  this->y(n) = point.y();
82  this->z(n) = point.z();
83  };
84 
86  {
87  double dist = 1000000;
88  GeoPrim::CPoint retval;
89  for(unsigned int i = 0;i < nnodes;i++){
90  GeoPrim::CPoint testp(&ncdata[3*i]);
91  double testd = (p-testp).norm();
92  if(testd < dist){
93  dist = testd;
94  retval = testp;
95  }
96  }
97  return(retval);
98  };
99 
101  {
102  double dist = 1000000;
103  Mesh::IndexType reti = 0;
104  for(unsigned int i = 0;i < nnodes;i++){
105  GeoPrim::CPoint testp(&ncdata[3*i]);
106  double testd = (p-testp).norm();
107  if(testd < dist){
108  dist = testd;
109  reti = i + 1;
110  }
111  }
112  if(dist_ptr)
113  *dist_ptr = dist;
114  return(reti);
115  };
116 
118  {
119  destroy();
120  if(n > 0 && data){
121  ncdata = new double [3*n];
122  nnodes = n;
123  mydata = true;
124  std::memcpy(ncdata,data,n*sizeof(double)*3);
125  }
126  };
127 
129  Mesh::Connectivity &conn,
131  std::vector<Mesh::IndexType> &candidates,
132  std::vector<Mesh::IndexType> &cells)
133  {
134  std::vector<IndexType>::iterator ci = candidates.begin();
135  while(ci != candidates.end()){
136  unsigned int cell_id = *ci++;
137  unsigned int esize = conn.Esize(cell_id);
138  std::vector<GeoPrim::CPoint> element_points(esize);
139  // Make a vector of the element points
140  for(IndexType node = 1;node <= esize;node++){
141  GeoPrim::CPoint ep(nc[conn.Node(cell_id,node)]);
142  element_points[node-1] = ep;
143  }
144  // Make the bounding box for the element
145  GeoPrim::CBox ebox(element_points);
146  // collide the ebox with the box
147  GeoPrim::CBox cbox(box.intersect(ebox));
148  if(!cbox.empty())
149  cells.push_back(cell_id);
150  }
151 
152  };
153 
155  Mesh::Connectivity &conn,
156  GeoPrim::CBox &box,
157  std::vector<Mesh::IndexType> &cells)
158  {
159  unsigned int nelem = conn.size();
160  IndexType n = 1;
161  while(n <= nelem){
162  unsigned int esize = conn.Esize(n);
163  std::vector<GeoPrim::CPoint> element_points(esize);
164  // Make a vector of the element points
165  for(IndexType node = 1;node <= esize;node++){
166  GeoPrim::CPoint ep(nc[conn.Node(n,node)]);
167  element_points[node-1] = ep;
168  }
169  // Make the bounding box for the element
170  GeoPrim::CBox ebox(element_points);
171  // collide the ebox with the box
172  GeoPrim::CBox cbox = box.intersect(ebox);
173  if(!cbox.empty())
174  cells.push_back(n);
175  n++;
176  }
177 
178  };
179 
181  Mesh::Connectivity &conn,
182  std::vector<double> &centroids)
183  {
184  unsigned int nelem = conn.size();
185  centroids.resize(3*nelem,0.0);
186  for(int i = 0;i < nelem;i++){
187  GeoPrim::C3Point p(&(centroids[3*i]));
189  e.Centroid(conn[i],nc,p);
190  // std::cout << "a" << i+1 << ": " << p << std::endl;
191  }
192  };
193 
194  void GetCoordinateBounds(NodalCoordinates &nc,std::vector<double> &bnds)
195  {
196  bnds.resize(6);
197  bnds[0] = bnds[2] = bnds[4] = std::numeric_limits<double>::max();
198  bnds[1] = bnds[3] = bnds[5] = std::numeric_limits<double>::min();
199  Mesh::IndexType number_of_nodes = nc.Size();
200  for(Mesh::IndexType nn = 1;nn <= number_of_nodes;nn++){
201  if(nc.x(nn) < bnds[0])
202  bnds[0] = nc.x(nn);
203  if(nc.x(nn) > bnds[1])
204  bnds[1] = nc.x(nn);
205  if(nc.y(nn) < bnds[2])
206  bnds[2] = nc.y(nn);
207  if(nc.y(nn) > bnds[3])
208  bnds[3] = nc.y(nn);
209  if(nc.z(nn) < bnds[4])
210  bnds[4] = nc.z(nn);
211  if(nc.z(nn) > bnds[5])
212  bnds[5] = nc.z(nn);
213  }
214  };
215 
216 
218  {
219  return(IRAD::Util::LessThan(*this,f));
220  };
221 
222  Mesh::Connectivity::Connectivity() : std::vector<std::vector<IndexType> >()
223  {
224  this ->_nelem = 0;
225  this->resize(0);
226  std::vector<std::vector<Mesh::IndexType> >(*this).swap(*this);
227  };
228 
229  Mesh::Connectivity::Connectivity(unsigned int N) : std::vector<std::vector<IndexType> >(N)
230  {
231  std::vector<std::vector<Mesh::IndexType> >(*this).swap(*this);
232  };
233  void Mesh::Connectivity::Resize(unsigned int N){this->resize(N);};
235  void Mesh::Connectivity::AddElement(const std::vector<IndexType> &elem)
236  {
237  _nelem++;
238  this->push_back(elem);
239  };
241  {
242  _nelem++;
243  std::vector<IndexType> a;
244  this->push_back(a);
245  };
246  void Mesh::Connectivity::Sync(){ _nelem = this->size();};
248  {
249  _nelem = this->size();
250  Connectivity::iterator ti = this->begin();
251  while(ti != this->end()){
252  std::vector<Mesh::IndexType>(*ti).swap(*ti);
253  ti++;
254  }
255  std::vector<std::vector<Mesh::IndexType> >(*this).swap(*this);
256  };
258  {
259  Connectivity::iterator ti = this->begin();
260  while(ti != this->end()){
261  if(ti->empty()){
262  ti = this->erase(ti);
263  _nelem--;
264  }
265  else
266  ti++;
267  }
268  };
270  DestroySizes();
271  Connectivity::iterator ti = this->begin();
272  while(ti != this->end()){
273  ti->resize(0);
274  std::vector<IndexType> tmp(*ti);
275  ti->swap(tmp);
276  ti++;
277  }
278  this->resize(0);
279  std::vector<std::vector<IndexType> >(*this).swap(*this);
280  };
282  _sizes.resize(_nelem);
283  for(IndexType i = 0;i < _nelem;i++){
284  _sizes[i] = (*this)[i].size();
285  // std::vector<IndexType> tmp((*this)[i]);
286  // ((*this)[i].swap(tmp));
287  }
288  };
289  void Mesh::Connectivity::DestroySizes(){ _sizes.resize(0);};
290 
291  // warning, if called with unsync'd Connectivity table, result
292  // is silently garbage.
294  {
295  if(nnodes <= 0)
296  nnodes = MaxNodeId<Connectivity,std::vector<IndexType> >(*this);
297  rc.Resize(nnodes);
298  rc.Sync();
299  for(IndexType i = 0;i < _nelem;i++){
300  if((*this)[i].size() > 1){
301  std::vector<IndexType>::const_iterator ii = (*this)[i].begin();
302  while(ii != (*this)[i].end()){
303  rc[*ii-1].push_back(i+1);
304  ii++;
305  }
306  }
307  }
308  };
309 
310  // warning, if called with unsync'd Connectivity table, result
311  // is silently garbage.
313  {
314  if(nnodes <= 0)
315  nnodes = MaxNodeId<Connectivity,std::vector<IndexType> >(*this);
316  // Connectivity::const_iterator ci = this->begin();
317  // while(ci != this->end()){
318  // std::vector<IndexType>::const_iterator ii = ci->begin();
319  // while(ii != ci->end()){
320  // nnodes = (nnodes > *ii ? nnodes : *ii);
321  // ii++;
322  // }
323  // ci++;
324  // }
325  // }
326  rc.Resize(nnodes);
327  rc.Sync();
328  for(IndexType i = 0;i < _nelem;i++){
329  std::vector<IndexType>::const_iterator ii = (*this)[i].begin();
330  while(ii != (*this)[i].end()){
331  rc[*ii-1].push_back(i+1);
332  ii++;
333  }
334  }
335  };
336 
338  std::vector<SymbolicFace> &sf,Connectivity &dc) const
339  {
340  // this->Sync();
341  // this->SyncSizes();
342  ef.Resize(this->Nelem());
343  Mesh::IndexType number_of_elements = this->Nelem();
344  Mesh::IndexType nface_estimate = static_cast<Mesh::IndexType>(2.2 * number_of_elements);
345  fcon.Resize(0);
346  fcon.reserve(nface_estimate);
347  sf.reserve(nface_estimate);
348  Mesh::IndexType number_of_faces = 0;
349  std::vector<Mesh::Connectivity> all_face_conn;
350  all_face_conn.resize(this->Nelem());
351  // std::vector<Mesh::IndexType> element_nfaces;
352  // element_nfaces.resize(this->Nelem());
353  // This loop sizes the C[F] array (i.e. for each cell, which faces)
354  // They're init'd to 0 so that we can tell which faces have been processed
355  for(Mesh::IndexType element_being_processed = 1;
356  element_being_processed <= number_of_elements;
357  element_being_processed++)
358  {
359  Mesh::IndexType index = element_being_processed - 1;
360  Mesh::IndexType size_of_element = this->Esize(element_being_processed);
361  Mesh::GenericElement ge(size_of_element);
362  // element_nfaces[index] = nfaces;
363  ef[index].resize(ge.nfaces(),0);
364  // std::vector<Mesh::IndexType>(ef[index]).swap(ef[index]);
365  ge.get_face_connectivities(all_face_conn[index],(*this)[index]);
366  }
367  ef.Sync();
368  ef.SyncSizes();
369  // This loop populates the F[N] (i.e. for each face, which nodes), and
370  // the C[F] arrays.
371  for(Mesh::IndexType element_being_processed = 1;
372  element_being_processed <= number_of_elements;
373  element_being_processed++)
374  {
375  Mesh::IndexType index = element_being_processed - 1;
376  Mesh::IndexType size_of_element = this->Esize(element_being_processed);
377  Mesh::GenericElement ge(size_of_element);
378  Mesh::IndexType nfaces = ef.Esize(element_being_processed);
379  // Mesh::Connectivity efc;
380  // This call populates the F[N] for the faces local
381  // to the element_being_processed.
382  // ge.get_face_connectivities(efc,(*this)[index]);
383  // This loop goes through each face of the element_being_processed
384  // and updates the F[N] and C[F] arrays.
385  for(Mesh::IndexType face_being_processed = 1;
386  face_being_processed <= nfaces;
387  face_being_processed++){
388  Mesh::IndexType findex = face_being_processed - 1;
389  if(!ef[index][findex]){ // 0 if face hasn't yet been processed
390  fcon.push_back(all_face_conn[index][findex]); // add the new face to the F[N] array
391  ef[index][findex] = number_of_faces + 1; // add the face id to the C[F] array
392  SubEntityId seid1;
393  SubEntityId seid2;
394  sf.push_back(std::make_pair(seid1,seid2));
395  sf[number_of_faces].first.first = element_being_processed;
396  sf[number_of_faces].first.second = face_being_processed;
397  // Now look at each cell containing each node of the current face and determine
398  // which one (if any) have the same face. This will be the face neighbor of the
399  // element_being_processed for the face identified by (number_of_faces + 1).
400  // std::list<Mesh::IndexType> element_nbrlist;
401  bool found = false;
402  std::vector<Mesh::IndexType>::iterator fni = fcon[number_of_faces].begin();
403  while(fni != fcon[number_of_faces].end() && !found){ // for every node in this face
404  Mesh::IndexType face_node_index = *fni++ - 1;
405  std::vector<Mesh::IndexType>::iterator enbri = dc[face_node_index].begin();
406  while(enbri != dc[face_node_index].end() && !found){ // look thru all the node's cells
407  Mesh::IndexType enbr_index = *enbri++ - 1;
408  if(enbr_index+1 > element_being_processed){
409  Mesh::IndexType nbr_nfaces = ef.Esize(enbr_index+1);
410  for(Mesh::IndexType nbrface = 1;nbrface <= nbr_nfaces && !found;nbrface++){
411  Mesh::IndexType nbr_face_index = nbrface -1;
412  if(!ef[enbr_index][nbr_face_index]){
413  if(IRAD::Util::HaveOppositeOrientation(all_face_conn[index][findex],
414  all_face_conn[enbr_index][nbr_face_index])){
415  found = true;
416  ef[enbr_index][nbr_face_index] = number_of_faces + 1;
417  sf[number_of_faces].second.first = enbr_index+1;
418  sf[number_of_faces].second.second = nbr_face_index+1;
419  } // if faces match
420  }
421  }
422  }
423  }
424  }
425  number_of_faces++;
426  }
427  }
428  }
429  fcon.Sync();
430  };
431 
432  // warning, if called with unsync'd Connectivity table, result
433  // is silently garbage.
435  {
436  Connectivity::iterator ci = this->begin();
437  IndexType n = 1;
438  while(ci != this->end()){
439  ci->erase(std::lower_bound(ci->begin(),ci->end(),offset+n++));
440  ci++;
441  }
442  };
443 
445  {
446  Connectivity::iterator ci = this->begin();
447  IndexType n = 1;
448  while(ci != this->end()){
449  ci->insert(std::lower_bound(ci->begin(),ci->end(),offset+n),1,offset+n);
450  n++;
451  ci++;
452  }
453  };
454 
455  // input is dual connectivity (i.e. for every node, which elements)
457  const Connectivity &dc,
458  IndexType size)
459  {
460  rl.resize(_nelem);
461  // rl._nelem = _nelem;
462  for(IndexType i = 0; i < _nelem;i++){
463  std::vector<IndexType>::const_iterator ni = (*this)[i].begin();
464  while(ni != (*this)[i].end()){
465  IndexType index = *ni - 1;
466  std::vector<IndexType>::const_iterator dci = dc[index].begin();
467  while(dci != dc[index].end())
468  rl[i].insert(*dci++);
469  ni++;
470  }
471  rl[i].erase(i+1);
472  }
473  };
474 
475  // input is dual connectivity (i.e. for every node, which elements)
477  Connectivity &dc,
478  bool exclude_self,
479  bool sortit)
480  {
481  rl.Resize(_nelem);
482  rl._nelem = _nelem;
483  std::vector<bool> added(_nelem,false);
484  for(IndexType i = 0; i < _nelem;i++){
485  IndexType current_element = i + 1;
486  std::vector<IndexType>::iterator ni = (*this)[i].begin();
487  std::list<IndexType> nbrlist;
488  while(ni != (*this)[i].end()){
489  IndexType index = *ni - 1;
490  std::vector<IndexType>::iterator dci = dc[index].begin();
491  while(dci != dc[index].end()){
492  IndexType ai = *dci - 1;
493  if(!added[ai]){
494  nbrlist.push_back(*dci);
495  added[ai] = true;
496  }
497  dci++;
498  }
499  ni++;
500  }
501  if(sortit)
502  nbrlist.sort();
503  // nbrlist.unique();
504  if(exclude_self){
505  nbrlist.remove(current_element);
506  added[i] = false;
507  }
508  rl[i].resize(nbrlist.size());
509  IndexType j = 0;
510  std::list<IndexType>::iterator si = nbrlist.begin();
511  while(si != nbrlist.end()){
512  rl[i][j++] = *si;
513  added[*si-1] = false;
514  si++;
515  }
516  }
517  };
518 
519  // input is dual connectivity (i.e. for every node, which elements)
521  Connectivity &dc,
522  IndexType n,
523  bool sortit)
524  {
525  rl.Resize(_nelem);
526  rl._nelem = _nelem;
527  IndexType nadj = n;
528  if(n == 0){
529  std::cout << "GETADJACENT: Determining MaxNodeId" << std::endl;
530  nadj = MaxNodeId<Connectivity,std::vector<IndexType> >(dc);
531  }
532  std::vector<bool> added(nadj,false);
533  for(IndexType i = 0; i < _nelem;i++){
534  // IndexType current_element = i + 1;
535  std::vector<IndexType>::iterator ni = (*this)[i].begin();
536  std::list<IndexType> nbrlist;
537  while(ni != (*this)[i].end()){
538  IndexType index = *ni - 1;
539  std::vector<IndexType>::iterator dci = dc[index].begin();
540  while(dci != dc[index].end()){
541  IndexType ai = *dci - 1;
542  if(!added[ai]){
543  nbrlist.push_back(*dci);
544  added[ai] = true;
545  }
546  dci++;
547  }
548  ni++;
549  }
550  if(sortit)
551  nbrlist.sort();
552  // nbrlist.unique();
553  rl[i].resize(nbrlist.size());
554  IndexType j = 0;
555  std::list<IndexType>::iterator si = nbrlist.begin();
556  while(si != nbrlist.end()){
557  rl[i][j++] = *si;
558  added[*si-1] = false;
559  si++;
560  }
561  }
562  };
563 
564 
565  // Doesn't have to be nodes - this is a graph type operation
566  // Takes a list of nodes in nodes and determines a list of
567  // unique elements they touch as indicated by the dual
568  // connectivity - can be removed from Connectivity class
569  void Connectivity::ElementsOn(std::vector<Mesh::IndexType> &nodes,
570  Connectivity &dc,
571  std::vector<Mesh::IndexType> &subset)
572  {
573  std::list<Mesh::IndexType> alist;
574  std::vector<Mesh::IndexType>::iterator ni = nodes.begin();
575  while(ni != nodes.end()){
576  Mesh::IndexType node_index = *ni++ - 1;
577  std::vector<Mesh::IndexType>::iterator dci = dc[node_index].begin();
578  while(dci != dc[node_index].end())
579  alist.push_back(*dci++);
580  }
581  alist.sort();
582  alist.unique();
583  subset.resize(alist.size());
584  std::vector<Mesh::IndexType>::iterator ssi = subset.begin();
585  std::list<Mesh::IndexType>::iterator li = alist.begin();
586  while(li != alist.end())
587  *ssi++ = *li++;
588  };
589 
590 
591  // Does breadth first renumbering and produces the remap:
592  // remap[old_id] = new_id
593  void Connectivity::BreadthFirstRenumber(std::vector<Mesh::IndexType> &remap)
594  {
595  remap.resize(_nelem,0);
596  IndexType renumber = 1;
597  for(IndexType i = 0;i < _nelem && renumber <= _nelem;i++){
598  // while(renumber <= _nelem){
599  if(remap[i] == 0){
600  remap[i] = renumber++;
601  std::list<IndexType> processing_queue;
602  std::vector<IndexType>::iterator ni = (*this)[i].begin();
603  while(ni != (*this)[i].end()){
604  IndexType index = *ni++ - 1;
605  if(remap[index] == 0){
606  processing_queue.push_back(index);
607  remap[index] = renumber++;
608  }
609  }
610  std::list<IndexType>::iterator pqi = processing_queue.begin();
611  while(pqi != processing_queue.end()){
612  IndexType index = *pqi;
613  std::vector<IndexType>::iterator ini = (*this)[index].begin();
614  while(ini != (*this)[index].end()){
615  IndexType iindex = *ini++ - 1;
616  if(remap[iindex] == 0){
617  processing_queue.push_back(iindex);
618  remap[iindex] = renumber++;
619  }
620  }
621  pqi++;
622  }
623  }
624  }
625  assert((renumber == (_nelem+1)));
626  };
627 
628 
630  GenericCell_2::Centroid(std::vector<IndexType> &ec,NodalCoordinates &nc) const
631  {
632  GeoPrim::C3Point centroid(0,0,0);
633  IndexType i = 0;
634  IndexType esize = ec.size();
635  while(i < esize)
636  centroid += GeoPrim::C3Point(nc[ec[i++]]);
637  double scal = 1.0/(static_cast<double>(esize));
638  return(centroid *= scal);
639  };
640 
641  // Populate SF with the shape function of the element at the nat.c.
642  void
643  GenericCell_2::shape_func(const GeoPrim::CVector &natc,double SF[]) const
644  {
645  switch (_size) {
646  case 3: {
647  SF[0] = 1. - natc[0] - natc[1];
648  SF[1] = natc[0];
649  SF[2] = natc[1];
650  return;
651  }
652  case 4: {
653  const double xi = natc[0];
654  const double xi_minus = 1. - xi;
655  const double eta = natc[1];
656  const double eta_minus = 1. - eta;
657 
658  SF[0] = xi_minus * eta_minus;
659  SF[1] = xi * eta_minus;
660  SF[2] = xi * eta;
661  SF[3] = xi_minus * eta;
662  return;
663  }
664  default:
665  std::cerr << "GenericCell_2::shape_func:Error: unkown element type."
666  << std::endl;
667  exit(1);
668  }
669  };
670 
671 
672  // This function evaluates the shape function of an element. It
673  // computes the barycentric coordinates from the natural coordinates.
674  void
675  GenericCell_2::dshape_func( const GeoPrim::CVector &natc, double Np[][2]) const {
676  switch ( _size) {
677  case 3: {
678  Np[0][0] = -1; Np[0][1] = -1;
679  Np[1][0] = 1; Np[1][1] = 0;
680  Np[2][0] = 0; Np[2][1] = 1;
681  return;
682  }
683  case 4: {
684  const double xi = natc[0];
685  const double xi_minus = 1. - xi;
686  const double eta = natc[1];
687  const double eta_minus = 1. - eta;
688 
689  Np[0][0] = -eta_minus; Np[0][1] = -xi_minus;
690  Np[1][0] = eta_minus; Np[1][1] = -xi;
691  Np[2][0] = eta; Np[2][1] = xi;
692  Np[3][0] = -eta; Np[3][1] = xi_minus;
693 
694  return;
695  }
696  default:
697  std::cerr << "GenericCell_2::dshape_func:error: Unknown element type."
698  << std::endl;
699  exit(1);
700  }
701  };
702  // This function evaluates the Jacobian at a given point.
703  // J and nc are both size 2 (nc = natural coordinates)
705  const GeoPrim::CVector &nc,
706  GeoPrim::CVector J[]) const {
707  switch (_size) {
708  case 3:
709  J[0] = p[1]-p[0]; J[1] = p[2]-p[0];
710  return;
711  case 4: {
712  const double xi = nc[0];
713  const double xi_minus = 1. - xi;
714  const double eta = nc[1];
715  const double eta_minus = 1. - eta;
716  J[0] = ((p[1]-p[0]) *= eta_minus) += (( p[2]-p[3]) *= eta );
717  J[1] = ((p[3]-p[0]) *= xi_minus) += (( p[2]-p[1]) *= xi);
718  return;
719  }
720  case 6: {
721  const double xi = nc[0];
722  const double eta = nc[1];
723  const double zeta = 1.-xi-eta;
724 
725  J[0] = ((p[1]-p[0]) *= 4.*xi -1.)
726  += ((p[3]-p[0]) *= 4.*zeta-4*xi)
727  += ((p[4]-p[5]) *= 4.*eta);
728  J[1] = ((p[2]-p[0]) *= 4.*eta -1.)
729  += ((p[5]-p[0]) *= 4*zeta-4*eta)
730  += ((p[4]-p[3]) *= 4.*xi);
731  return;
732  }
733  case 8: {
734  const double xi = nc[0];
735  const double xi_minus = 1. - xi;
736  const double eta = nc[1];
737  const double eta_minus = 1. - eta;
738 
739  J[0] = ((p[1]-p[0]) *= eta_minus) += ((p[2]-p[3]) *= eta)
740  -= ((((p[0]-p[4])+=(p[1]-p[4])) *= 2.*eta_minus*(xi_minus-xi))
741  += (((p[2]-p[6])+=(p[3]-p[6])) *= 2.*eta*(xi_minus-xi))
742  += (((p[1]-p[5])+=(p[2]-p[5])-=((p[0]-p[7])+=(p[3]-p[7])))
743  *= 2.*eta*eta_minus));
744 
745  ((J[1] = p[3]-p[0]) *= xi_minus) += ((p[2]-p[1]) *= xi)
746  -= ((((p[1]-p[5])+=(p[2]-p[5])) *= 2.*xi*(eta_minus-eta))
747  += (((p[0]-p[7])+=(p[3]-p[7])) *= 2.*xi_minus*(eta_minus-eta))
748  += (((p[2]-p[6])+=(p[1]-p[4])-=((p[3]-p[6])+=(p[0]-p[4])))
749  *= 2.*xi*xi_minus));
750  return;
751  }
752  default:
753  abort(); // Should never reach here
754  }
755  };
756 
758  IndexType elnum,
759  const Connectivity &ec,
760  const NodalCoordinates &nc)
761  {
762  GeoPrim::CPoint P[3];
763  for(IndexType i = 0;i < _size;i++){
764  IndexType i_minus = (i==0 ? _size -1 : i - 1);
765  P[i_minus] = nc[ec.Node(elnum,i_minus+1)];
766  P[i] = nc[ec.Node(elnum,i+1)];
767  IndexType i_plus = (i == (_size-1) ? 0 : i+1);
768  P[i_plus] = nc[ec.Node(elnum,i_plus+1)];
769  ns[i] = GeoPrim::CVector(P[i] - P[i_minus])%GeoPrim::CVector(P[i_plus] - P[i]);
770  }
771  };
772 
774  IndexType elnum,
775  const Connectivity &ec,
776  const NodalCoordinates &nc)
777  {
778  for(IndexType i = 0;i < _size;i++)
779  P[i].init(nc[ec.Node(elnum,i+1)]);
780  };
781 
782  // Evaluates the shape function and jacobian at a given point
783  void
785  GeoPrim::CVector &natc,
786  IndexType elnum,
787  const Connectivity &ec,
788  const NodalCoordinates &nc,
789  GeoPrim::CVector &fvec,
790  GeoPrim::CVector jac[]) const // fjac is 3x2
791  {
792  GeoPrim::CPoint P[(const IndexType)_size];
793  double SF[(const IndexType)_size];
794  this->shape_func(natc,SF);
795  fvec.init(-1.0*p);
796  for(IndexType i = 0;i < _size;i++){
797  P[i].init(nc[ec.Node(elnum,i+1)]);
798  fvec += SF[i]*P[i];
799  }
800  GeoPrim::CVector v1(P[0],P[1]);
801  GeoPrim::CVector v2(P[0],P[2]);
802  this->jacobian(P,natc,jac);
803  jac[2] = v1%v2;
804  jac[2].normalize();
805  Transpose(jac);
806  }
807 
808  // Interpolate a field value from the nodes of the element to the point
809  // having natural coordinates nc.
811  const GeoPrim::CVector &nc,
812  GeoPrim::CVector &v) const
813  {
814  const double xi = nc.x();
815  const double eta = nc.y();
816  v = f[0];
817  switch(_size) {
818  case 3: {
819  v += ((f[1]-f[0])*=xi) += ((f[2]-f[0])*=eta);
820  return;
821  }
822  case 4: {
823  v += ((f[1]-f[0]) *= (xi * (1.-eta)))
824  += ((f[3]-f[0]) *= eta)
825  += ((f[2]-f[3]) *= xi*eta);
826  return;
827  }
828  case 6: {
829  const double zeta=1.-xi-eta;
830 
831  v += ((f[1]-f[0]) *= xi * (2.*xi-1.))
832  += ((f[3]-f[0]) *= 4.* xi * zeta)
833  += ((f[2]-f[0]) *= eta * (2.*eta-1.))
834  += ((f[5]-f[0]) *= 4. * eta * zeta)
835  += ((f[4]-f[0]) *= 4.*xi*eta);
836  return;
837  }
838  case 8: {
839  const double xi_minus = 1. - xi;
840  const double eta_minus = 1. - eta;
841  v += ((f[1]-f[0]) *= eta * (2.*eta-1.))
842  += ((f[3]-f[0]) *= eta)
843  += ((f[2]-f[3]) *= xi * eta)
844  -= ((((f[0]-f[4])+=(f[1]-f[4])) *= 2.*xi*xi_minus*eta_minus)
845  += (((f[2]-f[6])+=(f[3]-f[6])) *= 2.*xi*xi_minus*eta)
846  += (((f[1]-f[5])+=(f[2]-f[5])) *= 2.*xi*eta*eta_minus)
847  += (((f[0]-f[7])+=(f[3]-f[7])) *= 2.*xi_minus*eta*eta_minus));
848  return;
849  }
850  default:
851  assert(false);
852  }
853  return;
854  }
855 
856  void GenericCell_2::ReOrient(std::vector<IndexType> &ec)
857  {
858  switch(_size) {
859  case 3: {
860  Mesh::IndexType temp = ec[0];
861  ec[0] = ec[1];
862  ec[1] = temp;
863  return;
864  }
865  case 4: {
866  Mesh::IndexType temp = ec[0];
867  ec[0] = ec[1];
868  ec[1] = temp;
869  temp = ec[2];
870  ec[2] = ec[3];
871  ec[3] = temp;
872  return;
873  }
874  default:
875  assert(false);
876  }
877  return;
878 
879  }
880 
881  // Evaluates the shape function and jacobian at a given point
882  void
884  GeoPrim::CVector &natc,
885  IndexType elnum,
886  const Connectivity &ec,
887  const NodalCoordinates &nc,
888  GeoPrim::CVector &fvec,
889  GeoPrim::CVector fjac[]) const
890  {
891  GeoPrim::CPoint P[(const IndexType)_size];
892  double SF[(const IndexType)_size];
893  this->shape_func(natc,SF);
894  fvec.init(-1.0*p);
895  for(IndexType i = 0;i < _size;i++){
896  // std::cout << "debugging: " << GeoPrim::CPoint(nc[ec.Node(elnum,i+1)]) << std::endl;
897  P[i].init(nc[ec.Node(elnum,i+1)]);
898  fvec += SF[i]*P[i];
899  }
900  this->jacobian(P,natc,fjac);
901  Transpose(fjac);
902  }
903 
904  // Populate SF with the shape function of the element at the nat.c.
905  void
906  GenericElement::shape_func(const GeoPrim::CVector &nc,double SF[]) const
907  {
908  switch (_size) {
909  // Tets are 4 nodes or 10
910  case 4: {
911  SF[0] = 1. - nc.x() - nc.y() - nc.z();
912  SF[1] = nc.x();
913  SF[2] = nc.y();
914  SF[3] = nc.z();
915  break;
916  }
917  case 10: {
918  const double xi = nc.x();
919  const double eta = nc.y();
920  const double zeta = nc.z();
921  const double alpha = (1. - xi - eta - zeta);
922  SF[0] = alpha*(1. - 2.*(xi + eta + zeta));
923  SF[1] = xi *(2.* xi - 1.);
924  SF[2] = eta *(2. * eta - 1.);
925  SF[3] = zeta *(2. * zeta - 1.);
926  SF[4] = 4.* xi * alpha;
927  SF[5] = 4.* eta * alpha;
928  SF[6] = 4.* zeta * alpha;
929  SF[7] = 4. * xi * eta;
930  SF[8] = 4. * eta * zeta;
931  SF[9] = 4. * xi * zeta;
932  break;
933  }
934  // Hex's are 8 nodes or 20
935  case 8: {
936  const double xi = nc.x();
937  const double xi_minus = 1. - xi;
938  const double eta = nc.y();
939  const double eta_minus = 1. - eta;
940  const double zeta = nc.z();
941  const double zeta_minus = 1. - zeta;
942  SF[0] = xi_minus * eta_minus * zeta_minus;
943  SF[1] = xi * eta_minus * zeta_minus;
944  SF[2] = xi * eta * zeta_minus;
945  SF[3] = xi_minus * eta * zeta_minus;
946  SF[4] = xi_minus * eta_minus * zeta;
947  SF[5] = xi * eta_minus * zeta;
948  SF[6] = xi * eta * zeta;
949  SF[7] = xi_minus * eta * zeta;
950  break;
951  }
952  default:
953  std::cerr << "GenericElement::shape_func:Error: unkown element type."
954  << std::endl;
955  exit(1);
956  }
957  }
958 
959  // Populate dSF with the derivative of the shape function for the element
960  // at nat.c.
961  void
962  GenericElement::dshape_func(const GeoPrim::CVector &nc,double dSF[][3]) const
963  {
964  switch (_size) {
965  case 4: {
966  dSF[0][0] = -1; dSF[0][1] = -1; dSF[0][2] = -1;
967  dSF[1][0] = 1; dSF[1][1] = 0; dSF[1][2] = 0;
968  dSF[2][0] = 0; dSF[2][1] = 1; dSF[2][2] = 0;
969  dSF[3][0] = 0; dSF[3][1] = 0; dSF[3][2] = 1;
970  break;
971  }
972  case 10:{
973  const double xi = nc.x();
974  const double eta = nc.y();
975  const double zeta = nc.z();
976  const double alpha = (1. - xi - eta - zeta);
977  dSF[0][0] = (4.*(xi+eta+zeta)-3.); dSF[0][1] = dSF[0][0]; dSF[0][2] = dSF[0][0];
978  dSF[1][0] = 4.*xi - 1.; dSF[1][1] = 0; dSF[1][2] = 0;
979  dSF[2][0] = 0; dSF[2][1] = 4.*eta - 1.; dSF[2][2] = 0;
980  dSF[3][0] = 0; dSF[3][1] = 0; dSF[3][2] = 4.*zeta - 1.;
981  dSF[4][0] = 4.*(alpha - xi); dSF[4][1] = -4.*xi; dSF[4][2] = -4.*xi;
982  dSF[5][0] = -4.*eta; dSF[5][1] = 4.*(alpha - eta); dSF[5][2] = -4.*eta;
983  dSF[6][0] = -4.*zeta; dSF[6][1] = -4.*zeta; dSF[6][2] = 4.*(alpha - zeta);
984  dSF[7][0] = 4.*eta; dSF[7][1] = 4.*xi; dSF[7][2] = 0;
985  dSF[8][0] = 0; dSF[8][1] = 4.*zeta; dSF[8][2] = 4.*eta;
986  dSF[9][0] = 4.*zeta; dSF[9][1] = 0; dSF[9][2] = 4.*xi;
987  break;
988  }
989  case 8: {
990  const double xi = nc.x();
991  const double xi_minus = 1. - xi;
992  const double eta = nc.y();
993  const double eta_minus = 1. - eta;
994  const double zeta = nc.z();
995  const double zeta_minus = 1. - zeta;
996  dSF[0][0] = -1.*eta_minus*zeta_minus; dSF[0][1] = -1.*xi_minus*zeta_minus; dSF[0][2] = -1.*xi_minus*eta_minus;
997  dSF[1][0] = eta_minus*zeta_minus; dSF[1][1] = -1.*xi*zeta_minus; dSF[1][2] = -1.*xi*eta_minus;
998  dSF[2][0] = eta*zeta_minus; dSF[2][1] = xi*zeta_minus; dSF[2][2] = -1.*xi*eta;
999  dSF[3][0] = -1.*eta*zeta_minus; dSF[3][1] = xi_minus*zeta_minus; dSF[3][2] = -1.*xi_minus*eta;
1000  dSF[4][0] = -1.*eta_minus*zeta; dSF[4][1] = -1.*xi_minus*zeta; dSF[4][2] = xi_minus*eta_minus;
1001  dSF[5][0] = eta_minus*zeta; dSF[5][1] = -1.*xi*zeta; dSF[5][2] = xi*eta_minus;
1002  dSF[6][0] = eta*zeta; dSF[6][1] = xi*zeta; dSF[6][2] = xi*eta;
1003  dSF[7][0] = -1.*eta*zeta; dSF[7][1] = xi_minus * zeta; dSF[7][2] = xi_minus*eta;
1004  break;
1005  }
1006  default:
1007  std::cerr << "GenericElement::dshape_func:error: Unknown element type."
1008  << std::endl;
1009  exit(1);
1010  }
1011  }
1012 
1013  // Populate J with the jacobian for the point having natural
1014  // coordinates nc. p are the nodal coordinates of the vertices
1015  void
1017  const GeoPrim::CVector &nc,
1018  GeoPrim::CVector J[]) const
1019  {
1020  switch(_size){
1021  case 4: {
1022  J[0] = p[1] - p[0];
1023  J[1] = p[2] - p[0];
1024  J[2] = p[3] - p[0];
1025  break;
1026  }
1027  case 10: {
1028  const double xi = nc.x();
1029  const double eta = nc.y();
1030  const double zeta = nc.z();
1031  const double alpha = (1. - xi - eta - zeta);
1032  GeoPrim::CPoint P(p[0]*(4.*(xi+eta+zeta)-3.));
1033  J[0] = ((p[9]-p[6])*=4.*zeta)+=((p[7]-p[5])*=4.*eta)+=
1034  (p[4]*(4.*(alpha-xi))+p[1]*(4.*xi-1.)+P);
1035  J[1] = ((p[8]-p[6])*=4.*zeta)+=((p[7]-p[4])*=4.*xi)+=
1036  (p[5]*(4.*(alpha-eta))+p[2]*(4.*eta-1.)+P);
1037  J[2] = ((p[9]-p[4])*=4.*xi)+=((p[8]-p[5])*=4.*eta)+=
1038  (p[6]*(4.*(alpha-zeta))+p[3]*(4.*zeta-1.)+P);
1039  break;
1040  }
1041  case 8: {
1042  const double xi = nc.x();
1043  const double xi_minus = 1. - xi;
1044  const double eta = nc.y();
1045  const double eta_minus = 1. - eta;
1046  const double zeta = nc.z();
1047  const double zeta_minus = 1. - zeta;
1048  J[0] = ((p[6]-p[7])*=eta*zeta)+=((p[5]-p[4])*=eta_minus*zeta)+=
1049  ((p[2]-p[3])*=eta*zeta_minus)+=((p[1]-p[0])*=eta_minus*zeta_minus);
1050  J[1] = ((p[7]-p[4])*=xi_minus*zeta)+=((p[6]-p[5])*=xi*zeta)+=
1051  ((p[3]-p[0])*=xi_minus*zeta_minus)+=((p[2]-p[1])*=xi*zeta_minus);
1052  J[2] = ((p[7]-p[3])*=xi_minus*eta)+=((p[6]-p[2])*=xi*eta)+=
1053  ((p[5]-p[1])*=xi*eta_minus)+=((p[4]-p[0])*=xi_minus*eta_minus);
1054  break;
1055  }
1056  default:
1057  std::cerr << "GenericElement::jacobian:Error: Cannot handle this"
1058  << " element size (yet)." << std::endl;
1059  exit(1);
1060  }
1061  }
1062 
1063  // Interpolate a field value from the nodes of the element to the point
1064  // having natural coordinates nc.
1065  void
1067  const GeoPrim::CVector &nc,
1068  GeoPrim::CVector &v) const
1069  {
1070  const double xi = nc.x();
1071  const double eta = nc.y();
1072  const double zeta = nc.z();
1073  switch(_size) {
1074  case 4: {
1075  v = f[0];
1076  v += (((f[1]-f[0])*=xi) += ((f[2]-f[0])*=eta) += ((f[3] - f[0])*=zeta));
1077  // v += (f[1]-f[0])*=xi+=(f[2]-f[0])*=eta+=(f[3]-f[0])*=zeta;
1078  break;
1079  }
1080  case 10: {
1081  const double alpha = (1.-xi-eta-zeta);
1082  v = (alpha*(1.-2.*(xi+eta+zeta))*f[0] +
1083  xi*(2.*xi-1.)*f[1] +
1084  eta*(2.*eta-1.)*f[2] +
1085  zeta*(2.*zeta-1.)*f[3] +
1086  4.*xi*alpha*f[4] +
1087  4.*eta*alpha*f[5] +
1088  4.*zeta*alpha*f[6] +
1089  4.*xi*eta*f[7] +
1090  4.*eta*zeta*f[8] +
1091  4.*zeta*xi*f[9]);
1092  break;
1093  }
1094  case 8: {
1095  const double xi = nc.x();
1096  const double xi_minus = 1. - xi;
1097  const double eta = nc.y();
1098  const double eta_minus = 1. - eta;
1099  const double zeta = nc.z();
1100  const double zeta_minus = 1. - zeta;
1101  v = (xi_minus*eta_minus*zeta_minus*f[0] +
1102  xi*eta_minus*zeta_minus*f[1] +
1103  xi*eta*zeta_minus*f[2] +
1104  xi_minus*eta*zeta_minus*f[3] +
1105  xi_minus*eta_minus*zeta*f[4] +
1106  xi*eta_minus*zeta*f[5] +
1107  xi*eta*zeta*f[6] +
1108  xi_minus*eta*zeta*f[7]);
1109  break;
1110  }
1111  default:
1112  std::cerr << "interpolate::error Cannot handle this element "
1113  << "type (yet)." << std::endl;
1114  exit(1);
1115  }
1116  }
1117 
1124  void
1125  GetMeshBoxes(const NodalCoordinates &nc,
1126  const Connectivity &ec,
1127  GeoPrim::CBox &mesh_box,
1128  GeoPrim::CBox &small_box,
1129  GeoPrim::CBox &large_box)
1130  {
1131  mesh_box.init(nc[1],nc.size());
1132  small_box = mesh_box;
1133  IndexType nelem = ec.Nelem();
1134  IndexType n = 1;
1135  while(n <= nelem){
1136  unsigned int esize = ec.Esize(n);
1137  std::vector<GeoPrim::CPoint> element_points(esize);
1138  // Make a vector of the element points
1139  for(IndexType node = 1;node <= esize;node++){
1140  GeoPrim::CPoint ep(nc[ec.Node(n,node)]);
1141  element_points[node-1] = ep;
1142  }
1143  // Make the bounding box for the element
1144  GeoPrim::CBox box(element_points);
1145  if(!box.empty()){
1146  if(box < small_box) small_box = box;
1147  if(box > large_box) large_box = box;
1148  }
1149  n++;
1150  }
1151  }
1152 
1153 
1166  void
1167  FindElementsInBox(const GeoPrim::CBox &box,
1168  const NodalCoordinates &nc,
1169  const Connectivity &dc, // dual connectivity
1170  std::list<IndexType> &elements)
1171  {
1172  int nnodes = nc.Size();
1173  for(int i = 1;i <= nnodes;i++){
1174  GeoPrim::CPoint p(nc[i]);
1175  if(box.contains(p)){
1176  std::vector<IndexType>::const_iterator dci = dc[i-1].begin();
1177  while(dci != dc[i-1].end()){
1178  elements.push_back(*dci++);
1179  }
1180  }
1181  }
1182  if(!elements.empty()){
1183  elements.sort();
1184  elements.unique();
1185  }
1186  }
1187 
1188 
1213  FindPointInCells(const GeoPrim::CPoint &p, // Target point
1214  const NodalCoordinates &nc, // Source
1215  const Connectivity &ec, // Source connectivity
1216  const std::vector<Mesh::IndexType> &elements, // candidate cells
1217  GeoPrim::CVector &natc) // Returns Targ nat
1218  {
1219 
1220  // GeoPrim::CBox bounds(box.around(p));
1221  // std::list<IndexType> elements;
1222  // FindElementsInBox(bounds, nc, dc, elements);
1223  std::vector<IndexType>::const_iterator ei = elements.begin();
1224  while(ei != elements.end()){
1225  GeoPrim::CVector guess;
1226  unsigned int esize = ec.Esize(*ei);
1227  if(esize == 4 || esize == 10)
1228  guess.init(.25,.25,.25);
1229  else if (esize == 8 || esize == 20)
1230  guess.init(.5,.5,.5);
1231  else
1232  assert(false);
1233  natc.init(guess);
1234  // Solve the non-linear system using newton-raphson with an
1235  // initial guess as the center of the theoretical element.
1236  if(!NewtonRaphson(natc,*ei,GenericElement(esize),ec,nc,p)){
1237  // double dist = 0.0;
1238  // Mesh::IndexType closest_node = nc.closest_node(p,&dist);
1239  // std::cout << "Mesh::FindPointInMesh: Error: Closest approach: " << dist
1240  // << " at node " << closest_node << "." << std::endl
1241  // << "Mesh::FindPointInMesh: Element(" << *ei << ") = (";
1242  // IRAD::Util::DumpContents(std::cout,ec[*ei-1],",");
1243  // std::cout << ")" << std::endl;
1244  // std::cout << "Point: " << p << std::endl
1245  // << "Nodes: " << std::endl;
1246  // std::vector<Mesh::IndexType>::const_iterator ni = ec[*ei-1].begin();
1247  // while(ni != ec[*ei-1].end()){
1248  // std::cout << ni - ec[*ei-1].begin() << ": " << GeoPrim::C3Point(nc[*ni]) << std::endl;
1249  // ni++;
1250  // }
1251  // assert(false);
1252  return(0);
1253  }
1254  if(natc[0] >= LTOL && natc[0] <= HTOL &&
1255  natc[1] >= LTOL && natc[1] <= HTOL &&
1256  natc[2] >= LTOL && natc[2] <= HTOL){
1257  if(esize == 4 || esize == 10){
1258  if((natc[0]+natc[1]+natc[2]) <= HTOL)
1259  return (*ei);
1260  }
1261  else if(esize == 8 || esize == 20)
1262  return(*ei);
1263  else{
1264  std::cerr << "Mesh::FindPointInMesh: Error: Cannot handle"
1265  << " this element type. (yet)" << std::endl;
1266  exit(1);
1267  }
1268  }
1269  ei++;
1270  }
1271  return (0);
1272  }
1273 
1298  FindPointInMesh(const GeoPrim::CPoint &p, // Target Mesh point
1299  const NodalCoordinates &nc, // Source
1300  const Connectivity &ec, // Source connectivity
1301  const Connectivity &dc, // Source dual connectivity
1302  const GeoPrim::CBox &box, // neigborhood (typically defined by some source character)
1303  GeoPrim::CVector &natc) // Returns Targ nat
1304  {
1305 
1306  GeoPrim::CBox bounds(box.around(p));
1307  std::list<IndexType> elements;
1308  FindElementsInBox(bounds, nc, dc, elements);
1309  std::list<IndexType>::iterator ei = elements.begin();
1310  while(ei != elements.end()){
1311  GeoPrim::CVector guess;
1312  unsigned int esize = ec.Esize(*ei);
1313  if(esize == 4 || esize == 10)
1314  guess.init(.25,.25,.25);
1315  else if (esize == 8 || esize == 20)
1316  guess.init(.5,.5,.5);
1317  natc.init(guess);
1318  // Solve the non-linear system using newton-raphson with an
1319  // initial guess as the center of the theoretical element.
1320  if(!NewtonRaphson(natc,*ei,GenericElement(esize),ec,nc,p)){
1321  double dist = 0.0;
1322  Mesh::IndexType closest_node = nc.closest_node(p,&dist);
1323  std::cout << "Mesh::FindPointInMesh: Error: Closest approach: " << dist
1324  << " at node " << closest_node << "." << std::endl
1325  << "Mesh::FindPointInMesh: Element(" << *ei << ") = (";
1326  IRAD::Util::DumpContents(std::cout,ec[*ei-1],",");
1327  std::cout << ")" << std::endl;
1328  std::vector<Mesh::IndexType>::const_iterator ei2 = dc[closest_node-1].begin();
1329  GeoPrim::CBox new_bounds;
1330  while(ei2 != dc[closest_node-1].end()){
1331  // For every element touching this node
1332  std::vector<Mesh::IndexType>::const_iterator ni = ec[*ei2-1].begin();
1333  while(ni != ec[*ei2-1].end())
1334  new_bounds.AddPoint(nc[*ni++]);
1335  ei2++;
1336  }
1337  std::cout << "Mesh::FindPointInMesh: Bounding box of failed search: "
1338  << new_bounds << std::endl;
1339  return(0);
1340  }
1341  if(natc[0] >= LTOL && natc[0] <= HTOL &&
1342  natc[1] >= LTOL && natc[1] <= HTOL &&
1343  natc[2] >= LTOL && natc[2] <= HTOL){
1344  if(esize == 4 || esize == 10){
1345  if((natc[0]+natc[1]+natc[2]) <= HTOL)
1346  return (*ei);
1347  }
1348  else if(esize == 8 || esize == 20)
1349  return(*ei);
1350  else{
1351  std::cerr << "Mesh::FindPointInMesh: Error: Cannot handle"
1352  << " this element type. (yet)" << std::endl;
1353  exit(1);
1354  }
1355  }
1356  ei++;
1357  }
1358  return (0);
1359  }
1360 
1361 
1386  FindPointInMesh_2(const GeoPrim::CPoint &p, // Target Mesh point
1387  const NodalCoordinates &nc, // Source
1388  const Connectivity &ec, // Source connectivity
1389  const Connectivity &dc, // Source dual connectivity
1390  const GeoPrim::CBox &box, // Source
1391  GeoPrim::CVector &natc) // Returns Targ nat
1392  {
1393 
1394  GeoPrim::CBox bounds(box.around(p));
1395  std::list<IndexType> elements;
1396  FindElementsInBox(bounds, nc, dc, elements);
1397  std::list<IndexType>::iterator ei = elements.begin();
1398  while(ei != elements.end()){
1399  GeoPrim::CVector guess;
1400  unsigned int esize = ec.Esize(*ei);
1401  if(esize == 3 || esize == 6)
1402  guess.init(.25,.25,0);
1403  else if (esize == 4 || esize == 8)
1404  guess.init(.5,.5,0);
1405  natc.init(guess);
1406  // Solve the non-linear system using newton-raphson with an
1407  // initial guess as the center of the theoretical element.
1408  if(!NewtonRaphson_2(natc,*ei,GenericCell_2(esize),ec,nc,p)){
1409  double dist = 0.0;
1410  Mesh::IndexType closest_node = nc.closest_node(p,&dist);
1411  std::cout << "Mesh::FindPointInMesh: Error: Closest approach: " << dist
1412  << " at node " << closest_node << "." << std::endl
1413  << "Mesh::FindPointInMesh: Element(" << *ei << ") = (";
1414  IRAD::Util::DumpContents(std::cout,ec[*ei-1],",");
1415  std::cout << ")" << std::endl;
1416  std::vector<Mesh::IndexType>::const_iterator ei2 = dc[closest_node-1].begin();
1417  GeoPrim::CBox new_bounds;
1418  while(ei2 != dc[closest_node-1].end()){
1419  // For every element touching this node
1420  std::vector<Mesh::IndexType>::const_iterator ni = ec[*ei2-1].begin();
1421  while(ni != ec[*ei2-1].end())
1422  new_bounds.AddPoint(nc[*ni++]);
1423  ei2++;
1424  }
1425  std::cout << "Mesh::FindPointInMesh: Bounding box of failed search: "
1426  << new_bounds << std::endl;
1427  return(0);
1428  }
1429  if(natc[0] >= LTOL && natc[0] <= HTOL &&
1430  natc[1] >= LTOL && natc[1] <= HTOL)
1431  {
1432  if(esize == 3 || esize == 6){
1433  if(((natc[0]+natc[1]) <= HTOL))
1434  return (*ei);
1435  }
1436  else if(esize == 4 || esize == 8)
1437  return(*ei);
1438  else{
1439  std::cerr << "Mesh::FindPointInMesh: Error: Cannot handle"
1440  << " this element type. (yet)" << std::endl;
1441  exit(1);
1442  }
1443  }
1444  ei++;
1445  }
1446  return (0);
1447  }
1448 
1449 
1451  GenericElement::Centroid(std::vector<IndexType> &ec,NodalCoordinates &nc) const
1452  {
1453  GeoPrim::C3Point centroid(0,0,0);
1454  IndexType i = 0;
1455  IndexType esize = ec.size();
1456  while(i < esize)
1457  centroid += GeoPrim::C3Point(nc[ec[i++]]);
1458  double scal = 1.0/(static_cast<double>(esize));
1459  return(centroid *= scal);
1460  };
1461 
1462  void
1463  GenericElement::Centroid(std::vector<IndexType> &ec,NodalCoordinates &nc,GeoPrim::C3Point &centroid) const
1464  {
1465  centroid.Init();
1466  IndexType i = 0;
1467  IndexType esize = ec.size();
1468  while(i < esize)
1469  centroid += GeoPrim::C3Point(nc[ec[i++]]);
1470  double scal = 1.0/(static_cast<double>(esize));
1471  centroid *= scal;
1472  };
1473 
1474  bool
1475  GenericElement::Inverted(std::vector<IndexType> &ec,NodalCoordinates &nc) const
1476  {
1477  // Form the vector V1 from element centroid to first face centroid
1478  // Dot V1 with the first face normal
1479  // return(result < 0)
1480  if(_size == 4 || _size == 10){ // Tet Faces: 132 241 342 143
1481  GeoPrim::C3Point p1(nc[ec[0]]);
1482  GeoPrim::C3Point p2(nc[ec[2]]);
1483  GeoPrim::C3Point p3(nc[ec[1]]);
1484  GeoPrim::C3Facet aface(&p1,&p2,&p3);
1485  GeoPrim::C3Vector avec(Centroid(ec,nc),aface.Centroid());
1486  return((avec*aface.Normal()) < 0);
1487  }
1488  else if(_size == 5 || _size == 13){ // Pyr Faces: 1432 251 352 453 154
1489  GeoPrim::C3Point p1(nc[ec[0]]);
1490  GeoPrim::C3Point p2(nc[ec[3]]);
1491  GeoPrim::C3Point p3(nc[ec[2]]);
1492  GeoPrim::C3Point p4(nc[ec[1]]);
1493  GeoPrim::C3Facet bface(&p1,&p2,&p3,&p4);
1494  GeoPrim::C3Vector bvec(Centroid(ec,nc),bface.Centroid());
1495  return((bvec*bface.Normal()) < 0);
1496  }
1497  else if(_size == 6 || _size == 15){ // Prism Faces: 2541 3652 1463 132 456
1498  GeoPrim::C3Point p1(nc[ec[1]]);
1499  GeoPrim::C3Point p2(nc[ec[4]]);
1500  GeoPrim::C3Point p3(nc[ec[3]]);
1501  GeoPrim::C3Point p4(nc[ec[0]]);
1502  GeoPrim::C3Facet cface(&p1,&p2,&p3,&p4);
1503  GeoPrim::C3Vector cvec(Centroid(ec,nc),cface.Centroid());
1504  return((cvec*cface.Normal()) < 0);
1505  }
1506  else if(_size == 8 || _size == 20){ // Hex Faces: 1432 2651 3762 4873 1584 5678
1507  GeoPrim::C3Point p1(nc[ec[0]]);
1508  GeoPrim::C3Point p2(nc[ec[3]]);
1509  GeoPrim::C3Point p3(nc[ec[2]]);
1510  GeoPrim::C3Point p4(nc[ec[1]]);
1511  GeoPrim::C3Facet dface(&p1,&p2,&p3,&p4);
1512  GeoPrim::C3Vector dvec(Centroid(ec,nc),dface.Centroid());
1513  return((dvec*dface.Normal()) < 0);
1514  }
1515  else
1516  return(false);
1517  return(false);
1518  };
1519 
1520  bool
1521  GenericElement::ShapeOK(std::vector<IndexType> &ec,NodalCoordinates &nc) const
1522  {
1523  // ensure element is not poorly shaped
1524  // make sure point 3 is not co-linear with points 1 and 2
1525  // make sure 4th point not co-planar with base
1526  if(_size == 4){ // Tet Faces: 132 241 342 143
1527  GeoPrim::C3Point p1(nc[ec[0]]);
1528  GeoPrim::C3Point p2(nc[ec[2]]);
1529  GeoPrim::C3Point p3(nc[ec[1]]);
1530  GeoPrim::C3Point p4(nc[ec[3]]);
1531  GeoPrim::C3Plane plane(p1,p2,p3);
1532  return(!plane.contains_point(p4));
1533  }
1534  // ensure element in not poorly shaped
1535  // make sure quad base is planar
1536  // make sure area of quad base is positive
1537  // make sure 5th point not co-planar with quad base
1538  else if(_size == 5){ // Pyr Faces: 1432 251 352 453 154
1539  GeoPrim::C3Point p1(nc[ec[0]]);
1540  GeoPrim::C3Point p2(nc[ec[3]]);
1541  GeoPrim::C3Point p3(nc[ec[2]]);
1542  GeoPrim::C3Point p4(nc[ec[1]]);
1543  GeoPrim::C3Point p5(nc[ec[4]]);
1544  GeoPrim::C3Facet bface(&p1,&p2,&p3,&p4);
1545  GeoPrim::C3Vector bvec(Centroid(ec,nc),bface.Centroid());
1546  return((bvec*bface.Normal()) < 0);
1547  }
1548  // ensure element is not poorly shaped
1549  // make sure both triangular faces are triangles (i.e. not co-linear)
1550  // make sure no points of opposing face is co-planar with base
1551  // make sure quad faces are planar
1552  // make sure quad faces have positive area
1553  else if(_size == 6){ // Prism Faces: 2541 3652 1463 132 456
1554  GeoPrim::C3Point p1(nc[ec[1]]);
1555  GeoPrim::C3Point p2(nc[ec[4]]);
1556  GeoPrim::C3Point p3(nc[ec[3]]);
1557  GeoPrim::C3Point p4(nc[ec[0]]);
1558  GeoPrim::C3Facet cface(&p1,&p2,&p3,&p4);
1559  GeoPrim::C3Vector cvec(Centroid(ec,nc),cface.Centroid());
1560  return((cvec*cface.Normal()) < 0);
1561  }
1562  // ensure element is not poorly shaped
1563  // make sure each face is planar
1564  // make sure each face has positive area
1565  else if(_size == 8){ // Hex Faces: 1432 2651 3762 4873 1584 5678
1566  GeoPrim::C3Point p1(nc[ec[0]]);
1567  GeoPrim::C3Point p2(nc[ec[1]]);
1568  GeoPrim::C3Point p3(nc[ec[2]]);
1569  GeoPrim::C3Point p4(nc[ec[3]]);
1570 
1571  GeoPrim::C3Point p5(nc[ec[4]]);
1572  GeoPrim::C3Point p6(nc[ec[5]]);
1573  GeoPrim::C3Point p7(nc[ec[6]]);
1574  GeoPrim::C3Point p8(nc[ec[7]]);
1575 
1576  GeoPrim::C3Plane plane1(p1,p4,p3);
1577  if(!plane1.contains_point(p2))
1578  return(false);
1579  GeoPrim::C3Plane plane2(p2,p6,p5);
1580  if(!plane2.contains_point(p1))
1581  return(false);
1582  GeoPrim::C3Plane plane3(p3,p7,p6);
1583  if(!plane3.contains_point(p2))
1584  return(false);
1585  GeoPrim::C3Plane plane4(p4,p8,p7);
1586  if(!plane4.contains_point(p3))
1587  return(false);
1588  GeoPrim::C3Plane plane5(p1,p5,p8);
1589  if(!plane5.contains_point(p4))
1590  return(false);
1591  GeoPrim::C3Plane plane6(p5,p6,p7);
1592  if(!plane6.contains_point(p8))
1593  return(false);
1594  }
1595  else
1596  return(true);
1597  return(true);
1598  };
1599 
1600  void
1601  GenericElement::ReOrient(std::vector<IndexType> &ec)
1602  {
1603  IndexType temp;
1604  switch(_size){
1605  case 4: // Tet Faces: 132 241 342 143
1606  case 10:
1607  temp = ec[1];
1608  ec[1] = ec[0];
1609  ec[0] = temp;
1610  break;
1611  case 5: // Pyr Faces: 1432 251 352 453 154
1612  case 13:
1613  temp = ec[2];
1614  ec[2] = ec[0];
1615  ec[0] = ec[2];
1616  break;
1617  case 6: // Prism Faces: 2541 3652 1463 132 456
1618  case 15:
1619  temp = ec[1];
1620  ec[1] = ec[0];
1621  ec[0] = ec[1];
1622  temp = ec[4];
1623  ec[4] = ec[3];
1624  ec[3] = temp;
1625  break;
1626  case 8:
1627  case 20:
1628  temp = ec[2];
1629  ec[2] = ec[0];
1630  ec[0] = ec[2];
1631  temp = ec[6];
1632  ec[6] = ec[4];
1633  ec[4] = temp;
1634  break;
1635  }
1636  };
1637 
1638 
1639 
1640  // Searches _all_ elements one by one for a given point (last resort)
1642  GlobalFindPointInMesh(const GeoPrim::CPoint &p, // Target Mesh point
1643  const NodalCoordinates &nc, // Source
1644  const Connectivity &ec, // Source
1645  const Connectivity &dc, // Source
1646  const GeoPrim::CBox &box, // Source
1647  GeoPrim::CVector &natc) // Returns Targ nat
1648  {
1649  GeoPrim::CVector guess;
1650  int ein = 1;
1651  int ein_size = ec.Nelem();
1652  while(ein <= ein_size){
1653  unsigned int esize = ec.Esize(ein);
1654  if(esize == 4 || esize == 10)
1655  guess.init(.25,.25,.25);
1656  else if (esize == 8 || esize == 20)
1657  guess.init(.5,.5,.5);
1658  natc.init(guess);
1659  // Solve the non-linear system using newton-raphson with an
1660  // initial guess as the center of the theoretical element.
1661  if(!NewtonRaphson(natc,ein,GenericElement(esize),ec,nc,p)){
1662  std::cerr << "GlobalFindPointInMesh: error NewtonRaphson failed."
1663  << std::endl;
1664  return(0);
1665  }
1666  if(natc[0] >= LTOL && natc[0] <= HTOL &&
1667  natc[1] >= LTOL && natc[1] <= HTOL &&
1668  natc[2] >= LTOL && natc[2] <= HTOL){
1669  if(esize == 4 || esize == 10){
1670  if((natc[0]+natc[1]+natc[2]) <= HTOL){
1671  return (ein);
1672  }
1673  }
1674  else if(esize == 8 || esize == 20)
1675  return(ein);
1676  else{
1677  std::cerr << "GlobalFindPointInMesh: Error: Cannot handle"
1678  << " this element type. (yet)" << std::endl;
1679  exit(1);
1680  }
1681  }
1682  ein++;
1683  }
1684  return(0);
1685  }
1686 
1687 
1688  // Does not work for parallel meshes - does not work with BC's. Need
1689  // to support T3D mesh formats as well:
1690  // T3D:
1691  // tri,quad,mixed topological entity counts
1692  // [3,4,7] [0,1,2,2,3,3,3]
1693  //
1694  int ReadMesh(const std::string &path,Mesh::UnstructuredMesh &mesh)
1695  {
1696  std::ifstream Inf;
1697  Inf.open(path.c_str());
1698  if(!Inf)
1699  return(1);
1700  Inf >> mesh.nc >> mesh.con;
1701  if(!Inf)
1702  return(1);
1703  Inf.close();
1704  return(0);
1705  }
1706 
1711  // Input: Single Element Connectivity
1712  // Output: vector of face connectivities for this element
1713  void
1715  const std::vector<IndexType> &e) const
1716  {
1717  // std::vector<std::vector<IndexType> > rv;
1718  switch(_size){
1719  case 4: // Tet Faces: 132 241 342 143
1720  case 10:
1721  rv.Resize(4);
1722 
1723  rv[0].resize(3);
1724  // std::vector<Mesh::IndexType>(rv[0]).swap(rv[0]);
1725  rv[0][0] = e[0]; // 1
1726  rv[0][1] = e[2]; // 3
1727  rv[0][2] = e[1]; // 2
1728 
1729  rv[1].resize(3);
1730  // std::vector<Mesh::IndexType>(rv[1]).swap(rv[1]);
1731  rv[1][0] = e[1]; // 2
1732  rv[1][1] = e[3]; // 4
1733  rv[1][2] = e[0]; // 1
1734 
1735  rv[2].resize(3);
1736  // std::vector<Mesh::IndexType>(rv[2]).swap(rv[2]);
1737  rv[2][0] = e[2]; // 3
1738  rv[2][1] = e[3]; // 4
1739  rv[2][2] = e[1]; // 2
1740 
1741  rv[3].resize(3);
1742  // std::vector<Mesh::IndexType>(rv[3]).swap(rv[3]);
1743  rv[3][0] = e[0]; // 1
1744  rv[3][1] = e[3]; // 4
1745  rv[3][2] = e[2]; // 3
1746  break;
1747  case 5: // Pyr Faces: 1432 251 352 453 154
1748  case 13:
1749  rv.Resize(5);
1750 
1751  rv[0].resize(4);
1752  // std::vector<Mesh::IndexType>(rv[0]).swap(rv[0]);
1753  rv[0][0] = e[0]; // 1
1754  rv[0][1] = e[3]; // 4
1755  rv[0][2] = e[2]; // 3
1756  rv[0][3] = e[1]; // 2
1757 
1758  rv[1].resize(3);
1759  // std::vector<Mesh::IndexType>(rv[1]).swap(rv[1]);
1760  rv[1][0] = e[1]; // 2
1761  rv[1][1] = e[4]; // 5
1762  rv[1][2] = e[0]; // 1
1763 
1764  rv[2].resize(3);
1765  // std::vector<Mesh::IndexType>(rv[2]).swap(rv[2]);
1766  rv[2][0] = e[2]; // 3
1767  rv[2][1] = e[4]; // 5
1768  rv[2][2] = e[1]; // 2
1769 
1770  rv[3].resize(3);
1771  // std::vector<Mesh::IndexType>(rv[3]).swap(rv[3]);
1772  rv[3][0] = e[3]; // 4
1773  rv[3][1] = e[4]; // 5
1774  rv[3][2] = e[2]; // 3
1775 
1776  rv[4].resize(3);
1777  // std::vector<Mesh::IndexType>(rv[4]).swap(rv[4]);
1778  rv[4][0] = e[0]; // 1
1779  rv[4][1] = e[4]; // 5
1780  rv[4][2] = e[3]; // 4
1781  break;
1782  case 6: // Prism Faces: 2541 3652 1463 132 456
1783  case 15:
1784  rv.Resize(5);
1785 
1786  rv[0].resize(4);
1787  // std::vector<Mesh::IndexType>(rv[0]).swap(rv[0]);
1788  rv[0][0] = e[1]; // 2
1789  rv[0][1] = e[4]; // 5
1790  rv[0][2] = e[3]; // 4
1791  rv[0][3] = e[0]; // 1
1792 
1793  rv[1].resize(4);
1794  // std::vector<Mesh::IndexType>(rv[1]).swap(rv[1]);
1795  rv[1][0] = e[2]; // 3
1796  rv[1][1] = e[5]; // 6
1797  rv[1][2] = e[4]; // 5
1798  rv[1][3] = e[1]; // 2
1799 
1800  rv[2].resize(4);
1801  // std::vector<Mesh::IndexType>(rv[2]).swap(rv[2]);
1802  rv[2][0] = e[0]; // 1
1803  rv[2][1] = e[3]; // 4
1804  rv[2][2] = e[5]; // 6
1805  rv[2][3] = e[2]; // 3
1806 
1807  rv[3].resize(3);
1808  // std::vector<Mesh::IndexType>(rv[3]).swap(rv[3]);
1809  rv[3][0] = e[0]; // 1
1810  rv[3][1] = e[2]; // 3
1811  rv[3][2] = e[1]; // 2
1812 
1813  rv[4].resize(3);
1814  // std::vector<Mesh::IndexType>(rv[4]).swap(rv[4]);
1815  rv[4][0] = e[4]; // 5
1816  rv[4][1] = e[5]; // 6
1817  rv[4][2] = e[3]; // 4
1818  break;
1819  case 8:
1820  case 20:
1821  rv.Resize(6);
1822 
1823  rv[0].resize(4);
1824  // std::vector<Mesh::IndexType>(rv[0]).swap(rv[0]);
1825  rv[0][0] = e[0]; // 1
1826  rv[0][1] = e[3]; // 4
1827  rv[0][2] = e[2]; // 3
1828  rv[0][3] = e[1]; // 2
1829 
1830  rv[1].resize(4);
1831  // std::vector<Mesh::IndexType>(rv[1]).swap(rv[1]);
1832  rv[1][0] = e[1]; // 2
1833  rv[1][1] = e[5]; // 6
1834  rv[1][2] = e[4]; // 5
1835  rv[1][3] = e[0]; // 1
1836 
1837  rv[2].resize(4);
1838  // std::vector<Mesh::IndexType>(rv[2]).swap(rv[2]);
1839  rv[2][0] = e[2]; // 3
1840  rv[2][1] = e[6]; // 7
1841  rv[2][2] = e[5]; // 6
1842  rv[2][3] = e[1]; // 2
1843 
1844  rv[3].resize(4);
1845  // std::vector<Mesh::IndexType>(rv[3]).swap(rv[3]);
1846  rv[3][0] = e[3]; // 4
1847  rv[3][1] = e[7]; // 8
1848  rv[3][2] = e[6]; // 7
1849  rv[3][3] = e[2]; // 3
1850 
1851  rv[4].resize(4);
1852  // std::vector<Mesh::IndexType>(rv[4]).swap(rv[4]);
1853  rv[4][0] = e[0]; // 1
1854  rv[4][1] = e[4]; // 5
1855  rv[4][2] = e[7]; // 8
1856  rv[4][3] = e[3]; // 4
1857 
1858  rv[5].resize(4);
1859  // std::vector<Mesh::IndexType>(rv[5]).swap(rv[5]);
1860  rv[5][0] = e[4]; // 5
1861  rv[5][1] = e[5]; // 6
1862  rv[5][2] = e[6]; // 7
1863  rv[5][3] = e[7]; // 8
1864  break;
1865  default:
1866  rv.Resize(0);
1867  }
1868  // return(rv);
1869  };
1870 
1882  bool
1884  IndexType elnum,
1885  const GenericElement &el,
1886  const Connectivity &ec,
1887  const NodalCoordinates &nc,
1888  const GeoPrim::CPoint &point)
1889  {
1890  int k,i;
1891  int ntrial = 100; // Number of iterations before giving up
1892  double errx,errf;
1893  int indx[3];
1894  double errtol = 1e-12;
1895  GeoPrim::CVector p;
1896  GeoPrim::CVector fvec;
1897  GeoPrim::CVector fjac[3];
1898  for (k=0;k<ntrial;k++) {
1899  // std::cout << k << std::endl;
1900  el.shapef_jacobian_at(point,natc,elnum,ec,nc,fvec,fjac);
1901  errf=0.0;
1902  for (i=0;i<3;i++){
1903  // if(fvec[i] < errtol)
1904  // fvec[i] = 0.0;
1905  errf += fabs(fvec[i]);
1906  }
1907  if (errf <= errtol)
1908  return (true);
1909  p = -1.0 * fvec;
1910  // std::cout << "Jac: " << fjac[0] << std::endl
1911  // << "Jac: " << fjac[1] << std::endl
1912  // << "Jac: " << fjac[2] << std::endl
1913  // << "fv : " << fvec << std::endl
1914  // << "nc : " << natc << std::endl
1915  // << "err: " << errf << std::endl;
1916  if(!LUDcmp(fjac,indx)){
1917  // std::cerr << "NewtonRaphson::error: LUDcmp failed." << std::endl;
1918  // std::cout << "Jac: " << fjac[0] << std::endl
1919  // << "Jac: " << fjac[1] << std::endl
1920  // << "Jac: " << fjac[2] << std::endl;
1921  return(false);
1922  }
1923  LUBksb(fjac,indx,p);
1924  errx=0.0;
1925  for (i=0;i<3;i++)
1926  errx += fabs(p[i]);
1927  natc += p;
1928  if (errx <= errtol)
1929  return (true);
1930  }
1931  // std::cerr << "NewtonRaphson::warning: reached maximum iterations" << std::endl;
1932  return (false);
1933  }
1945  bool
1947  IndexType elnum,
1948  const GenericCell_2 &el,
1949  const Connectivity &ec,
1950  const NodalCoordinates &nc,
1951  const GeoPrim::CPoint &point)
1952  {
1953  int k,i;
1954  int ntrial = 10; // Number of iterations before giving up
1955  double errx,errf;
1956  int indx[3];
1957  GeoPrim::CVector p;
1958  GeoPrim::CVector fvec;
1959  GeoPrim::CVector fjac[3];
1960  for (k=0;k<ntrial;k++) {
1961  el.shapef_jacobian_at(point,natc,elnum,ec,nc,fvec,fjac);
1962  errf=0.0;
1963  for (i=0;i<3;i++)
1964  errf += fabs(fvec[i]);
1965  if (errf <= TOL)
1966  return (true);
1967  p = -1.0 * fvec;
1968  if(!LUDcmp(fjac,indx)){
1969  // std::cerr << "NewtonRaphson::error: LUDcmp failed." << std::endl;
1970  return(false);
1971  }
1972  LUBksb(fjac,indx,p);
1973  errx=0.0;
1974  for (i=0;i<3;i++)
1975  errx += fabs(p[i]);
1976  natc += p;
1977  if (errx <= TOL)
1978  return (true);
1979  }
1980  // std::cerr << "NewtonRaphson::warning: reached maximum iterations" << std::endl;
1981  return (false);
1982  }
1983 
1984 
1985  // LU Decomp
1986 #define LUDTINY 1.0e-24
1987  bool
1988  LUDcmp(GeoPrim::CVector a[], int indx[])
1989  {
1990  int i,j,k;
1991  int imax = 0;
1992  double big,dum,sum,temp;
1993  GeoPrim::CVector vv;
1994 
1995 
1996 
1997  for (i=0;i<3;i++) {
1998  big=0.0;
1999  for (j=0;j<3;j++)
2000  if ((temp=fabs(a[i][j])) > big) big=temp;
2001  if (big == 0.0){
2002  // std::cerr << "LUDcmp::error: Singular matrix" << std::endl;
2003  return(false);
2004  }
2005  vv[i]=1.0/big;
2006  }
2007  for (j=0;j<3;j++) {
2008  for (i=0;i<j;i++) {
2009  sum=a[i][j];
2010  for (k=0;k<i;k++)
2011  sum -= a[i][k]*a[k][j];
2012  a[i][j]=sum;
2013  }
2014  big=0.0;
2015  for (i=j;i<3;i++) {
2016  sum=a[i][j];
2017  for (k=0;k<j;k++)
2018  sum -= a[i][k]*a[k][j];
2019  a[i][j]=sum;
2020  if ( (dum=vv[i]*fabs(sum)) >= big) {
2021  big=dum;
2022  imax=i;
2023  }
2024  }
2025  if (j != imax) {
2026  for (k=0;k<3;k++) {
2027  dum=a[imax][k];
2028  a[imax][k]=a[j][k];
2029  a[j][k]=dum;
2030  }
2031  vv[imax]=vv[j];
2032  }
2033  indx[j]=imax;
2034  if (a[j][j] == 0.0) a[j][j]=LUDTINY;
2035  if (j != 3) {
2036  dum=1.0/(a[j][j]);
2037  for (i=j+1;i<3;i++)
2038  a[i][j] *= dum;
2039  }
2040  }
2041  return (true);
2042  }
2043 #undef LUDTINY
2044 
2045  // LU Back substitution
2046  void
2048  int indx[],
2049  GeoPrim::CVector &b)
2050  {
2051  int i,ii=0,ip,j;
2052  double sum;
2053 
2054  for (i=0;i<3;i++) {
2055  ip=indx[i];
2056  sum=b[ip];
2057  b[ip]=b[i];
2058  if (ii){
2059  for (j=ii;j<=i-1;j++)
2060  sum -= a[i][j]*b[j];
2061  }
2062  else if (sum)
2063  ii=i;
2064  b[i]=sum;
2065  }
2066  for (i=2;i>=0;i--) {
2067  sum=b[i];
2068  for (j=i+1;j<3;j++)
2069  sum -= a[i][j]*b[j];
2070  b[i]=sum/a[i][i];
2071  }
2072  }
2073 
2074  std::istream &operator>>(std::istream &iSt, Mesh::GeometricEntity &ge)
2075  {
2076  std::string line;
2077  std::getline(iSt,line);
2078  std::istringstream Istr(line);
2079  Istr >> ge.first;
2080  iSt >> ge._collections;
2081  ge.second = ge._collections.size();
2082  return(iSt);
2083  }
2084 
2085  std::istream &operator>>(std::istream &iSt, Mesh::Connectivity &ec)
2086  {
2087  std::string line;
2088  std::getline(iSt,line);
2089  std::istringstream Istr(line);
2090  IndexType nelem = 0;
2091  Istr >> nelem;
2092  if(nelem > 0){
2093  ec.Resize(nelem);
2094  ec._nelem = nelem;
2095  for(IndexType i = 0;i < nelem;i++){
2096  std::getline(iSt,line);
2097  std::istringstream Istr2(line);
2098  IndexType node;
2099  ec[i].reserve(8);
2100  while(Istr2 >> node)
2101  ec[i].push_back(node);
2102  std::vector<Mesh::IndexType>(ec[i]).swap(ec[i]);
2103  }
2104  }
2105  return(iSt);
2106  }
2107 
2108  std::istream &operator>>(std::istream &iSt, Mesh::NodalCoordinates &nc)
2109  {
2110  // if(nc.size() == 0) return (iSt);
2111  std::string line;
2112  IndexType nnodes;
2113  std::getline(iSt,line);
2114  std::istringstream Istr(line);
2115  Istr >> nnodes;
2116  if(nnodes > 0){
2117  nc.init(nnodes);
2118  for(IndexType n = 1;n <= nc.size();n++){
2119  double *inPtr = nc[n];
2120  std::getline(iSt,line);
2121  std::istringstream Istr2(line);
2122  Istr2 >> inPtr[0] >> inPtr[1] >> inPtr[2];
2123  }
2124  }
2125  return(iSt);
2126  }
2127 
2128  std::ostream &operator<<(std::ostream &oSt, const Mesh::NodalCoordinates &nc)
2129  {
2130  // if(nc.size() == 0) return(oSt);
2131  oSt.setf(std::ios::scientific);
2132  oSt.setf(std::ios::showpoint);
2133  oSt << std::setprecision(10) << std::setiosflags(std::ios::left);
2134  oSt << nc.size();
2135  if(nc.size() > 0) oSt << "\n";
2136  for(IndexType n = 1;n <= nc.size() ;n++){
2137  oSt << std::setw(16) << nc[n][0] << "\t"
2138  << std::setw(16) << nc[n][1] << "\t"
2139  << std::setw(16) << nc[n][2];
2140  if(n != nc.size())
2141  oSt << std::endl;
2142  }
2143  return (oSt);
2144  }
2145 
2146  std::ostream &operator<<(std::ostream &oSt, const Mesh::Connectivity &ec)
2147  {
2148  oSt << std::setiosflags(std::ios::left) << ec.size();
2149  if(ec.size() == 0) return(oSt);
2150  oSt << "\n";
2151  Mesh::Connectivity::const_iterator ci = ec.begin();
2152  while(ci != ec.end()){
2153  std::vector<IndexType>::const_iterator ni = ci->begin();
2154  while(ni != ci->end()){
2155  oSt << *ni++;
2156  if(ni != ci->end())
2157  oSt << "\t";
2158  }
2159  ci++;
2160  if(ci != ec.end())
2161  oSt << "\n";
2162  }
2163  return(oSt);
2164  }
2165 
2166  std::ostream &operator<<(std::ostream &oSt, const Mesh::GeometricEntity &ge)
2167  {
2168  if(ge.first.empty()) return(oSt);
2169  oSt << std::setiosflags(std::ios::left) << ge.first << "\n";
2170  oSt << ge._collections;
2171  return(oSt);
2172  }
2173 
2174 
2175 } // namespace Mesh
2176 
/brief Cartesian 3 Vector
void Sync()
Definition: Mesh.C:246
void swap(int &a, int &b)
Definition: buildface.cpp:88
int GetMeshCentroids(Mesh::NodalCoordinates &nc, Mesh::Connectivity &conn, std::vector< double > &centroids)
C3Vector & Init(const double *a)
Mesh::IndexType closest_node(const GeoPrim::CPoint &p, double *dist_ptr=NULL) const
Definition: Mesh.C:100
const double TOL
Definition: Mesh.H:53
void AddPoint(const CPoint &p)
void ShrinkWrap()
Definition: Mesh.C:247
void GetAdjacent(Connectivity &rl, Connectivity &dc, IndexType n=0, bool sortit=false)
Definition: Mesh.C:520
void init_copy(IndexType n, double *data)
Definition: Mesh.C:117
General connectivity object.
Definition: Mesh.H:334
void init(const double *points, unsigned int n)
void shape_func(const GeoPrim::CVector &, double[]) const
Definition: Mesh.C:906
bool operator<(const TestFace &f)
Definition: Mesh.C:217
Mesh::Connectivity _collections
Definition: Mesh.H:441
j indices k indices k
Definition: Indexing.h:6
void int int REAL REAL * y
Definition: read.cpp:74
void dshape_func(const GeoPrim::CVector &, double[][2]) const
Definition: Mesh.C:675
void jacobian(const GeoPrim::CPoint p[], const GeoPrim::CVector &, GeoPrim::CVector J[]) const
Definition: Mesh.C:704
Mesh::IndexType GlobalFindPointInMesh(const GeoPrim::CPoint &p, const NodalCoordinates &nc, const Connectivity &ec, const Connectivity &dc, const GeoPrim::CBox &box, GeoPrim::CVector &natc)
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
NT p1
KD_tree::Box box
Definition: Overlay_0d.C:47
double * ncdata
Definition: Mesh.H:261
int ReadMesh(const std::string &path, Mesh::UnstructuredMesh &mesh)
Mesh Stuff.
GeoPrim::C3Point Centroid()
Class Mesh is the main class that holds all information to describe the current state of the mesh...
Definition: Mesh.hpp:19
C3Vector Normal() const
void dshape_func(const GeoPrim::CVector &, double[][3]) const
Definition: Mesh.C:962
void GetNeighborhood(NeighborHood &, const Connectivity &dc, IndexType size=0)
Definition: Mesh.C:456
bool good() const
Definition: Mesh.C:47
bool LUDcmp(GeoPrim::CVector a[], int indx[])
real *8 function offset(vNorm, x2, y2, z2)
Definition: PlaneNorm.f90:211
void GetPointSet(GeoPrim::CPoint ps[], IndexType elnum, const Connectivity &ec, const NodalCoordinates &nc)
Definition: Mesh.C:773
bool contains(const CPoint &p) const
Definition: adj.h:150
void ReOrient(std::vector< IndexType > &ec)
Definition: Mesh.C:856
void ElementsOn(std::vector< Mesh::IndexType > &nodes, Connectivity &dc, std::vector< Mesh::IndexType > &subset)
Definition: Mesh.C:569
void Resize(unsigned int N=0)
Definition: Mesh.C:233
T norm(const NVec< DIM, T > &v)
void GetMeshBoxes(const NodalCoordinates &nc, const Connectivity &ec, GeoPrim::CBox &mesh_box, GeoPrim::CBox &small_box, GeoPrim::CBox &large_box)
Bounding boxes for a mesh.
Mesh::IndexType FindPointInMesh_2(const GeoPrim::CPoint &p, const NodalCoordinates &nc, const Connectivity &ec, const Connectivity &dc, const GeoPrim::CBox &box, GeoPrim::CVector &natc)
Locate element containing given physical point.
bool ShapeOK(std::vector< IndexType > &ec, NodalCoordinates &nc) const
Definition: Mesh.C:1521
*********************************************************************Illinois Open Source License ****University of Illinois NCSA **Open Source License University of Illinois All rights reserved ****Developed free of to any person **obtaining a copy of this software and associated documentation to deal with the Software without including without limitation the rights to and or **sell copies of the and to permit persons to whom the **Software is furnished to do subject to the following this list of conditions and the following disclaimers ****Redistributions in binary form must reproduce the above **copyright this list of conditions and the following **disclaimers in the documentation and or other materials **provided with the distribution ****Neither the names of the Center for Simulation of Advanced the University of nor the names of its **contributors may be used to endorse or promote products derived **from this Software without specific prior written permission ****THE SOFTWARE IS PROVIDED AS WITHOUT WARRANTY OF ANY **EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES **OF FITNESS FOR A PARTICULAR PURPOSE AND **NONINFRINGEMENT IN NO EVENT SHALL THE CONTRIBUTORS OR **COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR **ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE **USE OR OTHER DEALINGS WITH THE SOFTWARE v
Definition: roccomf90.h:20
void get_face_connectivities(Connectivity &, const std::vector< IndexType > &) const
Face conn for given element.
Definition: Mesh.C:1714
IndexType _size
Definition: Mesh.H:602
IndexType Size() const
Definition: Mesh.C:49
void DestroySizes()
Definition: Mesh.C:289
std::pair< IndexType, CellEntityIDType > SubEntityId
Definition: Mesh.H:59
void int int int REAL REAL REAL * z
Definition: write.cpp:76
void ReOrient(std::vector< IndexType > &ec)
Definition: Mesh.C:1601
void matrix_mode(IndexType offset=0)
Definition: Mesh.C:444
void AddElement()
Definition: Mesh.C:240
void Inverse(Connectivity &, IndexType nnodes=0) const
Definition: Mesh.C:312
IndexType & Node(IndexType e, IndexType n)
Definition: Mesh.H:354
bool Inverted(std::vector< IndexType > &ec, NodalCoordinates &nc) const
Definition: Mesh.C:1475
void GetNormalSet(GeoPrim::CVector ns[], IndexType elnum, const Connectivity &ec, const NodalCoordinates &nc)
Definition: Mesh.C:757
IndexType nfaces() const
Definition: Mesh.H:641
CVector & init(const CPoint &p)
IndexType Esize(IndexType n) const
Definition: Mesh.H:365
blockLoc i
Definition: read.cpp:79
IndexType nnodes
Definition: Mesh.H:262
void interpolate(const GeoPrim::CVector f[], const GeoPrim::CVector &nc, GeoPrim::CVector &) const
Definition: Mesh.C:810
int CollideCellsWithBox(Mesh::NodalCoordinates &nc, Mesh::Connectivity &conn, GeoPrim::CBox &box, std::vector< Mesh::IndexType > &candidates, std::vector< Mesh::IndexType > &cells)
void int int REAL * x
Definition: read.cpp:74
IndexType _size
Definition: Mesh.H:558
IndexType Nelem() const
Definition: Mesh.H:364
Connects continuous to discrete.
Definition: Mesh.H:433
const double LTOL
Definition: Mesh.H:54
Mesh::IndexType FindPointInMesh(const GeoPrim::CPoint &p, const NodalCoordinates &nc, const Connectivity &ec, const Connectivity &dc, const GeoPrim::CBox &box, GeoPrim::CVector &natc)
Locate element containing given physical point.
const NT & n
void BreadthFirstRenumber(std::vector< Mesh::IndexType > &remap)
Definition: Mesh.C:593
Mesh::IndexType FindPointInCells(const GeoPrim::CPoint &p, const NodalCoordinates &nc, const Connectivity &ec, const std::vector< Mesh::IndexType > &elements, GeoPrim::CVector &natc)
Locate element containing given physical point.
IndexType _nelem
Definition: Mesh.H:339
void BuildFaceConnectivity(Connectivity &fcon, Connectivity &ef, std::vector< Mesh::SymbolicFace > &sf, Connectivity &dc) const
Definition: Mesh.C:337
IndexType size() const
Definition: Mesh.C:48
const GeoPrim::CPoint closest_point(const GeoPrim::CPoint &p) const
Definition: Mesh.C:85
void Transpose(CVector matrix[])
Definition: GeoPrimitives.C:11
const double HTOL
Definition: Mesh.H:55
void graph_mode(IndexType offset=0)
Definition: Mesh.C:434
void SyncSizes()
Definition: Mesh.C:281
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
CVector & normalize()
void InverseDegenerate(Connectivity &, IndexType nnodes=0) const
Definition: Mesh.C:293
CBox around(const CPoint &p) const
j indices j
Definition: Indexing.h:6
C3Point Centroid() const
friend istream & operator>>(istream &stream, Mesh &mesh)
The mesh instream operator is used to drive the reading of the one input file to the code...
Definition: Mesh.cpp:402
#define LUDTINY
Definition: Mesh.C:1986
void LUBksb(GeoPrim::CVector a[], int indx[], GeoPrim::CVector &b)
bool contains_point(const C3Point &P) const
void shapef_jacobian_at(const GeoPrim::CPoint &p, GeoPrim::CVector &natc, IndexType elnum, const Connectivity &ec, const NodalCoordinates &nc, GeoPrim::CVector &fvec, GeoPrim::CVector fjac[]) const
Definition: Mesh.C:883
CBox intersect(const CBox &b) const
Connectivity con
Definition: Mesh.H:450
int CollideMeshWithBox(Mesh::NodalCoordinates &nc, Mesh::Connectivity &conn, GeoPrim::CBox &box, std::vector< Mesh::IndexType > &cells)
void int int REAL REAL REAL *z blockDim dim * ni
Definition: read.cpp:77
long double dist(long double *coord1, long double *coord2, int size)
bool NewtonRaphson(GeoPrim::CVector &natc, IndexType elnum, const GenericElement &el, const Connectivity &ec, const NodalCoordinates &nc, const GeoPrim::CPoint &point)
Newton-Raphson method, customized for using the GeoPrimitives and computational mesh constructs...
void shapef_jacobian_at(const GeoPrim::CPoint &p, GeoPrim::CVector &natc, IndexType elnum, const Connectivity &ec, const NodalCoordinates &nc, GeoPrim::CVector &fvec, GeoPrim::CVector jac[]) const
Definition: Mesh.C:784
void GetCoordinateBounds(NodalCoordinates &nc, std::vector< double > &)
C3Vector C3Point
IRAD::Primitive::IndexType IndexType
Definition: Mesh.H:57
void jacobian(const GeoPrim::CPoint p[], const GeoPrim::CVector &nc, GeoPrim::CVector J[]) const
Definition: Mesh.C:1016
friend ostream & operator<<(ostream &stream, Mesh &mesh)
The mesh ostream operator is used to drive the writing of both output fils from the code...
Definition: Mesh.cpp:359
void init(IndexType s=3)
Definition: Mesh.H:561
void interpolate(const GeoPrim::CVector f[], const GeoPrim::CVector &nc, GeoPrim::CVector &) const
Definition: Mesh.C:1066
GeoPrim::C3Point Centroid()
bool NewtonRaphson_2(GeoPrim::CVector &natc, IndexType elnum, const GenericCell_2 &el, const Connectivity &ec, const NodalCoordinates &nc, const GeoPrim::CPoint &point)
Newton-Raphson method, customized for using the GeoPrimitives and computational mesh constructs...
void init_node(IndexType n, const GeoPrim::CPoint &)
Definition: Mesh.C:78
bool empty() const
void Truncate()
Definition: Mesh.C:257
NodalCoordinates nc
Definition: Mesh.H:449
void shape_func(const GeoPrim::CVector &, double[]) const
Definition: Mesh.C:643
Encapsulates an element-connectivity of a mesh.
Definition: Connectivity.h:41
void destroy()
Definition: Mesh.C:269
void FindElementsInBox(const GeoPrim::CBox &box, const NodalCoordinates &nc, const Connectivity &dc, std::list< IndexType > &elements)
Get elements in box.