Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Rocmop_2.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: Rocmop_2.C,v 1.5 2008/12/06 08:45:24 mtcampbe Exp $
24 
25 /****************************************************************
26  * Rocmop_2.C (previously named Rocmop_1_1.C)
27  * Originally written by Phil Alexandar
28  *
29  * Modified by Pornput Suriyamongkol - 03/22/07
30  * --------------------------------------------
31  * - Rename this file to Rocmop_2.C
32  *
33  * - Make it links to Mesquite 0.9.5
34  * - Disable smooth_boeing()
35  *
36  * - Fixes in smooth()
37  * - Check total number of panes
38  * - Coordinate update algorithm
39  * - Displacement update algorithm
40  * - Constrain maximum displacement
41  *
42  ****************************************************************/
43 
44 #ifdef MESQUITE
45 #define USE_STD_INCLUDES 1
46 #define USE_C_PREFIX_INCLUDES 1
47 #include "Mesquite.hpp"
48 #include "MeshImpl.hpp"
49 #include "MsqError.hpp"
50 #include "InstructionQueue.hpp"
51 #include "MeshSet.hpp"
52 #include "TerminationCriterion.hpp"
53 #include "QualityAssessor.hpp"
54 #include "PlanarDomain.hpp"
55 #include "ShapeImprovementWrapper.hpp"
56 
57 // algorithms
58 //#include "MeanRatioQualityMetric.hpp"
59 #include "MeanRatioFunctions.hpp"
60 #include "EdgeLengthQualityMetric.hpp"
61 #include "LPtoPTemplate.hpp"
62 #include "FeasibleNewton.hpp"
63 #include "ConjugateGradient.hpp"
64 //#include "MsqMessage.hpp"
65 #include "MesqPane_95.h"
66 
67 using namespace Mesquite;
68 #endif
69 
70 #include "Rocblas.h"
71 #include "Rocmop_2.h"
72 #include "Rocmap.h"
73 #include "roccom.h"
74 #include "Pane_communicator.h"
75 #include "Pane_connectivity.h"
77 #include "Geometric_Metrics_3.h"
78 #include "PN_patch.h"
79 #include "geometry.h"
80 #include "mapbasic.h"
81 
82 // for debugging
83 #include <iostream>
84 #include <iomanip>
85 #include <fstream>
86 using namespace std;
87 // end for debugging
88 
89 // To enable profiling, use ROCPROF=1 in your make command.
90 #ifdef ROCPROF
91 #include "Rocprof.H"
92 #endif
93 
95 
96 using MAP::Pane_connectivity;
97 using MAP::Pane_communicator;
98 using MAP::Rocmap;
99 using MAP::Pane_ghost_connectivity;
100 using std::cout;
101 using std::endl;
102 
103 Rocmop::~Rocmop() {
104 
105  print_legible(0,"Entering Rocmop::~Rocmop");
106 
107  if (_buf_window){
108  delete _buf_window;
109  _buf_window = NULL;
110  }
111 
112  for(int i =0, ni=_dcs.size(); i<ni; ++i){
113  delete _dcs[i];
114  _dcs[i] = NULL;
115  }
116  print_legible(1,"Exiting Rocmop::~Rocmop");
117 }
118 
119 // Utility function to fetch a non-empty, non-commented line from the
120 // file passed in "Inf". The noop char is the "comment" character, all
121 // lines beginning with 'noop', or empty lines will be ignored. All
122 // whitespace is also ignored. Comments may go on the same line as
123 // data lines. Data lines must not start with whitespace. Valid data
124 // should be separated by newlines.
125 std::ifstream &get_next_line(std::ifstream &Inf,
126  std::string &line,
127  const char noop)
128 {
129  if(!Inf)
130  return(Inf);
131  std::getline(Inf,line);
132  while((line.empty() || line[0] == ' ' || line[0] == noop) && Inf)
133  std::getline(Inf,line);
134  return(Inf);
135 }
136 
137 // New Rocmop function to read the configuration file. Currently, all
138 // processors open and read this file (as opposed to process 0 bc'ing).
139 // If the file does not exist, or has formatting errors, the file is
140 // ignored and Rocmop will continue to function with it's defaults.
141 void Rocmop::read_config_file(const std::string &cfname)
142 {
143  std::ifstream Inf;
144  Inf.open(cfname.c_str());
145 
146  // We can't use the usual print_legible function here because the
147  // buffer winodw may not be created yet.
148  int rank =0;
149  if(COMMPI_Initialized()){
150  int ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);
151  assert( ierr == 0);
152  }
153 
154  // If the file doesn't exist, fire off a warning and continue
155  if(!Inf && rank==0){
156  std::cerr << "Rocmop: Warning: Could not open configfile, "
157  << cfname << "." << std::endl;
158  return;
159  }
160 
161  std::string line;
162  std::istringstream Istr;
163 
164  // Read and set the verbosity
165  int verbosity;
166  get_next_line(Inf,line,'#');
167  // At this point, "line" should have data in it. By using the
168  // istringstream object this way, we eliminate all whitespace
169  // and extract only the valid part of the line. If the file
170  // has already closed, line will be empty, and verbosity will
171  // usually take on some nonsense value.
172  Istr.str(line);
173  Istr >> verbosity;
174  // If the line had only the one chunk of data in it, Istr will
175  // have a bit set that needs to be cleared with a call to "clear()"
176  // before populating it with another string.
177  Istr.clear();
178  if(verbosity < 0 || verbosity > 10){
179  std::cerr << "Rocmop: Warning: Invalid verbosity from configfile. "
180  << "Giving up on " << cfname << "." << std::endl;
181  Inf.close();
182  return;
183  }
184  _verb = verbosity;
185  // Speak up if verbosity is turned on!
186  if (rank==0 && _verb){
187  std::cout << "Rocmop: Found configfile, " << cfname << "." << std::endl
188  << "Rocmop: Setting verbosity to " << _verb << "." << std::endl;
189  }
190 
191  // Load the next line from configfile and set smoothing method
192  get_next_line(Inf,line,'#');
193  Istr.str(line);
194  Istr >> _method;
195  Istr.clear();
196  if(_method < 0 || _method > SMOOTH_NONE){
197  std::cerr << "Rocmop: Warning: Invalid smoothing method from configfile. "
198  << "Giving up on " << cfname << "." << std::endl;
199  Inf.close();
200  return;
201  }
202  // I love these ternary operators
203  if (rank==0 && _verb){
204  std::cout << "Rocmop: Setting method to "
205  << (_method == SMOOTH_VOL_MESQ_WG ? "SMOOTH_VOL_MESQ_WG" :
206  (_method == SMOOTH_VOL_MESQ_NG ? "SMOOTH_VOL_MESQ_NG" :
207  (_method == SMOOTH_SURF_MEDIAL ? "SMOOTH_SURF_MEDIAL" :
208  "SMOOTH_NONE"))) << "." << std::endl;
209  }
210 
211  // Load the next line and set laziness
212  int lazy;
213  get_next_line(Inf,line,'#');
214  Istr.str(line);
215  Istr >> lazy;
216  Istr.clear();
217  if(lazy > 0)
218  _lazy = 1;
219  if (rank==0 && _verb){
220  std::cout << "Rocmop: Setting lazy to " << _lazy << "." << std::endl;
221  }
222 
223  // Load the next line and set tolerance for lazy threshold
224  double tol;
225  get_next_line(Inf,line,'#');
226  Istr.str(line);
227  Istr >> tol;
228  Istr.clear();
229  if(tol < 0. || tol > 180.){
230  std::cerr << "Rocmop: Warning: Invalid dihedral angle tolerance"
231  << " from configfile. "
232  << "Giving up on " << cfname << "." << std::endl;
233  Inf.close();
234  return;
235  }
236  _tol = tol;
237  if (rank==0 && _verb){
238  std::cout << "Rocmop: Setting tolerance to " << _tol << "." << std::endl;
239  }
240 
241  // Load the next line and set node displacement constraint for Mesquite smoothing
242  double max_disp;
243  get_next_line(Inf,line,'#');
244  Istr.str(line);
245  Istr >> max_disp;
246  Istr.clear();
247  if(max_disp < 0. || max_disp > 10.0){
248  std::cerr << "Rocmop: Warning: Invalid displacement constraint from configfile. "
249  << "Giving up on " << cfname << "." << std::endl;
250  Inf.close();
251  return;
252  }
253  _maxdisp = max_disp;
254  if (rank==0 && _verb){
255  std::cout << "Rocmop: Setting displacement constraint to "
256  << _maxdisp << "." << std::endl;
257  }
258 
259  // Load the next line and set N, which forces Rocmop to smooth every Nth step
260  get_next_line(Inf,line,'#');
261  Istr.str(line);
262  Istr >> _smoothfreq;
263  Istr.clear();
264  if(_smoothfreq <= 0 || _method == SMOOTH_NONE)
265  _smoothfreq = 0;
266  if (rank==0 && _verb){
267  if(_method == SMOOTH_NONE){
268  std::cout << "Rocmop: No method selected, setting N to 0"
269  << ",disabling smoothing." << std::endl;
270  }
271  else{
272  std::cout << "Rocmop: Setting N to " << _smoothfreq
273  << (_smoothfreq==0 ? ", disabling smoothing." : ".")
274  << std::endl;
275 
276  }
277  }
278 
279  // Displacement threshold. When the max displacement among all processors
280  // exceeds this value, smooth.
281  get_next_line(Inf,line,'#');
282  Istr.str(line);
283  Istr >> _disp_thresh;
284  Istr.clear();
285  if(_disp_thresh < 0.0)
286  _disp_thresh = 0.0;
287  else if ((_smoothfreq > 1) && (_disp_thresh > 0.0) ){
288  _smoothfreq = 1;
289  if(rank==0 && _verb)
290  std::cout << "Rocmop: WARNING: N reset to 1 to enable displacement thresholding."
291  << std::endl;
292  }
293  if (rank==0 && _verb){
294  std::cout << "Rocmop: Setting displacement threshold to "
295  << _disp_thresh << "." << std::endl;
296  }
297 
298  // Close up the file, we're done.
299  Inf.close();
300 
301 }
302 
303 void Rocmop::load( const std::string &mname) {
304 
305  Rocmop *mop = new Rocmop();
306 
307  // Hardcoded the control file location for now. I didn't really see a clean
308  // way to allow this to be dynamically set without adding additional init
309  // calls to codes outside Rocmop.
310  mop->read_config_file("Rocmop/RocmopControl.txt");
311 
312  COM_new_window( mname.c_str());
313 
314  std::string glb=mname+".global";
315 
316  COM_new_attribute( glb.c_str(), 'w', COM_VOID, 1, "");
317  COM_set_object( glb.c_str(), 0, mop);
318 
319  COM_Type types[4];
320  types[0] = COM_RAWDATA;
321  types[1] = COM_METADATA;
322  types[2] = COM_METADATA;
323  types[3] = COM_DOUBLE;
324 
325  COM_set_member_function( (mname+".smooth").c_str(),
326  (Member_func_ptr)(&Rocmop::smooth),
327  glb.c_str(), "bibB", types);
328 
329  types[1] = COM_STRING;
330  types[2] = COM_VOID;
331  COM_set_member_function( (mname+".set_value").c_str(),
332  (Member_func_ptr)(&Rocmop::set_value),
333  glb.c_str(), "bii", types);
334 
335  types[1] = COM_METADATA;
336  types[2] = COM_INT;
337 
338  COM_set_member_function( (mname+".smooth_boeing").c_str(),
339  (Member_func_ptr)(&Rocmop::smooth_boeing),
340  glb.c_str(), "bbi", types);
341 
342  types[1] = COM_METADATA;
343  types[2] = COM_METADATA;
344 
345  COM_set_member_function( (mname+".add_aspect_ratios").c_str(),
346  (Member_func_ptr)(&Rocmop::add_aspect_ratios),
347  glb.c_str(), "bbB", types);
348 
349  types[2] = COM_DOUBLE;
350  types[3] = COM_DOUBLE;
351 
352  COM_set_member_function( (mname+".obtain_extremal_dihedrals").c_str(),
353  (Member_func_ptr)(&Rocmop::obtain_extremal_dihedrals),
354  glb.c_str(), "bioo", types);
355 
356  COM_window_init_done( mname.c_str());
357 
358 }
359 
360 void Rocmop::unload( const std::string &mname) {
361 
362  Rocmop *mop;
363  std::string glb=mname+".global";
364 
365  COM_get_object( glb.c_str(), 0, &mop);
366  delete mop;
367 
368  COM_delete_window( mname.c_str());
369 }
370 
371 // Finds the maximum displacement over all processors
372 bool
373 Rocmop::check_displacements(COM::Attribute *w_disp)
374 {
375 #ifdef ROCPROF
376  Profile_begin("Rocmop::check_disp");
377 #endif
378 
379  int disp_id = w_disp->id();
380  double max_norm = 0.0;
381  static double disp_tally = 0.0;
382  bool retval = true;
383  // std::ofstream Ouf;
384  // Ouf.open("displacements.txt",ios::app);
385  std::vector<Pane*> allpanes;
386  const_cast<COM::Window*>(_usr_window)->panes(allpanes);
387 
388  // Find the maximum displacement on this processor
389  for(int i=0,ni = allpanes.size(); i<ni; ++i){
390 
391  Vector_3<double> *ptr = NULL;
392  COM::Attribute* ptr_att = allpanes[i]->attribute(disp_id);
393  void* void_ptr = ptr_att->pointer();
394  ptr = reinterpret_cast<Vector_3<double>*>(void_ptr);
395 
396  for(int j=0,nj = allpanes[i]->size_of_real_nodes(); j<nj; ++j){
397  double norm = ptr[j].norm();
398  // Re-assign them to zero to maintain original Rocmop behavior
399  // just in case. I'm pretty sure that any values in this array
400  // already get wiped out when the Mesquite displacements are
401  // copied in.
402  ptr[j][0] = 0.0;
403  ptr[j][1] = 0.0;
404  ptr[j][2] = 0.0;
405  // Ouf << j << ": " << norm << std::endl;
406  if(norm > max_norm)
407  max_norm = norm;
408  }
409  }
410  // Maximize the displacement across all processors
411  agree_double(max_norm,MPI_MAX);
412 
413  // Update the tally
414  disp_tally += max_norm;
415 
416  // Build a blurb about displacement
417  std::ostringstream Ostr;
418  Ostr << "Mesh Displacement: " << disp_tally;
419 
420  // Determine whether we have exceeded the threshold
421  if(disp_tally > _disp_thresh){
422  disp_tally = 0.0;
423  retval = true;
424  // If we intend to smooth - also print out the displacement
425  print_legible(0,Ostr.str().c_str());
426  }
427  else {
428  retval = false;
429  // If not smoothing, print out displacement if verbosity is higher
430  print_legible(1,Ostr.str().c_str());
431  }
432 #ifdef ROCPROF
433  Profile_end("Rocmop::check_disp");
434 #endif
435  // Ouf.close();
436  return(retval);
437 }
438 
439 // Zero displacements array
440 void
441 Rocmop::zero_displacements(COM::Attribute *w_disp)
442 {
443 #ifdef ROCPROF
444  Profile_begin("Rocmop::zero_disp");
445 #endif
446 
447  int disp_id = w_disp->id();
448  std::vector<Pane*> allpanes;
449  const_cast<COM::Window*>(_usr_window)->panes(allpanes);
450 
451  for(int i=0,ni = allpanes.size(); i<ni; ++i){
452  Vector_3<double> *ptr = NULL;
453  COM::Attribute* ptr_att = allpanes[i]->attribute(disp_id);
454  void* void_ptr = ptr_att->pointer();
455  ptr = reinterpret_cast<Vector_3<double>*>(void_ptr);
456  for(int j=0,nj = allpanes[i]->size_of_real_nodes(); j<nj; ++j){
457  // Zero to maintain original physics module behavior
458  ptr[j][0] = 0.0;
459  ptr[j][1] = 0.0;
460  ptr[j][2] = 0.0;
461  }
462  }
463 #ifdef ROCPROF
464  Profile_end("Rocmop::zero_disp");
465 #endif
466 }
467 
468 // Add aspect ratio measures to the user's mesh
469 void Rocmop::add_aspect_ratios(COM::Attribute *usr_att,
470  COM::Attribute *buf_att){
471 
472  COM::Window* usr_window = usr_att->window();
473  COM::Window* buf_window = NULL;
474 
475  bool del_buffer = false;
476 
477  if(!buf_att){
478  del_buffer = true;
479  // Create a buffer window by cloning from the user window
480  std::string buf_name(usr_window->name()+"-Rocmop_add_aspect");
481  buf_window = new COM::Window(buf_name,
482  usr_window->get_communicator());
483  buf_window->inherit( usr_att, "",
484  COM::Pane::INHERIT_CLONE, true, NULL,0);
485  buf_window->init_done();
486  }
487  else
488  buf_window = _buf_window;
489 
490  std::vector<Pane*> allpanes;
491 
492  buf_window->panes(allpanes);
493 
494  // Create and resize window level buffer attributes
495 #if 0
496  COM::Attribute * w_buff_R =
497  buf_window->new_attribute("Aspect Ratio: R (circumradius)",'e',COM_DOUBLE,1,"");
498  COM::Attribute * w_buff_r =
499  buf_window->new_attribute("Aspect Ratio: r (inradius)",'e',COM_DOUBLE,1,"");
500  COM::Attribute * w_buff_l =
501  buf_window->new_attribute("Aspect Ratio: l (shortest edge)",'e',COM_DOUBLE,1,"");
502  COM::Attribute * w_buff_rR =
503  buf_window->new_attribute("Aspect Ratio: 3r/R",'e',COM_DOUBLE,1,"");
504  COM::Attribute * w_buff_Rr =
505  buf_window->new_attribute("Aspect Ratio: R/r",'e',COM_DOUBLE,1,"");
506  COM::Attribute * w_buff_Rl =
507  buf_window->new_attribute("Aspect Ratio: R/l",'e',COM_DOUBLE,1,"");
508 #endif
509  COM::Attribute * w_buff_min =
510  buf_window->new_attribute("Aspect Ratio: min dih",'e',COM_DOUBLE,1,"");
511  COM::Attribute * w_buff_max =
512  buf_window->new_attribute("Aspect Ratio: max dih",'e',COM_DOUBLE,1,"");
513  COM::Attribute * w_buff_type =
514  buf_window->new_attribute("Element type",'e',COM_INT,1,"");
515 #if 0
516  buf_window->resize_array(w_buff_R,0);
517  buf_window->resize_array(w_buff_r,0);
518  buf_window->resize_array(w_buff_l,0);
519  buf_window->resize_array(w_buff_rR,0);
520  buf_window->resize_array(w_buff_Rr,0);
521  buf_window->resize_array(w_buff_Rl,0);
522 #endif
523  buf_window->resize_array(w_buff_min,0);
524  buf_window->resize_array(w_buff_max,0);
525  buf_window->resize_array(w_buff_type,0);
526  buf_window->init_done();
527 
528  // Obtain buffer attribute ids
529 #if 0
530  int R_id = w_buff_R->id();
531  int r_id = w_buff_r->id();
532  int l_id = w_buff_l->id();
533  int rR_id = w_buff_rR->id();
534  int Rr_id = w_buff_Rr->id();
535  int Rl_id = w_buff_Rl->id();
536 #endif
537  int min_id = w_buff_min->id();
538  int max_id = w_buff_max->id();
539  int type_id = w_buff_type->id();
540 
541  // Create and resize window level user attributes
542 #if 0
543  COM::Attribute * w_usr_R =
544  usr_window->new_attribute("Aspect Ratio: R",'e',COM_DOUBLE,1,"");
545  COM::Attribute * w_usr_r =
546  usr_window->new_attribute("Aspect Ratio: r",'e',COM_DOUBLE,1,"");
547  COM::Attribute * w_usr_l =
548  usr_window->new_attribute("Aspect Ratio: l",'e',COM_DOUBLE,1,"");
549  COM::Attribute * w_usr_rR =
550  usr_window->new_attribute("Aspect Ratio: 3r/R",'e',COM_DOUBLE,1,"");
551  COM::Attribute * w_usr_Rr =
552  usr_window->new_attribute("Aspect Ratio: R/r",'e',COM_DOUBLE,1,"");
553  COM::Attribute * w_usr_Rl =
554  usr_window->new_attribute("Aspect Ratio: R/l",'e',COM_DOUBLE,1,"");
555 #endif
556  COM::Attribute * w_usr_min =
557  usr_window->new_attribute("Aspect Ratio: min dih",'e',COM_DOUBLE,1,"");
558  COM::Attribute * w_usr_max =
559  usr_window->new_attribute("Aspect Ratio: max dih",'e',COM_DOUBLE,1,"");
560  COM::Attribute * w_usr_type =
561  usr_window->new_attribute("Element type",'e',COM_INT,1,"");
562 
563 #if 0
564  usr_window->resize_array(w_usr_R,0);
565  usr_window->resize_array(w_usr_r,0);
566  usr_window->resize_array(w_usr_l,0);
567  usr_window->resize_array(w_usr_rR,0);
568  usr_window->resize_array(w_usr_Rr,0);
569  usr_window->resize_array(w_usr_Rl,0);
570 #endif
571  usr_window->resize_array(w_usr_min,0);
572  usr_window->resize_array(w_usr_max,0);
573  usr_window->resize_array(w_usr_type,0);
574  usr_window->init_done();
575 
576 #if 0
577  double R,r,l;
578 #endif
579  double angles[] = {0.0,0.0};
580 
581  for(int i=0,ni=(int)allpanes.size();i<ni;++i){
582 #if 0
583  // get Pane level buffer attributes
584  double *R_ptr = reinterpret_cast<double *>
585  (allpanes[i]->attribute(R_id)->pointer());
586  double *r_ptr = reinterpret_cast<double *>
587  (allpanes[i]->attribute(r_id)->pointer());
588  double *l_ptr = reinterpret_cast<double *>
589  (allpanes[i]->attribute(l_id)->pointer());
590  double *rR_ptr = reinterpret_cast<double *>
591  (allpanes[i]->attribute(rR_id)->pointer());
592  double *Rr_ptr = reinterpret_cast<double *>
593  (allpanes[i]->attribute(Rr_id)->pointer());
594  double *Rl_ptr = reinterpret_cast<double *>
595  (allpanes[i]->attribute(Rl_id)->pointer());
596 #endif
597  double *min_ptr = reinterpret_cast<double *>
598  (allpanes[i]->attribute(min_id)->pointer());
599  double *max_ptr = reinterpret_cast<double *>
600  (allpanes[i]->attribute(max_id)->pointer());
601  int * type_ptr = reinterpret_cast<int *>
602  (allpanes[i]->attribute(type_id)->pointer());
603 
604  for(int j=0,nj=allpanes[i]->size_of_elements();j<nj;++j){
605 
606  Element_node_enumerator ene(allpanes[i],j+1);
607 
608 #if 0
609  Aspect_Metric_3 aspect_met;
610  aspect_met.initialize(ene);
611  aspect_met.getAspects(R,r,l);
612 #endif
613  Angle_Metric_3 angle_met;
614  angle_met.initialize(ene);
615  angle_met.compute(angles);
616 #if 0
617  R_ptr[j] = R;
618  r_ptr[j] = r;
619  l_ptr[j] = l;
620  COM_assertion_msg(R != 0.0,
621  "Cannot calculate aspect ratios with zero magnitude circumradius");
622  rR_ptr[j] = (3.0*r)/R;
623  COM_assertion_msg(r != 0.0,
624  "Cannot calculate aspect ratios with zero magnitude circumradius");
625  Rr_ptr[j] = R/r;
626  COM_assertion_msg(l != 0.0,
627  "Cannot calculate aspect ratios with zero magnitude circumradius");
628  Rl_ptr[j] = R/l;
629 #endif
630  min_ptr[j] = angles[0];
631  max_ptr[j] = angles[1];
632  type_ptr[j] = ene.type();
633  }
634  }
635 #if 0
636  Rocmap::update_ghosts(w_buff_R);
637  Rocmap::update_ghosts(w_buff_r);
638  Rocmap::update_ghosts(w_buff_l);
639  Rocmap::update_ghosts(w_buff_rR);
640  Rocmap::update_ghosts(w_buff_Rr);
641  Rocmap::update_ghosts(w_buff_Rl);
642 #endif
643  Rocmap::update_ghosts(w_buff_min);
644  Rocmap::update_ghosts(w_buff_max);
645  Rocmap::update_ghosts(w_buff_type);
646 #if 0
647  Rocblas::copy(w_buff_R,w_usr_R);
648  Rocblas::copy(w_buff_r,w_usr_r);
649  Rocblas::copy(w_buff_l,w_usr_l);
650  Rocblas::copy(w_buff_rR,w_usr_rR);
651  Rocblas::copy(w_buff_Rr,w_usr_Rr);
652  Rocblas::copy(w_buff_Rl,w_usr_Rl);
653 #endif
654  Rocblas::copy(w_buff_min,w_usr_min);
655  Rocblas::copy(w_buff_max,w_usr_max);
656  Rocblas::copy(w_buff_type,w_usr_type);
657 
658  if(del_buffer)
659  delete buf_window;
660 }
661 
662 #if 0
663 void Rocmop::get_user_coords(){
664  std::vector<Pane*> allbufpanes;
665  std::vector<Pane*> allusrpanes;
666  const_cast<COM::Window*>(_usr_window)->panes(allusrpanes);
667  _buf_window->panes(allbufpanes);
668  COM_assertion_msg(allbufpanes.size() == allusrpanes.size(),
669  "Buffer window and user window have different number of panes.");
670 
671  double *usr_x = NULL;
672  double *usr_y = NULL;
673  double *usr_z = NULL;
674 
675  int x_space = 1;
676  int y_space = 1;
677  int z_space = 1;
678 
679  for(int i=0, ni = allusrpanes.size(); i<ni; ++i){
680 
681  int stride = allusrpanes[i]->attribute(COM_NC)->stride();
682  // if stride == 0, then X,Y,Z coords stored in separate arrays
683  if(stride>=3){
684  x_space = y_space = z_space = allusrpanes[i]->attribute(COM_NC)->
685  size_of_components();
686  usr_x = allusrpanes[i]->attribute(COM_NC)->coordinates();
687  usr_y = usr_x +1;
688  usr_z = usr_y +1;
689  }
690  // else, if stride == 1, all X coords, then all Y, then all Z in 1 array
691  else if(stride==1){
692  }
693  }
694 }
695 
696 void Rocmop::get_real_disp(){
697 }
698 #endif
699 
700 void Rocmop::smooth(const COM::Attribute *pmesh,
701  COM::Attribute *disp,
702  double* timestep){
703 
704  // The static var N will statically store the current value of
705  // N. When N == 0, we will smooth and set N back to (_smoothfreq - 1).
706  // What this amounts to is that we smooth only every _smoothfreqth call
707  // to Rocmop. _smoothfreq is specified as "N" in the config file.
708  static int N = (_smoothfreq-1);
709 
710  if(N == 0){ // Go ahead and actually smooth if this is true
711  N = (_smoothfreq-1); // Reset N
712 
713  // We want to start profiling from here as it's smoothing we
714  // want to time, not the NOOP calls.
715 #ifdef ROCPROF
716  Profile_begin("Rocmop::smooth");
717 #endif
718 
719  COM_assertion_msg( validate_object()==0, "Invalid object");
720 
721  // Verify that we are working with a mesh or pmesh
722  int pmesh_id = pmesh->id();
723  COM_assertion_msg( pmesh &&
724  (pmesh_id==COM::COM_PMESH || pmesh_id==COM::COM_MESH),
725  "Input to Rocmop::smooth must be a mesh or pmesh attribute.");
726  _is_pmesh = (pmesh_id == COM_PMESH) ? true : false;
727 
728  // If buffer window exists and was cloned from the current user
729  // window, then just update the coordinates.
730 
731  if(_buf_window && (_usr_window == pmesh->window()))
732  {
733  // update nodel coordinates (real part) from _usr_window
734  update_buf_real_nc();
735  }
736 
737  // Else, inherit(clone) a buffer window from the user's mesh.
738  else
739  {
740  // Eliminate any old buffers
741  if(_buf_window)
742  delete _buf_window;
743 
744  _usr_window = pmesh->window();
745 
746  // First, check if pconn of _usr_window is complete
747  int pconnErr = 0;
748  pconnErr = check_input_pconn();
749  agree_int(pconnErr, MPI_MAX);
750  if (pconnErr == 1)
751  COM_assertion_msg(pconnErr == 0, "*** Rocmop:ERROR: PCONN incomplete ***");
752 
753  // Create a buffer window by cloning from the user window
754  std::string buf_name(_usr_window->name()+"-Rocmopbuf");
755  _buf_window = new COM::Window(buf_name,
756  _usr_window->get_communicator());
757  _buf_window->inherit( const_cast<COM::Attribute*>(_usr_window->attribute(COM::COM_MESH)), "",
758  COM::Pane::INHERIT_CLONE, false, NULL, 0);
759  _buf_window->init_done();
760 
761  // Add the pconn
762  if(_buf_window->size_of_panes_global() > 1){
763  Pane_ghost_connectivity pgc(_buf_window);
764  pgc.build_pconn();
765  }
766 
767  // Perform initialization specific to the smoother.
768  smoother_specific_init();
769  }
770 
771  // Max possible worst element quality is 180.0, so this
772  // default should result in mesh smoothing if _lazy==0
773  double mesh_qual = 190.0;
774 
775  // Check initial quality if we are in lazy mode
776  if(_lazy){
777 
778  // Fill a vector with pointers to the local panes
779  std::vector<const Pane*> allpanes;
780  _buf_window->panes(allpanes);
781  mesh_qual = check_all_elem_quality(allpanes);
782  }
783 
784  // Mechanism to trigger smoothing on tallied displacements
785  bool exceeded = true;
786  if(_disp_thresh > 0.0)
787  exceeded = check_displacements(disp);
788 
789  if(exceeded || ((mesh_qual > _tol) && _lazy)){
790  print_legible(0,"Smoothing...");
791  perform_smoothing();
792  print_legible(0,"Smoothing complete.");
793 
794  // At this point NC in _buf_window has been smoothed.
795  // Get displacement.
796  get_usr_disp(pmesh, disp, timestep);
797  }
798  else
799  {
800  _usr_window = pmesh->window();
801  zero_displacements(disp);
802  }
803 
804 #ifdef ROCPROF
805  Profile_end("Rocmop::smooth");
806 #endif
807  } // if (N says it's smoothing time
808  else{
809  if(_smoothfreq > 0)
810  N--;
811  _usr_window = pmesh->window();
812  zero_displacements(disp);
813  }
814 }
815 
816 /*************************************************************************
817  *
818  * Rocmop::update_buf_real_nc()
819  *
820  * Update update real NC of _buf_window from _usr_window
821  *
822  *************************************************************************/
823 
825 {
826  std::vector<const Pane*> allbufpanes;
827  _buf_window->panes(allbufpanes);
828  std::vector<const Pane*> allusrpanes;
829  _usr_window->panes(allusrpanes);
830 
831  COM_assertion_msg(allbufpanes.size() == allusrpanes.size(),
832  "Different number of panes on buffer and user windows.");
833 
834  for(int i = 0, ni = allbufpanes.size(); i < ni; ++i)
835  {
836  // Obtain pane level attributes
837  const COM::Attribute *usr_nc = allusrpanes[i]->attribute( COM::COM_NC);
838  const COM::Attribute *buf_nc = allbufpanes[i]->attribute( COM::COM_NC);
839 
840  COM_assertion_msg(usr_nc->stride() != 0,
841  "Rocmop can not operate on meshes with stride == 0");
842 
843  COM_assertion_msg(usr_nc->size_of_real_items() == buf_nc->size_of_real_items(),
844  "Number of real items differs between buffer and user windows");
845 
846  double* usr_nc_ptr = (double*)usr_nc->pointer();
847  double* buf_nc_ptr = (double*)buf_nc->pointer();
848 
849  // get stride and distance_to_next_component
850  int usr_nc_stride = usr_nc->stride();
851  int buf_nc_stride = buf_nc->stride();
852  int usr_nc_next_comp;
853  int buf_nc_next_comp;
854 
855  if (usr_nc_stride == 1)
856  usr_nc_next_comp = usr_nc->size_of_items();
857  else
858  usr_nc_next_comp = 1;
859 
860  if (buf_nc_stride == 1)
861  buf_nc_next_comp = buf_nc->size_of_items();
862  else
863  buf_nc_next_comp = 1;
864 
865  // update real node coordinates
866  for(int j=0, nj = usr_nc->size_of_real_items(); j<nj; ++j){
867  *buf_nc_ptr = *usr_nc_ptr;
868  *(buf_nc_ptr+ 1*buf_nc_next_comp) = *(usr_nc_ptr + 1*usr_nc_next_comp);
869  *(buf_nc_ptr+ 2*buf_nc_next_comp) = *(usr_nc_ptr + 2*usr_nc_next_comp);
870 
871  buf_nc_ptr += buf_nc_stride;
872  usr_nc_ptr += usr_nc_stride;
873  }
874  }
875 }
876 
877 
878 /*************************************************************************
879  *
880  * Rocmop::check_input_pconn()
881  *
882  * Check if all ghost nodes are listed in pconn block 3 of _usr_window
883  *
884  *************************************************************************/
885 
887 {
888  int rank =0;
889  if(COMMPI_Initialized())
890  {
891  int ierr = MPI_Comm_rank(_usr_window->get_communicator(), &rank);
892  assert( ierr == 0);
893  }
894 
895  std::vector<const Pane*> allusrpanes;
896  _usr_window->panes(allusrpanes);
897 
898  for(int i = 0, ni = allusrpanes.size(); i < ni; ++i)
899  {
900  // Obtain pane level attributes
901  const COM::Attribute *usr_nc = allusrpanes[i]->attribute(COM::COM_NC);
902  const COM::Attribute *usr_pconn = allusrpanes[i]->attribute(COM::COM_PCONN);
903  int minGhostNodeID = usr_nc->size_of_real_items() + 1;
904  int maxGhostNodeID = usr_nc->size_of_items();
905  int numGhostNodes = maxGhostNodeID - minGhostNodeID + 1;
906  int * pconnArray = (int *)usr_pconn->pointer();
907 
908  // Check pconn
909  bool OORGhostNodes = false; // found out of range ghost node
910  bool missGhostNodes = false; // ghost nodes missed from pconn
911 
912  // Allocate marking array
913  int * isMarked = new int [numGhostNodes];
914  for (int j = 0; j < numGhostNodes; j++)
915  isMarked[j] = 0;
916 
917  // Jump to pconn block 3
918  int index = 0;
919  int numNbrs = 0;
920  int numItems = 0;
921 
922  for (int j = 0; j < 2; j++)
923  {
924  numNbrs = pconnArray[index];
925  index++;
926 
927  for (int k = 0; k < numNbrs; k++)
928  {
929  index++; // step over proc id
930  numItems = pconnArray[index];
931  index++;
932  index += numItems;
933  }
934  }
935 
936  // Begin marking
937  numNbrs = pconnArray[index];
938  index++;
939 
940  for (int j = 0; j < numNbrs; j++)
941  {
942  index++; // step over proc id
943  numItems = pconnArray[index];
944  index++;
945 
946  for (int k = 0; k < numItems; k++)
947  {
948  int lid = pconnArray[index];
949  index++;
950 
951  if (lid < minGhostNodeID || lid > maxGhostNodeID)
952  {
953  std::cerr << "Rocmop: Error in check_input_pconn(): Rank "
954  << rank << ", Ghost node " << lid
955  << " is out of ghost node range.\n" << std::endl;
956  OORGhostNodes = true;
957  }
958  else if (isMarked[lid - minGhostNodeID] == 1)
959  {
960  if (_verb > 0)
961  std::cerr << "Rocmop: Warning in check_input_pconn(): Rank "
962  << rank << ", Ghost node " << lid
963  << " has > 1 owners.\n" << std::endl;
964  }
965  else
966  isMarked[lid - minGhostNodeID] = 1;
967  }
968  }
969 
970  // Check if any node is not marked
971  for (int j = 0; j < numGhostNodes; j++)
972  if (isMarked[j] == 0)
973  {
974  missGhostNodes = true;
975  std::cerr << "Rocmop: Error in check_input_pconn(): Rank "
976  << rank << ", Ghost node " << (j + minGhostNodeID)
977  << " is not listed in pconn block 3.\n" << std::endl;
978  }
979 
980  // Free up memory
981  delete isMarked;
982 
983  // Return the result
984  if (OORGhostNodes == true || missGhostNodes == true)
985  return 1;
986  }
987 
988  return 0;
989 }
990 
991 
992 /*************************************************************************
993  *
994  * Rocmop::get_usr_disp()
995  *
996  * Get displacement in _usr_window based on
997  * nodal coordinates in _buf_window
998  *
999  *************************************************************************/
1000 
1001 void Rocmop::get_usr_disp(const COM::Attribute *pmesh,
1002  COM::Attribute *disp,
1003  double* timestep)
1004 {
1005  /*
1006  * Disp array contains all nodal displacements.
1007  * For the real part, all displacements must not exceed
1008  * a given constraint. For the ghost part, they can since
1009  * they need to make up for incorrect initial positions
1010  * given by Rocflu (Rocflu never updates ghost nodes).
1011  *
1012  * The following steps are done.
1013  *
1014  * 1. Store displacements of REAL nodes in disp
1015  *
1016  * 2. Check if any displacements exceed the constraint
1017  * 2.1 If so, scale down all REAL displacements
1018  *
1019  * 3. Put updated NC in disp
1020  *
1021  * 4. Update ghost NC using Rocmap::update_ghosts(disp)
1022  *
1023  * 5. Disp now can be correctly calculated using
1024  * Rocblas::sub(disp, orig_nc, disp)
1025  *
1026  *
1027  * Pornput Suriyamongkol
1028  * 02/20/2007
1029  */
1030 
1031  std::vector<const Pane*> allusrpanes;
1032  std::vector<const Pane*> allbufpanes;
1033  _usr_window->panes(allusrpanes);
1034  _buf_window->panes(allbufpanes);
1035  COM_assertion_msg(allbufpanes.size() == allusrpanes.size(),
1036  "Different number of panes on buffer and user windows.");
1037 
1038  // 1. Store REAL displacment in disp
1039 
1040  int disp_id = disp->id();
1041  for(int i = 0, ni = allusrpanes.size(); i < ni; ++i){
1042 
1043  const COM::Attribute *old_nc = allusrpanes[i]->attribute(COM::COM_NC);
1044  const COM::Attribute *new_nc = allbufpanes[i]->attribute(COM::COM_NC);
1045  COM::Attribute *p_disp = const_cast<COM::Attribute*>
1046  (allusrpanes[i]->attribute(disp_id));
1047 
1048  COM_assertion_msg((p_disp->size_of_real_items() == new_nc->size_of_real_items()) &&
1049  (p_disp->size_of_real_items() == old_nc->size_of_real_items()),
1050  "Number of real items differs between buffer and user windows");
1051 
1052  double* old_nc_ptr = (double*)old_nc->pointer();
1053  double* new_nc_ptr = (double*)new_nc->pointer();
1054  double* p_disp_ptr = (double*)p_disp->pointer();
1055 
1056  int old_nc_stride = old_nc->stride();
1057  int new_nc_stride = new_nc->stride();
1058  int p_disp_stride = p_disp->stride();
1059 
1060  // Set distances to the next component for each data structure
1061  int old_nc_next_comp;
1062  int new_nc_next_comp;
1063  int p_disp_next_comp;
1064 
1065  if (old_nc_stride == 1)
1066  old_nc_next_comp = old_nc->size_of_items();
1067  else
1068  old_nc_next_comp = 1;
1069 
1070  if (new_nc_stride == 1)
1071  new_nc_next_comp = new_nc->size_of_items();
1072  else
1073  new_nc_next_comp = 1;
1074 
1075  if (p_disp_stride == 1)
1076  p_disp_next_comp = p_disp->size_of_items();
1077  else
1078  p_disp_next_comp = 1;
1079 
1080  // Put displacements for real nodes in p_disp
1081  for(int j = 0, nj = new_nc->size_of_real_items(); j < nj; ++j){
1082 
1083  *p_disp_ptr = *new_nc_ptr - *old_nc_ptr;
1084  *(p_disp_ptr+1*p_disp_next_comp) = *(new_nc_ptr+1*new_nc_next_comp) - *(old_nc_ptr+1*old_nc_next_comp);
1085  *(p_disp_ptr+2*p_disp_next_comp) = *(new_nc_ptr+2*new_nc_next_comp) - *(old_nc_ptr+2*old_nc_next_comp);
1086 
1087  // go to next item
1088  old_nc_ptr += old_nc_stride;
1089  new_nc_ptr += new_nc_stride;
1090  p_disp_ptr += p_disp_stride;
1091  }
1092  }
1093 
1094  // 2. Constrain displacements
1095 
1096  constrain_displacements(disp);
1097 
1098  // 3. Update real NC in disp
1099 
1100  for(int i = 0, ni = allusrpanes.size(); i < ni; ++i){
1101 
1102  const COM::Attribute *old_nc = allusrpanes[i]->attribute(COM::COM_NC);
1103  COM::Attribute *p_disp = const_cast<COM::Attribute*>
1104  (allusrpanes[i]->attribute(disp_id));
1105 
1106  double* old_nc_ptr = (double*)old_nc->pointer();
1107  double* p_disp_ptr = (double*)p_disp->pointer();
1108 
1109  int old_nc_stride = old_nc->stride();
1110  int p_disp_stride = p_disp->stride();
1111 
1112  // Set distances to the next component for each data structure
1113 
1114  int old_nc_next_comp;
1115  int p_disp_next_comp;
1116 
1117  if (old_nc_stride == 1)
1118  old_nc_next_comp = old_nc->size_of_items();
1119  else
1120  old_nc_next_comp = 1;
1121 
1122  if (p_disp_stride == 1)
1123  p_disp_next_comp = p_disp->size_of_items();
1124  else
1125  p_disp_next_comp = 1;
1126 
1127  // Update real part of NC in disp
1128  for(int j = 0, nj = p_disp->size_of_real_items(); j < nj; ++j){
1129 
1130  *p_disp_ptr = *old_nc_ptr + *p_disp_ptr;
1131  *(p_disp_ptr+1*p_disp_next_comp) = *(old_nc_ptr+1*old_nc_next_comp) + *(p_disp_ptr+1*p_disp_next_comp);
1132  *(p_disp_ptr+2*p_disp_next_comp) = *(old_nc_ptr+2*old_nc_next_comp) + *(p_disp_ptr+2*p_disp_next_comp);
1133 
1134  // go to next item
1135  old_nc_ptr += old_nc_stride;
1136  p_disp_ptr += p_disp_stride;
1137  }
1138  }
1139 
1140  // 4. Update ghost part of disp
1141 
1142  Rocmap::update_ghosts(disp);
1143 
1144  // 5. Get displacment
1145 
1146  const COM::Attribute *orig_nc = pmesh->window()->attribute(COM::COM_NC);
1147  Rocblas::sub(disp, orig_nc, disp);
1148 
1149  if(timestep)
1150  Rocblas::div_scalar (disp,(const void*)timestep, disp);
1151 }
1152 
1153 
1154 
1156 #ifdef ROCPROF
1157  Profile_begin("Rocmop::perform_smoothing");
1158 #endif
1159  print_legible(1," Entering Rocmop::perform_smoothing");
1160 
1161  COM_assertion_msg(_buf_window, "Unexpected NULL pointer encountered.");
1162 
1163  // Select iterative or noniterative option depending on the smoother.
1164  if (0) // No noniterative smoothers currently
1165  perform_noniterative_smoothing();
1166  else if( _method < SMOOTH_NONE)
1167  perform_iterative_smoothing();
1168  else
1169  COM_assertion_msg(0, "No valid smoothing method selected");
1170 
1171  print_legible(1," Exiting Rocmop::perform_smoothing");
1172 #ifdef ROCPROF
1173  Profile_end("Rocmop::perform_smoothing");
1174 #endif
1175 }
1176 
1178  // All internal iterative behavior has been removed.
1179 #ifdef ROCPROF
1180  Profile_begin("Rocmop::perform_itersmooth");
1181 #endif
1182 
1183  print_legible(1," Entering Rocmop::perform_iterative_smoothing");
1184 
1185  COM_assertion_msg(_buf_window, "Unexpected NULL pointer encountered.");
1186 
1187  std::vector<const Pane*> allpanes;
1188  _buf_window->panes(allpanes);
1189 
1190 #ifdef MESQUITE
1191 
1192  if(_method==SMOOTH_VOL_MESQ_WG)
1193  {
1194  smooth_vol_mesq_wg();
1195  }
1196  else if(_method==SMOOTH_VOL_MESQ_NG)
1197  {
1198  smooth_vol_mesq_ng();
1199  }
1200 
1201 #else
1202 
1203  if((_method==SMOOTH_VOL_MESQ_WG) || (_method==SMOOTH_VOL_MESQ_NG))
1204  COM_assertion_msg(0,"Rocmop not compiled with MESQUITE");
1205 
1206 #endif
1207 
1208  else COM_assertion_msg(0, "No valid iterative smoothing method selected");
1209 
1210  print_legible(1," Exiting Rocmop::perform_iterative_smoothing");
1211 #ifdef ROCPROF
1212  Profile_end("Rocmop::perform_itersmooth");
1213 #endif
1214 }
1215 
1217 #ifdef ROCPROF
1218  Profile_begin("Rocmop::perform_nonitersmooth");
1219 #endif
1220 
1221  print_legible(1," Entering Rocmop::perform_noniterative_smoothing");
1222 
1223  if(_niter != 1){
1224  std::cerr << "Although the maximum number of iterations > 1 is selected,\n"
1225  << "the smoothing method is noniterative, and will run once.\n";
1226  }
1227 
1228  if (0)
1229  ;// Currently, no noniterative methods exist.
1230  else COM_assertion_msg(0, "No valid noniterative smoothing method selected");
1231 
1232  print_legible(1," Exiting Rocmop::perform_noniterative_smoothing");
1233 #ifdef ROCPROF
1234  Profile_end("Rocmop::perform_nonitersmooth");
1235 #endif
1236 }
1237 
1238 // Perform smoother specific initializing, for example initializing the
1239 // Window_manifold_2 for a surface mesh, adding smoother specific attributes
1240 // to the window, etc.
1242 #ifdef ROCPROF
1243  Profile_begin("Rocmop::perform_smooth_init");
1244 #endif
1245 
1246  print_legible(1," Entering Rocmop::smoother_specific_init");
1247 
1248  // get rid of any old data
1249  if(_wm){ delete _wm; _wm = NULL; }
1250 
1251  // perform initialization common to surface smoothers
1252  if(_method==SMOOTH_SURF_MEDIAL){
1253  // Initialize the Window_manifold
1254  if(_wm == NULL)
1255  Rocsurf::initialize(_buf_window->attribute(_is_pmesh ? COM_PMESH : COM_MESH));
1256  }
1257 
1258  // perform smoother specific initialization
1259  switch (_method){
1260 
1261 #ifdef MESQUITE
1262  case SMOOTH_VOL_MESQ_WG: {
1263  // Obtain a list of elements containing shared nodes for each pane.
1264  determine_shared_border();
1265  if(_invert_tets){
1266  invert_elements(COM::Connectivity::TET4);
1267  _invert_tets = 0;
1268  }
1269  if(_invert_hexes){
1270  invert_elements(COM::Connectivity::HEX8);
1271  _invert_hexes = 0;
1272  }
1273  break;
1274  }
1275  case SMOOTH_VOL_MESQ_NG: {
1276 
1277  // Check to see if the physical surface boundary exists
1278  const std::string surf_attr("is_surface");
1279  const COM::Attribute *w_is_surface = _usr_window->attribute(surf_attr);
1280  if(w_is_surface){
1281 
1282  COM_assertion_msg( COM_compatible_types( w_is_surface->data_type(), COM_INT),
1283  "Surface-list must have integer type");
1284  COM_assertion_msg( w_is_surface->is_nodal() == 1,
1285  "Surface-list must be nodal");
1286  COM_assertion_msg( w_is_surface->size_of_components() == 1,
1287  "Surface-list must have a single component");
1288  COM_assertion_msg( w_is_surface->initialized() == 1,
1289  "Surface-list must be initialized");
1290 
1291  // Clone the attribute
1292  COM::Attribute * new_attr =
1293  _buf_window->inherit( const_cast<COM::Attribute *>(w_is_surface),
1294  surf_attr, COM::Pane::INHERIT_CLONE, true, NULL, 0);
1295  COM_assertion_msg(new_attr, "Attribute could not be allocated.");
1296  }
1297  // else, detect the physical boundary ourselves
1298  else{
1299  COM::Attribute* w_surf_attr =
1300  _buf_window->new_attribute( "is_surface", 'n', COM_INT, 1, "");
1301  _buf_window->resize_array( w_surf_attr, 0);
1302 
1303  determine_physical_border(w_surf_attr);
1304  }
1305  _buf_window->init_done();
1306 
1307  if(_invert_tets)
1308  invert_elements(COM::Connectivity::TET4);
1309  break;
1310  }
1311 #else
1312  case SMOOTH_VOL_MESQ_WG:
1313  case SMOOTH_VOL_MESQ_NG:
1314  COM_assertion_msg(0, "Not compiled with MESQUITE");
1315  break;
1316 #endif
1317 
1318  case SMOOTH_SURF_MEDIAL: {
1319 
1320  // Extend buffer window
1321  COM::Attribute* w_disps =
1322  _buf_window->new_attribute( "disps", 'n', COM_DOUBLE, 3, "");
1323  _buf_window->resize_array( w_disps, 0);
1324 
1325  COM::Attribute* w_facenormals =
1326  _buf_window->new_attribute( "facenormals", 'e', COM_DOUBLE, 3, "");
1327  _buf_window->resize_array( w_facenormals, 0);
1328 
1329  COM::Attribute* w_facecenters =
1330  _buf_window->new_attribute( "facecenters", 'e', COM_DOUBLE, 3, "");
1331  _buf_window->resize_array( w_facecenters, 0);
1332 
1333  COM::Attribute* w_eigvalues =
1334  _buf_window->new_attribute( "lambda", 'n', COM_DOUBLE, 3, "");
1335  _buf_window->resize_array( w_eigvalues, 0);
1336 
1337  COM::Attribute* w_vnormals =
1338  _buf_window->new_attribute( "vnormals", 'n', COM_DOUBLE, 3, "");
1339  _buf_window->resize_array( w_vnormals, 0);
1340 
1341  COM::Attribute* w_awnormals =
1342  _buf_window->new_attribute( "awnormals", 'n', COM_DOUBLE, 3, "");
1343  _buf_window->resize_array( w_awnormals, 0);
1344 
1345  COM::Attribute* w_uwnormals =
1346  _buf_window->new_attribute( "uwnormals", 'n', COM_DOUBLE, 3, "");
1347  _buf_window->resize_array( w_uwnormals, 0);
1348 
1349  COM::Attribute* w_eigvecs =
1350  _buf_window->new_attribute( "eigvecs", 'n', COM_DOUBLE, 9, "");
1351  _buf_window->resize_array( w_eigvecs, 0);
1352 
1353  COM::Attribute* w_tangranks =
1354  _buf_window->new_attribute( "tangranks", 'n', COM_INT, 1, "");
1355  _buf_window->resize_array( w_tangranks, 0);
1356 
1357  COM::Attribute* w_cntnranks =
1358  _buf_window->new_attribute( "cntnranks", 'n', COM_INT, 1, "");
1359  _buf_window->resize_array( w_cntnranks, 0);
1360 
1361  COM::Attribute* w_cntnvecs =
1362  _buf_window->new_attribute( "cntnvecs", 'n', COM_DOUBLE, 6, "");
1363  _buf_window->resize_array( w_cntnvecs, 0);
1364 
1365  COM::Attribute* w_scales =
1366  _buf_window->new_attribute( "scales", 'n', COM_DOUBLE, 1, "");
1367  _buf_window->resize_array( w_scales, 0);
1368 
1369  COM::Attribute* w_weights =
1370  _buf_window->new_attribute( "weights", 'n', COM_DOUBLE, 1, "");
1371  _buf_window->resize_array( w_weights, 0);
1372 
1373  COM::Attribute* w_weights2 =
1374  _buf_window->new_attribute( "weights2", 'n', COM_DOUBLE, 1, "");
1375  _buf_window->resize_array( w_weights2, 0);
1376 
1377  COM::Attribute* w_barycrds =
1378  _buf_window->new_attribute( "barycrds", 'n', COM_DOUBLE, 2, "");
1379  _buf_window->resize_array( w_barycrds, 0);
1380 
1381  COM::Attribute* w_PNelemids =
1382  _buf_window->new_attribute( "PNelemids", 'n', COM_INT, 1, "");
1383  _buf_window->resize_array( w_PNelemids, 0);
1384 
1385  // Extend the buffer window to hold local contributions to new placement
1386  // and the number of contributing faces for Laplacian smoothing.
1387  COM::Attribute * w_pnt_contrib =
1388  _buf_window->new_attribute("pnt_contrib", 'n', COM_DOUBLE, 3, "");
1389  _buf_window->resize_array(w_pnt_contrib, 0);
1390 
1391  COM::Attribute * w_disp_count =
1392  _buf_window->new_attribute("disp_count", 'n', COM_DOUBLE, 1, "");
1393  _buf_window->resize_array(w_disp_count, 0);
1394 
1395  _buf_window->init_done();
1396 
1397  break;
1398  }
1399  // case SMOOTH_LAPLACE : {
1400  //break;
1401  //}
1402  default:
1403  COM_assertion_msg(0, "Can't initialize for invalid smoother.");
1404  break;
1405  }
1406 
1407  COM_assertion_msg(_buf_window, "Unexpected NULL pointer encountered.");
1408 
1409  print_legible(1," Exiting Rocmop::smoother_specific_init");
1410 #ifdef ROCPROF
1411  Profile_end("Rocmop::perform_smooth_init");
1412 #endif
1413 }
1414 
1415 void Rocmop::set_value(const char* opt, const void* value)
1416 {
1417 
1418  //print_legible(0,"Entering Rocmop::set_value");
1419 
1420  COM_assertion_msg( validate_object()==0, "Invalid object");
1421 
1422  COM_assertion_msg( opt && value,
1423  "Rocmop::set_value does not except NULL parameters");
1424  std::string option;
1425  if(opt) option = opt;
1426  if ( option == "method") {
1427  COM_assertion_msg( *((int*)value) <= SMOOTH_NONE && *((int*)value)>=0
1428  ,"Illegal value for 'method' option");
1429  _method = *((int*)value);
1430  }
1431  else if ( option == "wrapper"){
1432  int wrapper = *((int*)value);
1433  COM_assertion_msg( wrapper < WRAPPER_MAX && wrapper >= 0
1434  , "Illegal value for 'wrapper' option");
1435  _wrapper = wrapper;
1436  }
1437  else if ( option == "verbose"){
1438  _verb = *((int*)value); }
1439  else if ( option == "lazy"){
1440  _lazy = *((int*)value); }
1441  else if ( option == "tol"){
1442  COM_assertion_msg( *((float*)value) <= 180. && *((float*)value)>=0.
1443  ,"Illegal value for 'tol' option");
1444  _tol = *((float*)value); }
1445  else if ( option == "maxdisp"){
1446  COM_assertion_msg( *((float*)value)>0.
1447  ,"Illegal value for 'maxdisp' option");
1448  _maxdisp = *((float*)value); }
1449  else if ( option == "niter"){
1450  _niter = *((int*)value); }
1451  else if ( option == "ctol"){
1452  COM_assertion_msg( *((float*)value) <= 1. && *((float*)value)>=0.
1453  ,"Illegal value for '_ctol' option");
1454  _ctol = *((float*)value); }
1455  else if ( option == "ncycle"){
1456  _ncycle = *((int*)value); }
1457  else if ( option == "inverted"){
1458  _invert_tets = *((int*)value);
1459  }
1460  else if ( option == "invert_tets"){
1461  _invert_tets = *((int*)value);
1462  }
1463  else if ( option == "invert_hexes"){
1464  _invert_hexes = *((int*)value);
1465  }
1466  else COM_assertion_msg( false, "Unknown option");
1467 
1468  //print_legible(1,"Exiting Rocmop::set_value");
1469 }
1470 
1471 void Rocmop::smooth_boeing(COM::Attribute* att, int* niter){
1472  /*
1473  std::vector<Pane*> allpanes;
1474  att->window()->panes(allpanes);
1475 
1476  COM_assertion_msg(allpanes.size() == 1,
1477  "This function only supports winows with a single pane\n");
1478 
1479  MesqPane mp(allpanes[0],false);
1480 
1481  if(_wrapper == WRAPPER_SHAPE){
1482 
1483  Mesquite::MsqError err;
1484  ShapeImprovementWrapper mesh_quality_algorithm(err);
1485  MSQ_ERRRTN(err);
1486  for(int i=0; i< *niter; ++i){
1487  mesh_quality_algorithm.run_instructions(&mp,err);
1488  MSQ_ERRRTN(err);
1489  }
1490  }
1491  else if(_wrapper == WRAPPER_BOEING){
1492  Mesquite::MsqError err;
1493  CGWrapper mesh_quality_algorithm(err);
1494  MSQ_ERRRTN(err);
1495  for(int i=0; i< *niter; ++i){
1496  mesh_quality_algorithm.run_instructions(&mp,err);
1497  MSQ_ERRRTN(err);
1498  }
1499  }
1500  */
1501 }
1502 
1503 void Rocmop::smooth_mesquite(std::vector<COM::Pane*> &allpanes,
1504  int ghost_level){
1505 
1506 #ifdef ROCPROF
1507  Profile_begin("Rocmop::smooth_mesquite");
1508 #endif
1509  Mesquite::MsqError err;
1510  ShapeImprovementWrapper mesh_quality_algorithm(err);
1511 
1512  int total_npanes = (int)allpanes.size();
1513  bool wg = (ghost_level == 0) ? false : true;
1514 
1515  // std::cout << "wg for Rocmop 114 is: " << wg << std::endl;
1516 
1517  for(int j=0; j < total_npanes; ++j){
1518  MesqPane mp(allpanes[j],wg);
1519  MeshSet mesh_set1;
1520  if(_verb > 4)
1521  mp.set_verb(_verb - 4);
1522 
1523  mesh_set1.add_mesh(&mp, err);
1524  MSQ_ERRRTN(err);
1525 #ifdef ROCPROF
1526  Profile_begin("Rocmop::Mesquite");
1527 #endif
1528  mesh_quality_algorithm.run_instructions(mesh_set1,err);
1529 #ifdef ROCPROF
1530  Profile_end("Rocmop::Mesquite");
1531 #endif
1532  MSQ_ERRRTN(err);
1533  }
1534 #ifdef ROCPROF
1535  Profile_end("Rocmop::smooth_mesquite");
1536 #endif
1537 }
1538 
1539 void Rocmop::reduce_sum_on_shared_nodes(COM::Attribute *att){
1540  Pane_communicator pc(att->window(), att->window()->get_communicator());
1541  pc.init(att);
1542  pc.begin_update_shared_nodes();
1543  pc.reduce_on_shared_nodes(MPI_SUM);
1544  pc.end_update_shared_nodes();
1545 }
1546 
1548 #ifdef ROCPROF
1549  Profile_begin("Rocmop::pane_border");
1550 #endif
1551 
1552  print_legible(1,"Entering Rocmop::determine_pane_border");
1553 
1554  std::vector<const COM::Pane*> allpanes;
1555  _buf_window->panes(allpanes);
1556  int local_npanes = (int)allpanes.size();
1557 
1558  _is_pane_bnd_node.resize(local_npanes);
1559  _is_pane_bnd_elem.resize(local_npanes);
1560 
1561  for(int i=0; i< local_npanes; ++i){
1562  int size_of_real_nodes = allpanes[i]->size_of_real_nodes();
1563  int size_of_real_elems = allpanes[i]->size_of_real_elements();
1564  _is_pane_bnd_node[i].resize(size_of_real_nodes,0);
1565  _is_pane_bnd_elem[i].resize(size_of_real_elems,0);
1566 
1567  std::vector<bool> is_isolated; // is a node isolated?
1568  MAP::Pane_boundary pb (allpanes[i]);
1569  pb.determine_border_nodes(_is_pane_bnd_node[i], is_isolated);
1570  }
1571 
1572  mark_elems_from_nodes(_is_pane_bnd_node,_is_pane_bnd_elem);
1573 
1574  print_legible(1,"Exiting Rocmop::determine_pane_border");
1575 #ifdef ROCPROF
1576  Profile_end("Rocmop::pane_border");
1577 #endif
1578 }
1579 
1580 
1582 #ifdef ROCPROF
1583  Profile_begin("Rocmop::shared_border");
1584 #endif
1585 
1586  print_legible(1,"Entering Rocmop::determine_shared_nodes");
1587 
1588  std::vector<const COM::Pane*> allpanes;
1589  _buf_window->panes(allpanes);
1590  int local_npanes = (int)allpanes.size();
1591 
1592  _is_shared_node.resize(local_npanes);
1593 
1594  //First, get the list of shared nodes.
1595  for(int i=0; i < (int)(local_npanes); ++i){
1596  // Obtain the pane connectivity of the local pane.
1597  const COM::Attribute *pconn = allpanes[i]->attribute(COM::COM_PCONN);
1598  // Use the pconn offset
1599  const int *vs = (const int*)pconn->pointer()+Pane_connectivity::pconn_offset();
1600  int vs_size=pconn->size_of_real_items()-Pane_connectivity::pconn_offset();
1601  _is_shared_node[i].resize(allpanes[i]->size_of_real_nodes(),0);
1602 
1603  // Determine the number of communicating panes for shared nodes.
1604  int count=0;
1605  for (int j=0, nj=vs_size; j<nj; j+=vs[j+1]+2) {
1606  if (_buf_window->owner_rank( vs[j]) >=0) ++count;
1607  }
1608 
1609  int index = 0;
1610  // Loop through communicating panes for shared nodes.
1611  for ( int j=0; j<count; ++j, index+=vs[index+1]+2) {
1612  // We skip the panes that are not in the current window
1613  while ( _buf_window->owner_rank(vs[index])<0) {
1614  index+=vs[index+1]+2;
1615  COM_assertion_msg( index<=vs_size, "Invalid communication map");
1616  }
1617  // Add shared nodes to the list
1618  for(int k=0; k<vs[index+1]; ++k){
1619  _is_shared_node[i][vs[index+2+k]-1] = 1;
1620  }
1621  }
1622  }
1623 
1624  mark_elems_from_nodes(_is_shared_node,_is_shared_elem);
1625 
1626  print_legible(1,"Exiting Rocmop::determine_shared_nodes");
1627 #ifdef ROCPROF
1628  Profile_end("Rocmop::shared_border");
1629 #endif
1630 }
1631 
1633 #ifdef ROCPROF
1634  Profile_begin("Rocmop::phys_border");
1635 #endif
1636  print_legible(1,"Entering Rocmop::determine_physical_border()");
1637 
1638  const std::string surf_attr("is_surface");
1639  COM::Attribute* w_is_surface = _buf_window->attribute(surf_attr);
1640  COM_assertion_msg( w_is_surface, "Unexpected NULL pointer");
1641  int is_surface_id = w_is_surface->id();
1642 
1643  std::vector<const COM::Pane*> allpanes;
1644  _buf_window->panes(allpanes);
1645  int local_npanes = (int)allpanes.size();
1646 
1647  _is_phys_bnd_node.resize(local_npanes);
1648 
1649  for(int i=0; i < local_npanes; ++i){
1650  _is_phys_bnd_node[i].resize(allpanes[i]->size_of_real_nodes());
1651 
1652  // get pane level pointer to physical border property.
1653  const COM::Attribute *p_is_surface = allpanes[i]->attribute(is_surface_id);
1654  int *is_surface_ptr = (int*)p_is_surface->pointer();
1655 
1656  // loop through real nodes
1657  for(int j=0, nj =(int) allpanes[i]->size_of_real_nodes();j<nj; ++j){
1658  if (is_surface_ptr[j])
1659  _is_phys_bnd_node[i][j] = true;
1660  }
1661  }
1662 
1663  mark_elems_from_nodes(_is_phys_bnd_node,_is_phys_bnd_elem);
1664 
1665 
1666  print_legible(1,"Exiting Rocmop::determine_physical_border()");
1667 #ifdef ROCPROF
1668  Profile_end("Rocmop::phys_border");
1669 #endif
1670 }
1671 
1672 void Rocmop::mark_elems_from_nodes(std::vector<std::vector<bool> > &marked_nodes,
1673  std::vector<std::vector<bool> > &marked_elems){
1674 #ifdef ROCPROF
1675  Profile_begin("Rocmop::mark_elem_node");
1676 #endif
1677 
1678  print_legible(1,"Entering Rocmop::mark_elems_from_nodes");
1679 
1680  std::vector<const COM::Pane*> allpanes;
1681  _buf_window->panes(allpanes);
1682  int local_npanes = (int)allpanes.size();
1683 
1684  marked_elems.clear();
1685  marked_elems.resize(local_npanes);
1686 
1687  //Loop through panes
1688  for(int i=0; i < (int)(local_npanes); ++i){
1689 
1690  marked_elems[i].clear();
1691  marked_elems[i].resize(allpanes[i]->size_of_real_elements(),false);
1692 
1693  // Loop through real elements.
1694  // Mark for quality check if they contain shared nodes.
1695  int s_real_elems = allpanes[i]->size_of_real_elements();
1696  std::vector<int> nodes;
1697  for(int j=1; j<= s_real_elems; ++j){
1698  Element_node_enumerator ene(allpanes[i],j);
1699  ene.get_nodes(nodes);
1700  for(int k=0, nk=nodes.size(); k<nk; ++k){
1701  if (marked_nodes[i][nodes[k]-1])
1702  marked_elems[i][j-1] = true;
1703  }
1704  }
1705  }
1706 
1707  print_legible(1,"Exiting Rocmop::mark_elems_from_nodes");
1708 #ifdef ROCPROF
1709  Profile_end("Rocmop::mark_elem_node");
1710 #endif
1711 }
1712 
1713 void Rocmop::invert_elements(int conn_type){
1714 #ifdef ROCPROF
1715  Profile_begin("Rocmop::invert_elements");
1716 #endif
1717  print_legible(1,"Entering Rocmop::invert_elements");
1718  std::vector<Pane*> allpanes;
1719  _buf_window->panes(allpanes);
1720  for(int i=0, ni = allpanes.size(); i<ni; ++i){
1721  MesqPane* mp = new MesqPane(allpanes[i]);
1722  mp->invert();
1723  //mp->invert(conn_type);
1724  if(mp)
1725  delete mp;
1726  mp = NULL;
1727  }
1728  print_legible(1,"Exiting Rocmop::invert_elements");
1729 #ifdef ROCPROF
1730  Profile_end("Rocmop::invert_tets");
1731 #endif
1732 }
1733 
1734 double Rocmop::check_marked_elem_quality(std::vector<std::vector<bool> > &marked_elems,
1735  std::vector<COM::Pane*> &allpanes){
1736 #ifdef ROCPROF
1737  Profile_begin("Rocmop::check_marked_quality");
1738 #endif
1739  print_legible(1,"Entering Rocmop::check_marked_elems");
1740 
1741  double worst_angle = 0.0;
1742  double angles[] = {0.0, 0.0};
1743  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1744  for(int k =0,nk=allpanes[i]->size_of_real_elements(); k<nk; ++k){
1745  if(marked_elems[i][k]){
1746  Element_node_enumerator ene(allpanes[i],k+1);
1747  Angle_Metric_3 am;
1748  am.initialize(ene);
1749  am.compute(angles);
1750  if(angles[1]>worst_angle)
1751  worst_angle = angles[1];
1752  }
1753  }
1754  }
1755  return worst_angle;
1756 
1757  print_legible(1,"Exiting Rocmop::check_marked_elems");
1758 #ifdef ROCPROF
1759  Profile_end("Rocmop::check_marked_quality");
1760 #endif
1761 }
1762 
1763 double Rocmop::check_all_elem_quality(std::vector<const COM::Pane*> &allpanes,
1764  bool with_ghosts){
1765 
1766 #ifdef ROCPROF
1767  Profile_begin("Rocmop::all_quality_const");
1768 #endif
1769  print_legible(1,"Entering Rocmop::check_all_elem_quality");
1770 
1771  int rank =0;
1772  int ierr = MPI_Comm_rank( _buf_window->get_communicator(),
1773  &rank); assert( ierr == 0);
1774  double worst_angle = 0.0;
1775  double angles[] = {0.0, 0.0};
1776  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1777  int nk=allpanes[i]->size_of_real_elements();
1778  if(with_ghosts)
1779  nk = allpanes[i]->size_of_elements();
1780  for(int k =0; k<nk; ++k){
1781  Element_node_enumerator ene(allpanes[i],k+1);
1782  Angle_Metric_3 am;
1783  am.initialize(ene);
1784  am.compute(angles);
1785  if(angles[1]>worst_angle)
1786  worst_angle = angles[1];
1787  }
1788  }
1789 
1790  agree_double(worst_angle, MPI_MAX);
1791 
1792 #ifdef ROCPROF
1793  Profile_end("Rocmop::all_quality_const");
1794 #endif
1795  return worst_angle;
1796 
1797  print_legible(1,"Exiting Rocmop::check_all_elem_quality");
1798 }
1799 
1800 double Rocmop::check_all_elem_quality(std::vector<COM::Pane*> &allpanes,
1801  bool with_ghosts){
1802 #ifdef ROCPROF
1803  Profile_begin("Rocmop::all_quality");
1804 #endif
1805 
1806  print_legible(1,"Entering Rocmop::check_all_elem_quality");
1807 
1808  if(COMMPI_Initialized()){
1809  int rank =0;
1810  int ierr = MPI_Comm_rank( _buf_window->get_communicator(),
1811  &rank); assert( ierr == 0);
1812  }
1813 
1814  double worst_angle = 0.0;
1815  double angles[] = {0.0, 0.0};
1816  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1817  int nk=allpanes[i]->size_of_real_elements();
1818  if(with_ghosts){
1819  nk = allpanes[i]->size_of_elements();
1820  }
1821  for(int k =0; k<nk; ++k){
1822  Element_node_enumerator ene(allpanes[i],k+1);
1823  Angle_Metric_3 am;
1824  am.initialize(ene);
1825  am.compute(angles);
1826 
1827  if(angles[1]>worst_angle)
1828  worst_angle = angles[1];
1829  }
1830  }
1831 #ifdef ROCPROF
1832  Profile_end("Rocmop::all_quality");
1833 #endif
1834 
1835  return worst_angle;
1836 
1837  print_legible(1,"Exiting Rocmop::check_all_elem_quality");
1838 }
1839 
1840 void Rocmop::print_legible(int verb, const char *msg){
1841  if(_verb > verb){
1842 
1843  int rank =0;
1844 
1845  if(COMMPI_Initialized()){
1846  int ierr = MPI_Comm_rank( _buf_window->get_communicator(),
1847  &rank);
1848  assert( ierr == 0);
1849  }
1850 
1851  if (rank==0)
1852  std::cout << "Rocmop: " << msg << std::endl;
1853  }
1854 }
1855 
1856 void Rocmop::constrain_displacements(COM::Attribute * w_disp){
1857 #ifdef ROCPROF
1858  Profile_begin("Rocmop::const_disp");
1859 #endif
1860 
1861  if(_maxdisp > 0.0){
1862 
1863  int disp_id = w_disp->id();
1864  double max_norm = 0.0;
1865 
1866  std::vector<Pane*> allpanes;
1867  const_cast<COM::Window*>(_usr_window)->panes(allpanes);
1868 
1869  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1870 
1871  Vector_3<double> *ptr = NULL;
1872  COM::Attribute* ptr_att = allpanes[i]->attribute(disp_id);
1873  void* void_ptr = ptr_att->pointer();
1874  ptr = reinterpret_cast<Vector_3<double>*>(void_ptr);
1875 
1876  for(int j=0,nj = allpanes[i]->size_of_real_nodes(); j<nj; ++j){
1877  double norm = ptr[j].norm();
1878  if(norm > max_norm)
1879  max_norm = norm;
1880  }
1881  }
1882 
1883  agree_double(max_norm,MPI_MAX);
1884 
1885  if(max_norm > _maxdisp){
1886  double div = max_norm/_maxdisp;
1887  Rocblas::div_scalar(const_cast<const COM::Attribute*>(w_disp),&div,w_disp);
1888  }
1889  }
1890 #ifdef ROCPROF
1891  Profile_end("Rocmop::const_disp");
1892 #endif
1893 }
1894 
1895 void Rocmop::print_extremal_dihedrals(COM::Window * window){
1896 #ifdef ROCPROF
1897  Profile_begin("Rocmop::ext_dihedrals");
1898 #endif
1899 
1900  // Find the rank of this processor, making sure to only make
1901  // MPI calls on parallel runs
1902  int myrank =0;
1903  if(COMMPI_Initialized()){ // true if in parallel
1904  int ierr = MPI_Comm_rank( window->get_communicator(),
1905  &myrank);
1906  assert( ierr == 0);
1907  }
1908 
1909  // Calculate extremal angles on local panes, and
1910  // record their locations by pane id and element id
1911 
1912  double max_angle = 0.0;
1913  double min_angle = 180.0;
1914  int max_pane = -1; // id of pane w/ the largest dihedral angle
1915  int min_pane = -1; // id of pane w/ the smallest dihedral angle
1916  int max_elem = -1; // id of element w/ the largest dihedral angle
1917  int min_elem = -1; // id of element w/ the smallest dihedral angle
1918  double angles[] = {0.0, 0.0};
1919 
1920  std::vector<Pane*> allpanes;
1921  window->panes(allpanes);
1922 
1923  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1924  for(int k =0,nk=allpanes[i]->size_of_real_elements(); k<nk; ++k){
1925  Element_node_enumerator ene(allpanes[i],k+1);
1926  Angle_Metric_3 am;
1927  am.initialize(ene);
1928  am.compute(angles);
1929  if(angles[1]>max_angle){
1930  max_angle = angles[1];
1931  max_pane = allpanes[i]->id();
1932  max_elem = k+1;
1933  }
1934  if(angles[0]<min_angle){
1935  min_angle = angles[0];
1936  min_pane = allpanes[i]->id();
1937  min_elem = k+1;
1938  }
1939  }
1940  }
1941 
1942  // Find minimum angle across all panes.
1943 
1944  // create MPI_DOUBLE_INT data types for send/recv buffs
1945  struct {
1946  double value;
1947  int rank;
1948  } send, recv;
1949  send.value = min_angle;
1950  send.rank = myrank;
1951 
1952  if(COMMPI_Initialized()){
1953  MPI_Allreduce(&send,&recv,1,MPI_DOUBLE_INT,MPI_MINLOC,
1954  window->get_communicator());
1955  }
1956  if(recv.rank == myrank && _verb > 1){
1957  std::cout << "Rocmop:" << std::endl << "Rocmop: "
1958  << std::setw(10) << min_angle << " on element "
1959  << min_elem << " of pane " << min_pane
1960  << "." << std::endl;
1961  }
1962 
1963  // Sync. output.
1964  if(COMMPI_Initialized()){
1965  MPI_Barrier(window->get_communicator());
1966  }
1967 
1968  // Find maximum angle across all panes.
1969 
1970  send.value = max_angle;
1971 
1972  if(COMMPI_Initialized()){
1973  MPI_Allreduce(&send,&recv,1,MPI_DOUBLE_INT,MPI_MAXLOC,
1974  window->get_communicator());
1975  }
1976  if(recv.rank == myrank && _verb > 1){
1977  std::cout << "Rocmop:" << std::endl << "Rocmop: "
1978  << std::setw(10) << max_angle << " on element "
1979  << max_elem << " of pane " << max_pane << std::endl;
1980  }
1981  // Sync. output.
1982  if(COMMPI_Initialized()){
1983  MPI_Barrier(window->get_communicator());
1984  }
1985 #ifdef ROCPROF
1986  Profile_end("Rocmop::ext_dihedrals");
1987 #endif
1988 
1989 }
1990 
1991 void Rocmop::obtain_extremal_dihedrals(const COM::Attribute *att, double *min_angle, double *max_angle){
1992 
1993  const COM::Window *win = att->window();
1994 
1995  bool cominit = COMMPI_Initialized();
1996 
1997  int rank =0;
1998  if(cominit){
1999  int ierr = MPI_Comm_rank( win->get_communicator(),
2000  &rank); assert( ierr == 0);
2001  }
2002 
2003  std::vector<const Pane*> allpanes;
2004  win->panes(allpanes);
2005 
2006  max_angle[0] = 0.0;
2007  min_angle[0] = 180.0;
2008  double angles[] = {0.0, 0.0};
2009 
2010  for(int i=0,ni = allpanes.size(); i<ni; ++i){
2011  for(int k =0,nk=allpanes[i]->size_of_real_elements(); k<nk; ++k){
2012  Element_node_enumerator ene(allpanes[i],k+1);
2013  Angle_Metric_3 am;
2014  am.initialize(ene);
2015  am.compute(angles);
2016 
2017  if(angles[1]>max_angle[0])
2018  max_angle[0] = angles[1];
2019  if(angles[0]<min_angle[0])
2020  min_angle[0] = angles[0];
2021  }
2022  }
2023 
2024  if(cominit){
2025  double temp = max_angle[0];
2026  MPI_Allreduce(&max_angle[0], &temp, 1, MPI_DOUBLE, MPI_MAX,
2027  win->get_communicator());
2028  max_angle[0] = temp;
2029 
2030  temp = min_angle[0];
2031  MPI_Allreduce(&min_angle[0], &temp, 1, MPI_DOUBLE, MPI_MIN,
2032  win->get_communicator());
2033  min_angle[0] = temp;
2034  }
2035 }
2036 
2037 void Rocmop::print_quality(std::string &s,const std::string &s2){
2038 
2039  string outstr("angles.txt");
2040 
2041 
2042  ofstream file;
2043  ofstream file2;
2044 
2045  bool cominit = COMMPI_Initialized();
2046 
2047  int rank =0;
2048  if(cominit){
2049  int ierr = MPI_Comm_rank( _buf_window->get_communicator(),
2050  &rank); assert( ierr == 0);
2051  }
2052 
2053  std::vector<Pane*> allpanes;
2054  _buf_window->panes(allpanes);
2055 
2056  double max_angle = 0.0;
2057  double min_angle = 180.0;
2058  double angles[] = {0.0, 0.0};
2059 
2060  file2.open(s2.c_str());
2061  for(int i=0,ni = allpanes.size(); i<ni; ++i){
2062  for(int k =0,nk=allpanes[i]->size_of_real_elements(); k<nk; ++k){
2063  Element_node_enumerator ene(allpanes[i],k+1);
2064  Angle_Metric_3 am;
2065  am.initialize(ene);
2066  am.compute(angles);
2067  file2 << angles[0] << " " << angles[1] << std::endl;
2068  if(angles[1]>max_angle)
2069  max_angle = angles[1];
2070  if(angles[0]<min_angle)
2071  min_angle = angles[0];
2072  }
2073  }
2074  file2.close();
2075 
2076  agree_double(max_angle,MPI_MAX);
2077  agree_double(min_angle,MPI_MIN);
2078 
2079  if (rank==0){
2080  file.open(outstr.c_str(), std::ios::app);
2081  COM_assertion_msg( file, "File failed to open\n");
2082  file << std::left << std::setw(30) << s << std::setw(0)
2083  << "(" << min_angle << " , " << max_angle << ")\n";
2084  file.close();
2085  }
2086 }
2087 
2088 void Rocmop::print_mquality(std::string &s,
2089  std::vector<std::vector<bool> > &to_check){
2090 
2091  int ierr = 0, rank =0;
2092 
2093  if(COMMPI_Initialized()){
2094  ierr = MPI_Comm_rank( _buf_window->get_communicator()
2095  , &rank);
2096  }
2097  assert( ierr == 0);
2098 
2099 
2100  std::vector<std::vector<bool> > elem_to_check;
2101  mark_elems_from_nodes(to_check, elem_to_check);
2102 
2103  std::vector<Pane*> allpanes;
2104  _buf_window->panes(allpanes);
2105 
2106  double max_angle = 0.0;
2107  double min_angle = 180.0;
2108  double angles[] = {0.0, 0.0};
2109  int id = -1;
2110  for(int i=0,ni = allpanes.size(); i<ni; ++i){
2111  for(int k =0,nk = elem_to_check[i].size(); k<nk; ++k){
2112  if(elem_to_check[i][k]){
2113  Element_node_enumerator ene(allpanes[i],k+1);
2114  Angle_Metric_3 am;
2115  am.initialize(ene);
2116  am.compute(angles);
2117  if(angles[1]>max_angle)
2118  max_angle = angles[1];
2119  if(angles[0]<min_angle){
2120  id = k;
2121  min_angle = angles[0];
2122  }
2123  }
2124  }
2125  }
2126 
2127  double temp = min_angle;
2128 
2129  agree_double(max_angle,MPI_MAX);
2130  agree_double(min_angle,MPI_MIN);
2131 
2132  if (rank==0){
2133  string outstr("angles.txt");
2134  ofstream file (outstr.c_str(), std::ios::app);
2135  COM_assertion_msg( file, "File failed to open\n");
2136 
2137  file << std::left << std::setw(30) << s << std::setw(0)
2138  << "(" << min_angle << " , " << max_angle << ")";
2139 
2140  if(_verb > 1)
2141  std::cout << std::left << std::setw(30) << "Rocmop: " << s
2142  << std::setw(0) << "(" << min_angle << " , "
2143  << max_angle << ")" << std::endl;
2144 
2145  file.close();
2146  }
2147 
2148  if(COMMPI_Initialized())
2149  ierr = MPI_Barrier(_buf_window->get_communicator());
2150  assert( ierr == 0);
2151 
2152  if(min_angle == temp){
2153 
2154  string outstr("angles.txt");
2155  ofstream file (outstr.c_str(), std::ios::app);
2156  COM_assertion_msg( file, "File failed to open\n");
2157 
2158  file << " worst = (" << rank << " , " << id << ")\n";
2159  file.close();
2160  }
2161 
2162  if(COMMPI_Initialized())
2163  ierr = MPI_Barrier(_buf_window->get_communicator());
2164  assert( ierr == 0);
2165 }
2166 
2168 #ifdef ROCPROF
2169  Profile_begin("Rocmop::perturb_stat");
2170 #endif
2171  // first calculate current quality of all nodes.
2172  std::vector<const Pane*> allpanes;
2173  std::vector<const Pane*> allpanes_usr;
2174  _buf_window->panes(allpanes);
2175  _usr_window->panes(allpanes_usr);
2176 
2177  COM::Attribute *w_fgpn_bnd =
2178  _buf_window->attribute("is_fgpn_bnd");
2179  COM::Attribute *w_qual_b_perturb =
2180  _buf_window->attribute("qual_b_perturb");
2181  COM::Attribute *w_qual_a_perturb =
2182  _buf_window->attribute("qual_a_perturb");
2183 
2184  double angles[] = {0.0, 0.0};
2185 
2186  // Get worst quality on local panes
2187  for(int i=0,ni=allpanes.size(); i<ni; ++i){
2188 
2189  COM::Attribute *p_fgpn_bnd =
2190  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_fgpn_bnd->id()));
2191  COM::Attribute *p_qual_b_perturb =
2192  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_qual_b_perturb->id()));
2193 
2194  int* fgpn_bnd_ptr = reinterpret_cast<int*>(p_fgpn_bnd->pointer());
2195  double* qual_b_perturb_ptr =
2196  reinterpret_cast<double*>(p_qual_b_perturb->pointer());
2197 
2198  std::vector<int> elist;
2199  // only worry about real nodes, ghost nodes should be fixed
2200  for(int j=0, nj= allpanes[i]->size_of_real_nodes(); j<nj; ++j){
2201  if(fgpn_bnd_ptr[j]){
2202  _dcs[i]->incident_elements(j+1,elist);
2203  qual_b_perturb_ptr[j] = 0.0;
2204  for(uint k=0, nk=elist.size(); k<nk; ++k){
2205  Element_node_enumerator ene(allpanes[i],k+1);
2206  Angle_Metric_3 am;
2207  am.initialize(ene);
2208  am.compute(angles);
2209  if(angles[1]>qual_b_perturb_ptr[j])
2210  qual_b_perturb_ptr[j] = angles[1];
2211  }
2212  }
2213  }
2214  }
2215 
2216  // Get the worst quality across all panes
2217  if(COMMPI_Initialized()){
2218  MAP::Pane_communicator pc(_buf_window, _buf_window->get_communicator());
2219  pc.init(w_qual_b_perturb);
2220  pc.begin_update_shared_nodes();
2221  pc.reduce_on_shared_nodes(MPI_MAX);
2222  pc.end_update_shared_nodes();
2223  }
2224 
2225  // Now generate random perturbations
2226  for(int i=0,ni=allpanes.size(); i<ni; ++i){
2227 
2228  COM::Attribute *p_fgpn_bnd =
2229  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_fgpn_bnd->id()));
2230  COM::Attribute *p_nc =
2231  const_cast<COM::Attribute*>(allpanes[i]->attribute(COM::COM_NC));
2232 
2233  int* fgpn_bnd_ptr =
2234  reinterpret_cast<int*>(p_fgpn_bnd->pointer());
2235  Vector_3<double>* nc_ptr =
2236  reinterpret_cast<Vector_3<double>*>(p_nc->pointer());
2237 
2238  std::vector<int> elist;
2239  // only worry about real nodes, ghost nodes should be fixed
2240  for(int j=0, nj= (int)allpanes[i]->size_of_real_nodes(); j<nj; ++j){
2241 
2242  if(fgpn_bnd_ptr[j]){
2243  _dcs[i]->incident_elements(j+1,elist);
2244 
2245  if(_verb > 1)
2246  std::cout << "Rocmop: Perturbing node " << j+1 << std::endl;
2247 
2248  //select a random element
2249  int rand_el = (std::rand()%elist.size());
2250  Element_node_enumerator ene(allpanes[i],elist[rand_el]);
2251  std::vector<int> enodes;
2252  ene.get_nodes(enodes);
2253 
2254  // get length of a randomly selected incident edge of the element
2255  int rand_ed = (std::rand()%3)+1;
2256  int nindex = 0;
2257  for(int nk= (int)enodes.size(); nindex<nk; ++nindex){
2258  if(enodes[nindex]==j+1)
2259  break;
2260  }
2261 
2262  COM_assertion_msg((nindex>=0 && nindex<= (int)enodes.size()),
2263  "Node not found in supposedly adjacent element\n");
2264  double length = (nc_ptr[j]-nc_ptr[enodes[(nindex+rand_ed)%4]-1]).norm();
2265 
2266  Vector_3<double> perturb(length,length,length);
2267  for(int k=0; k<3; ++k){
2268  perturb[0] *= (std::rand()%2 == 0) ?
2269  (double)((std::rand()%1000)+1)/1000.0 :
2270  -1.0*((double)((std::rand()%1000)+1)/1000.0);
2271  }
2272  nc_ptr[j] += perturb;
2273  }
2274  }
2275  }
2276 
2277  // Get perturbed worst quality on local panes
2278  for(int i=0,ni=(int)allpanes.size(); i<ni; ++i){
2279 
2280  COM::Attribute *p_fgpn_bnd =
2281  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_fgpn_bnd->id()));
2282  COM::Attribute *p_qual_a_perturb =
2283  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_qual_a_perturb->id()));
2284 
2285  int* fgpn_bnd_ptr =
2286  reinterpret_cast<int*>(p_fgpn_bnd->pointer());
2287  double* qual_a_perturb_ptr =
2288  reinterpret_cast<double*>(p_qual_a_perturb->pointer());
2289 
2290  std::vector<int> elist;
2291  // only worry about real nodes, ghost nodes should be fixed
2292  for(int j=0, nj= (int)allpanes[i]->size_of_real_nodes(); j<nj; ++j){
2293  if(fgpn_bnd_ptr[j]){
2294  _dcs[i]->incident_elements(j+1,elist);
2295  qual_a_perturb_ptr[j] = 0.0;
2296  for(int k=0, nk=(int)elist.size(); k<nk; ++k){
2297  Element_node_enumerator ene(allpanes[i],k+1);
2298  Angle_Metric_3 am;
2299  am.initialize(ene);
2300  am.compute(angles);
2301  if(angles[1]>qual_a_perturb_ptr[j])
2302  qual_a_perturb_ptr[j] = angles[1];
2303  }
2304  }
2305  }
2306  }
2307 
2308  // Get the perturbed worst quality across all panes
2309  if(COMMPI_Initialized()){
2310  MAP::Pane_communicator pc(_buf_window, _buf_window->get_communicator());
2311  pc.init(w_qual_a_perturb);
2312  pc.begin_update_shared_nodes();
2313  pc.reduce_on_shared_nodes(MPI_MAX);
2314  pc.end_update_shared_nodes();
2315  }
2316 
2317  // Reset positions of any nodes whose worst adj. element quality
2318  // has gotten worse.
2319  for(int i=0,ni=allpanes.size(); i<ni; ++i){
2320 
2321  COM::Attribute *p_fgpn_bnd =
2322  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_fgpn_bnd->id()));
2323  COM::Attribute *p_nc =
2324  const_cast<COM::Attribute*>(allpanes[i]->attribute(COM::COM_NC));
2325  COM::Attribute *p_nc_usr =
2326  const_cast<COM::Attribute*>(allpanes_usr[i]->attribute(COM::COM_NC));
2327 
2328  COM::Attribute *p_qual_b_perturb =
2329  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_qual_b_perturb->id()));
2330  COM::Attribute *p_qual_a_perturb =
2331  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_qual_a_perturb->id()));
2332 
2333  int* fgpn_bnd_ptr =
2334  reinterpret_cast<int*>(p_fgpn_bnd->pointer());
2335  Vector_3<double>* nc_ptr =
2336  reinterpret_cast<Vector_3<double>*>(p_nc->pointer());
2337  Vector_3<double>* nc_ptr_usr =
2338  reinterpret_cast<Vector_3<double>*>(p_nc_usr->pointer());
2339  double* qual_b_perturb_ptr =
2340  reinterpret_cast<double*>(p_qual_b_perturb->pointer());
2341  double* qual_a_perturb_ptr =
2342  reinterpret_cast<double*>(p_qual_a_perturb->pointer());
2343 
2344  // only worry about real nodes, ghost nodes should be fixed
2345 for(int j=0, nj= (int)allpanes[i]->size_of_real_nodes(); j<nj; ++j){
2346  if(fgpn_bnd_ptr[j] &&
2347  (qual_a_perturb_ptr[j] > qual_b_perturb_ptr[j]))
2348  nc_ptr[j] = nc_ptr_usr[j];
2349  }
2350  }
2351 #ifdef ROCPROF
2352  Profile_end("Rocmop::perturb_stat");
2353 #endif
2354 }
2355 
2356 
2357 extern "C" void Rocmop_load_module( const char *mname)
2358 { Rocmop::load( mname); }
2359 
2360 extern "C" void Rocmop_unload_module( const char *mname)
2361 { Rocmop::unload( mname); }
2362 
2363 // Fortran bindings
2364 extern "C" void COM_F_FUNC2(rocmop_load_module, ROCMOP_LOAD_MODULE)( const char *mname, long int length)
2365 { Rocmop::load( std::string(mname, length)); }
2366 
2367 extern "C" void COM_F_FUNC2(rocmop_unload_module, ROCMOP_UNLOAD_MODULE)( const char *mname, long int length)
2368 { Rocmop::unload( std::string(mname, length)); }
2369 
2371 
2372 
2373 
2374 
2375 
2376 
static void div_scalar(const Attribute *x, const void *y, Attribute *z, int swap=0)
Operation wrapper for division with y as a scalar pointer.
Definition: op3args.C:363
static void sub(const Attribute *x, const Attribute *y, Attribute *z)
Operation wrapper for subtraction.
Definition: op3args.C:237
int COM_Type
Indices for derived data types.
Definition: roccom_basic.h:122
void determine_physical_border()
Determine which nodes and elements are on the physical border.
Definition: Rocmop.C:677
void obtain_extremal_dihedrals(const COM::Attribute *att, double *min, double *max)
Obtain the min and max dihedral angles.
Definition: Rocmop_2.C:1991
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_COMM_WORLD
Utility for constructing pane connectivities in parallel.
3D Aspect Ratios Metric Class
void invert()
Invert Tetrahedrons.
Definition: MesqPane.C:45
virtual void compute(double atts[]) const
Calculate the metric value on this element.
double check_all_elem_quality(std::vector< const COM::Pane * > &allpanes, bool with_ghost=false)
Get the largest dihedral angle of all real elements.
Definition: Rocmop.C:785
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_MAX
const char * option(const char *const name, const int argc, const char *const *const argv, const char *defaut, const char *const usage=0)
Definition: CImg.h:5604
void print_mquality(std::string &s, std::vector< std::vector< bool > > &to_check)
Print the quality range of marked elements, for debugging.
Definition: Rocmop.C:883
void COM_delete_window(const char *wname)
Definition: roccom_c++.h:94
j indices k indices k
Definition: Indexing.h:6
Used to hold the error state and return it to the application.
void perturb_stationary()
Randomly perturn stationary nodes on pane boundary, not on phys. surface.
Definition: Rocmop_1.C:1689
void determine_pane_border()
Determine which nodes and elements are on pane borders.
Definition: Rocmop.C:603
#define COM_assertion_msg(EX, msg)
double s
Definition: blastest.C:80
void smooth_boeing(COM::Attribute *att, int *niter)
Definition: Rocmop_2.C:1471
This file contains the prototypes for Roccom API.
3D geometric quality Metric declarations.
void get_usr_disp(const COM::Attribute *pmesh, COM::Attribute *disp, double *timestep)
Get displacement in _usr_window based on nc in _buf_window.
Definition: Rocmop_2.C:1001
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_MIN
A Roccom mesh optimization module.
Definition: Rocmop.h:41
std::ifstream & get_next_line(std::ifstream &Inf, std::string &line, const char noop)
Definition: Rocmop_1.C:106
void COM_set_object(const char *wa_str, int pane_id, Type *addr)
Definition: roccom_c++.h:144
Handles communication of shared nodes, ghost nodes or ghost cells across panes.
#define COM_F_FUNC2(lowcase, uppercase)
Definition: roccom_basic.h:87
const int total_npanes
Definition: ex1.C:94
static void reduce_sum_on_shared_nodes(COM::Attribute *att)
Perform a sum-reduction on the shared nodes for the given attribute.
Definition: Rocmop.C:595
void Rocmop_unload_module(const char *mname)
Definition: Rocmop.C:953
T norm(const NVec< DIM, T > &v)
void zero_displacements(COM::Attribute *disp)
Definition: Rocmop_1.C:426
double length(Vector3D *const v, int n)
void COM_get_object(const char *wa_str, int pane_id, Type **addr)
Definition: roccom_c++.h:152
void update_buf_real_nc()
Update real nodal coordinates of _buf_window from _usr_window.
Definition: Rocmop_2.C:824
void read_config_file(const std::string &)
Definition: Rocmop_1.C:122
static int pconn_offset()
Retrieve an offset to avoid the number of communicating panes when reading a pconn attribute...
void perform_smoothing()
Perform smoothing on _buf_window.
Definition: Rocmop_1.C:776
void initialize(const COM::Attribute *pmesh)
Constructs the communication patterns of a distributed mesh.
Definition: Rocsurf.C:35
void Rocmop_load_module(const char *mname)
Definition: Rocmop.C:950
virtual ~Rocmop()
Destructor.
Definition: Rocmop.C:76
A class enabling Mesquite calls on Rocmop panes.
Definition: MesqPane.h:95
Utility for constructing pane ghost connecvtivities in parallel.
void perform_noniterative_smoothing()
Perform noniterative smoothing.
Definition: Rocmop.C:344
int COM_compatible_types(COM_Type type1, COM_Type type2)
Definition: roccom_c++.h:563
double check_marked_elem_quality(std::vector< std::vector< bool > > &marked_elems, std::vector< COM::Pane * > &allpanes)
Get the largest dihedral angle of marked real elements.
Definition: Rocmop.C:760
void constrain_displacements(COM::Attribute *w_disp)
Contrain displacements to _maxdisp.
Definition: Rocmop_1.C:1424
blockLoc i
Definition: read.cpp:79
Wrapper which performs a Feasible Newton solve using an objective function template with inverse mea...
static void unload(const std::string &mname)
Unloads Rocmop from Roccom.
Definition: Rocmop.C:120
void invert_elements(int conn_type)
Repair inverted tets or hexes.
Definition: Rocmop_2.C:1713
void determine_shared_border()
Determine which nodes and elements are shared.
Definition: Rocmop.C:631
void COM_window_init_done(const char *w_str, int pane_changed=true)
Definition: roccom_c++.h:102
int check_input_pconn()
Check pconn block 3 of the input mesh.
Definition: Rocmop_2.C:886
void print_legible(int verb, const char *msg)
Single process print message if given verbosity level is exceeded.
Definition: Rocmop_1.C:1408
#define MOP_END_NAMESPACE
Definition: mopbasic.h:29
void COM_new_window(const char *wname, MPI_Comm c=MPI_COMM_NULL)
Definition: roccom_c++.h:86
virtual void initialize(Vector_3< double > n[], int type)
Initialize a 3D Geometric Metric by nodal coords and element type.
Definition for Rocblas API.
void print_quality(std::string &s)
Print the quality range of all elements, for debugging.
Definition: Rocmop.C:846
void smooth(const COM::Attribute *pmesh, COM::Attribute *disp)
Smooth the mesh in a Rocmop managed buffer.
Definition: Rocmop.C:132
void int int * nk
Definition: read.cpp:74
static void update_ghosts(COM::Attribute *att, const COM::Attribute *pconn=NULL)
Update ghost nodal or elemental values for the given attribute.
Definition: Rocmap.C:87
j indices j
Definition: Indexing.h:6
void getAspects(double &R, double &r, double &l)
Get the geometric aspects.
void smoother_specific_init()
Perform smoother specific initialization.
Definition: Rocmop.C:364
static void load(const std::string &mname)
Loads Rocmop onto Roccom with a given module name.
Definition: Rocmop.C:88
#define MOP_BEGIN_NAMESPACE
Definition: mopbasic.h:28
3D Max and Min Angle Metric Class
void print_extremal_dihedrals(COM::Window *window)
Print the min and max dihedral angles along with their locations.
Definition: Rocmop_1.C:1463
static void copy(const Attribute *x, Attribute *y)
Wrapper for copy.
Definition: op2args.C:333
double rand()
Return a random variable between [0,1] with respect to an uniform distribution.
Definition: CImg.h:4833
void int int REAL REAL REAL *z blockDim dim * ni
Definition: read.cpp:77
void COM_new_attribute(const char *wa_str, const char loc, const int type, int ncomp, const char *unit)
Registering an attribute type.
Definition: roccom_c++.h:118
void int * nj
Definition: read.cpp:74
void COM_set_member_function(const char *wf_str, Member_func_ptr func, const char *wa_str, const char *intents, const COM_Type *types)
Definition: roccom_c++.h:330
static int rank
Definition: advectest.C:66
Geometric helper function header file.
void set_value(const char *opt, const void *val)
Set a Rocomp option.
Definition: Rocmop.C:529
void mark_elems_from_nodes(std::vector< std::vector< bool > > &marked_nodes, std::vector< std::vector< bool > > &marked_elems)
Mark the nodes which contain marked elems.
Definition: Rocmop.C:712
void add_aspect_ratios(COM::Attribute *usr_att, COM::Attribute *buf_att=NULL)
Definition: Rocmop_1.C:454
int COMMPI_Initialized()
Definition: commpi.h:168
#define MSQ_ERRRTN(err)
If passed error is true, return from a void function.
void smooth_mesquite(std::vector< COM::Pane * > &allpanes, int ghost_level=0)
Smooth the panes of the working window using MESQUITE.
Definition: Rocmop.C:570
void add_mesh(Mesquite::Mesh *mesh, MsqError &err)
adds a mesh to the MeshSet.
void perform_iterative_smoothing()
Perform iterative smoothing.
Definition: Rocmop_1.C:798
The MeshSet class stores one or more Mesquite::Mesh pointers and manages access to the mesh informati...
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
Type norm() const
Definition: mapbasic.h:112
bool check_displacements(COM::Attribute *disp)
Definition: Rocmop_1.C:357