Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Rocmop_1.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_1.C,v 1.8 2008/12/06 08:45:24 mtcampbe Exp $
24 
25 #ifdef MESQUITE
26 #define USE_STD_INCLUDES 1
27 #define USE_C_PREFIX_INCLUDES 1
28 #include "Mesquite.hpp"
29 #include "MeshImpl.hpp"
30 #include "MsqError.hpp"
31 #include "InstructionQueue.hpp"
32 #include "MeshSet.hpp"
33 #include "TerminationCriterion.hpp"
34 #include "QualityAssessor.hpp"
35 #include "PlanarDomain.hpp"
36 #include "ShapeImprovementWrapper.hpp"
37 
38 // algorithms
39 //#include "MeanRatioQualityMetric.hpp"
40 #include "MeanRatioFunctions.hpp"
41 #include "EdgeLengthQualityMetric.hpp"
42 #include "LPtoPTemplate.hpp"
43 #include "FeasibleNewton.hpp"
44 #include "ConjugateGradient.hpp"
45 //#include "MsqMessage.hpp"
46 #include "MesqPane_95.h"
47 
48 using namespace Mesquite;
49 #endif
50 
51 #include "Rocblas.h"
52 #include "Rocmop_1.h"
53 #include "Rocmap.h"
54 #include "roccom.h"
55 #include "Pane_communicator.h"
56 #include "Pane_connectivity.h"
57 #include "Geometric_Metrics_3.h"
58 #include "PN_patch.h"
59 #include "geometry.h"
60 #include "mapbasic.h"
61 
62 // for debugging
63 #include <iostream>
64 #include <iomanip>
65 #include <fstream>
66 using namespace std;
67 // end for debugging
68 
69 #define NO_STRINGSTREAM 1
70 
71 // To enable profiling, use ROCPROF=1 in your make command.
72 #ifdef ROCPROF
73 #include "Rocprof.H"
74 #endif
75 
77 
78 using MAP::Pane_connectivity;
79 using MAP::Pane_communicator;
80 using MAP::Rocmap;
81 using std::cout;
82 using std::endl;
83 
84 Rocmop::~Rocmop() {
85 
86  print_legible(0,"Entering Rocmop::~Rocmop");
87 
88  if (_buf_window){
89  delete _buf_window;
90  _buf_window = NULL;
91  }
92 
93  for(int i =0, ni=_dcs.size(); i<ni; ++i){
94  delete _dcs[i];
95  _dcs[i] = NULL;
96  }
97  print_legible(1,"Exiting Rocmop::~Rocmop");
98 }
99 
100 // Utility function to fetch a non-empty, non-commented line from the
101 // file passed in "Inf". The noop char is the "comment" character, all
102 // lines beginning with 'noop', or empty lines will be ignored. All
103 // whitespace is also ignored. Comments may go on the same line as
104 // data lines. Data lines must not start with whitespace. Valid data
105 // should be separated by newlines.
106 std::ifstream &get_next_line(std::ifstream &Inf,
107  std::string &line,
108  const char noop)
109 {
110  if(!Inf)
111  return(Inf);
112  std::getline(Inf,line);
113  while((line.empty() || line[0] == ' ' || line[0] == noop) && Inf)
114  std::getline(Inf,line);
115  return(Inf);
116 }
117 
118 // New Rocmop function to read the configuration file. Currently, all
119 // processors open and read this file (as opposed to process 0 bc'ing).
120 // If the file does not exist, or has formatting errors, the file is
121 // ignored and Rocmop will continue to function with it's defaults.
122 void Rocmop::read_config_file(const std::string &cfname)
123 {
124  std::ifstream Inf;
125  Inf.open(cfname.c_str());
126 
127  // We can't use the usual print_legible function here because the
128  // buffer winodw may not be created yet.
129  int rank =0;
130  if(COMMPI_Initialized()){
131  int ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);
132  assert( ierr == 0);
133  }
134 
135  // If the file doesn't exist, fire off a warning and continue
136  if(!Inf){
137  if(rank == 0)
138  std::cerr << "Rocmop: Warning: Could not open configfile, "
139  << cfname << "." << std::endl;
140  return;
141  }
142 
143  std::string line;
144  std::istringstream Istr;
145 
146  // Read and set the verbosity
147  int verbosity;
148  get_next_line(Inf,line,'#');
149  // At this point, "line" should have data in it. By using the
150  // istringstream object this way, we eliminate all whitespace
151  // and extract only the valid part of the line. If the file
152  // has already closed, line will be empty, and verbosity will
153  // usually take on some nonsense value.
154  Istr.str(line);
155  Istr >> verbosity;
156  // If the line had only the one chunk of data in it, Istr will
157  // have a bit set that needs to be cleared with a call to "clear()"
158  // before populating it with another string.
159  Istr.clear();
160  if(verbosity < 0 || verbosity > 10){
161  std::cerr << "Rocmop: Warning: Invalid verbosity from configfile. "
162  << "Giving up on " << cfname << "." << std::endl;
163  Inf.close();
164  return;
165  }
166  _verb = verbosity;
167  // Speak up if verbosity is turned on!
168  if (rank==0 && _verb){
169  std::cout << "Rocmop: Found configfile, " << cfname << "." << std::endl
170  << "Rocmop: Setting verbosity to " << _verb << "." << std::endl;
171  }
172 
173  // Load the next line from configfile and set smoothing method
174  get_next_line(Inf,line,'#');
175  Istr.str(line);
176  Istr >> _method;
177  Istr.clear();
178  if(_method < 0 || _method > SMOOTH_NONE){
179  std::cerr << "Rocmop: Warning: Invalid smoothing method from configfile. "
180  << "Giving up on " << cfname << "." << std::endl;
181  Inf.close();
182  return;
183  }
184  // I love these ternary operators
185  if (rank==0 && _verb){
186  std::cout << "Rocmop: Setting method to "
187  << (_method == SMOOTH_VOL_MESQ_WG ? "SMOOTH_VOL_MESQ_WG" :
188  (_method == SMOOTH_VOL_MESQ_NG ? "SMOOTH_VOL_MESQ_NG" :
189  (_method == SMOOTH_SURF_MEDIAL ? "SMOOTH_SURF_MEDIAL" :
190  "SMOOTH_NONE"))) << "." << std::endl;
191  }
192 
193  // Load the next line and set laziness
194  int lazy;
195  get_next_line(Inf,line,'#');
196  Istr.str(line);
197  Istr >> lazy;
198  Istr.clear();
199  if(lazy > 0)
200  _lazy = 1;
201  if (rank==0 && _verb){
202  std::cout << "Rocmop: Setting lazy to " << _lazy << "." << std::endl;
203  }
204 
205  // Load the next line and set tolerance for lazy threshold
206  float tol;
207  get_next_line(Inf,line,'#');
208 #if ! NO_STRINGSTREAM
209  Istr.str(line);
210  Istr >> tol;
211  Istr.clear();
212 #else
213  sscanf(line.c_str(), "%f", &tol);
214 #endif
215  if(tol < 0. || tol > 180.){
216  std::cerr << "Rocmop: Warning: Invalid dihedral angle tolerance"
217  << " from configfile. "
218  << "Giving up on " << cfname << "." << std::endl;
219  Inf.close();
220  return;
221  }
222  _tol = tol;
223  if (rank==0 && _verb){
224  std::cout << "Rocmop: Setting tolerance to " << _tol << "." << std::endl;
225  }
226 
227  // Load the next line and set node displacement constraint for Mesquite smoothing
228  float max_disp;
229  get_next_line(Inf,line,'#');
230 #if ! NO_STRINGSTREAM
231  Istr.str(line);
232  Istr >> max_disp;
233  Istr.clear();
234 #else
235  sscanf(line.c_str(), "%f", &max_disp);
236 #endif
237  if(max_disp < 0. || max_disp > 10.0){
238  std::cerr << "Rocmop: Warning: Invalid displacement constraint from configfile. "
239  << "Giving up on " << cfname << "." << std::endl;
240  Inf.close();
241  return;
242  }
243  _maxdisp = max_disp;
244  if (rank==0 && _verb){
245  std::cout << "Rocmop: Setting displacement constraint to "
246  << _maxdisp << "." << std::endl;
247  }
248 
249  // Load the next line and set N, which forces Rocmop to smooth every Nth step
250  get_next_line(Inf,line,'#');
251  Istr.str(line);
252  Istr >> _smoothfreq;
253  Istr.clear();
254  if(_smoothfreq <= 0 || _method == SMOOTH_NONE)
255  _smoothfreq = 0;
256  if (rank==0 && _verb){
257  if(_method == SMOOTH_NONE){
258  std::cout << "Rocmop: No method selected, setting N to 0"
259  << ", disabling smoothing." << std::endl;
260  }
261  else{
262  std::cout << "Rocmop: Setting N to " << _smoothfreq
263  << (_smoothfreq==0 ? ", disabling smoothing." : ".")
264  << std::endl;
265  }
266  }
267 
268  // Displacement threshold. When the max displacement among all processors
269  // exceeds this value, smooth.
270  get_next_line(Inf,line,'#');
271 #if ! NO_STRINGSTREAM
272  Istr.str(line);
273  Istr >> _disp_thresh;
274  Istr.clear();
275 #else
276  sscanf(line.c_str(), "%f", &_disp_thresh);
277 #endif
278  if(_disp_thresh < 0.0)
279  _disp_thresh = 0.0;
280  else if ((_smoothfreq > 1) && (_disp_thresh > 0.0) ){
281  _smoothfreq = 1;
282  if(rank==0 && _verb)
283  std::cout << "Rocmop: WARNING: N reset to 1 to enable displacement thresholding."
284  << std::endl;
285  }
286  if (rank==0 && _verb){
287  std::cout << "Rocmop: Setting displacement threshold to "
288  << _disp_thresh << "." << std::endl;
289  }
290 
291  // Close up the file, we're done.
292  Inf.close();
293 
294  N = _smoothfreq-1; // initial value used in smooth() function
295 }
296 
297 void Rocmop::load( const std::string &mname) {
298 
299  Rocmop *mop = new Rocmop();
300 
301  // Hardcoded the control file location for now. I didn't really see a clean
302  // way to allow this to be dynamically set without adding additional init
303  // calls to codes outside Rocmop.
304  mop->read_config_file("Rocmop/RocmopControl.txt");
305 
306  COM_new_window( mname.c_str());
307 
308  std::string glb=mname+".global";
309 
310  COM_new_attribute( glb.c_str(), 'w', COM_VOID, 1, "");
311  COM_set_object( glb.c_str(), 0, mop);
312 
313  COM_Type types[3];
314  types[0] = COM_RAWDATA;
315  types[1] = COM_METADATA;
316  types[2] = COM_METADATA;
317 
318  COM_set_member_function( (mname+".smooth").c_str(),
319  (Member_func_ptr)(&Rocmop::smooth),
320  glb.c_str(), "biB", types);
321 
322  COM_set_member_function( (mname+".smooth_in_place").c_str(),
323  (Member_func_ptr)(&Rocmop::smooth_in_place),
324  glb.c_str(), "bb", types);
325 
326  types[1] = COM_STRING;
327  types[2] = COM_VOID;
328  COM_set_member_function( (mname+".set_value").c_str(),
329  (Member_func_ptr)(&Rocmop::set_value),
330  glb.c_str(), "bii", types);
331 
332  types[1] = COM_METADATA;
333  types[2] = COM_METADATA;
334 
335  COM_set_member_function( (mname+".add_aspect_ratios").c_str(),
336  (Member_func_ptr)(&Rocmop::add_aspect_ratios),
337  glb.c_str(), "bbB", types);
338 
339 
340  COM_window_init_done( mname.c_str());
341 
342 }
343 
344 void Rocmop::unload( const std::string &mname) {
345 
346  Rocmop *mop;
347  std::string glb=mname+".global";
348 
349  COM_get_object( glb.c_str(), 0, &mop);
350  delete mop;
351 
352  COM_delete_window( mname.c_str());
353 }
354 
355 // Finds the maximum displacement over all processors
356 bool
357 Rocmop::check_displacements(COM::Attribute *w_disp)
358 {
359 #ifdef ROCPROF
360  Profile_begin("Rocmop::check_disp");
361 #endif
362 
363  int disp_id = w_disp->id();
364  double max_norm = 0.0;
365  // move to class member function
366  //static double disp_tally = 0.0;
367  bool retval = true;
368  // std::ofstream Ouf;
369  // Ouf.open("displacements.txt",ios::app);
370  std::vector<Pane*> allpanes;
371  const_cast<COM::Window*>(_usr_window)->panes(allpanes);
372 
373  // Find the maximum displacement on this processor
374  for(int i=0,ni = allpanes.size(); i<ni; ++i){
375 
376  Vector_3<double> *ptr = NULL;
377  COM::Attribute* ptr_att = allpanes[i]->attribute(disp_id);
378  void* void_ptr = ptr_att->pointer();
379  ptr = reinterpret_cast<Vector_3<double>*>(void_ptr);
380 
381  for(int j=0,nj = allpanes[i]->size_of_real_nodes(); j<nj; ++j){
382  double norm = ptr[j].norm();
383  // Re-assign them to zero to maintain original Rocmop behavior
384  // just in case. I'm pretty sure that any values in this array
385  // already get wiped out when the Mesquite displacements are
386  // copied in.
387  ptr[j][0] = 0.0;
388  ptr[j][1] = 0.0;
389  ptr[j][2] = 0.0;
390  // Ouf << j << ": " << norm << std::endl;
391  if(norm > max_norm)
392  max_norm = norm;
393  }
394  }
395  // Maximize the displacement across all processors
396  agree_double(max_norm,MPI_MAX);
397 
398  // Update the tally
399  disp_tally += max_norm;
400 
401  // Build a blurb about displacement
402  std::ostringstream Ostr;
403  Ostr << "Mesh Displacement: " << disp_tally;
404 
405  // Determine whether we have exceeded the threshold
406  if(disp_tally > _disp_thresh){
407  disp_tally = 0.0;
408  retval = true;
409  // If we intend to smooth - also print out the displacement
410  print_legible(0,Ostr.str().c_str());
411  }
412  else {
413  retval = false;
414  // If not smoothing, print out displacement if verbosity is higher
415  print_legible(1,Ostr.str().c_str());
416  }
417 #ifdef ROCPROF
418  Profile_end("Rocmop::check_disp");
419 #endif
420  // Ouf.close();
421  return(retval);
422 }
423 
424 // Zero displacements array
425 void
426 Rocmop::zero_displacements(COM::Attribute *w_disp)
427 {
428 #ifdef ROCPROF
429  Profile_begin("Rocmop::zero_disp");
430 #endif
431 
432  int disp_id = w_disp->id();
433  std::vector<Pane*> allpanes;
434  const_cast<COM::Window*>(_usr_window)->panes(allpanes);
435 
436  for(int i=0,ni = allpanes.size(); i<ni; ++i){
437  Vector_3<double> *ptr = NULL;
438  COM::Attribute* ptr_att = allpanes[i]->attribute(disp_id);
439  void* void_ptr = ptr_att->pointer();
440  ptr = reinterpret_cast<Vector_3<double>*>(void_ptr);
441  for(int j=0,nj = allpanes[i]->size_of_real_nodes(); j<nj; ++j){
442  // Zero to maintain original physics module behavior
443  ptr[j][0] = 0.0;
444  ptr[j][1] = 0.0;
445  ptr[j][2] = 0.0;
446  }
447  }
448 #ifdef ROCPROF
449  Profile_end("Rocmop::zero_disp");
450 #endif
451 }
452 
453 // Add aspect ratio measures to the user's mesh
454 void Rocmop::add_aspect_ratios(COM::Attribute *usr_att,
455  COM::Attribute *buf_att){
456 
457  COM::Window* usr_window = usr_att->window();
458  COM::Window* buf_window = NULL;
459 
460  bool del_buffer = false;
461 
462  if(!buf_att){
463  del_buffer = true;
464  // Create a buffer window by cloning from the user window
465  std::string buf_name(usr_window->name()+"-Rocmop_add_aspect");
466  buf_window = new COM::Window(buf_name,
467  usr_window->get_communicator());
468  buf_window->inherit( usr_att, "",
469  COM::Pane::INHERIT_CLONE, true, NULL,0);
470  buf_window->init_done();
471  }
472  else
473  buf_window = _buf_window;
474 
475  std::vector<Pane*> allpanes;
476 
477  buf_window->panes(allpanes);
478 
479  // Create and resize window level buffer attributes
480  COM::Attribute * w_buff_R =
481  buf_window->new_attribute("Aspect Ratio: R (circumradius)",'e',COM_DOUBLE,1,"");
482  COM::Attribute * w_buff_r =
483  buf_window->new_attribute("Aspect Ratio: r (inradius)",'e',COM_DOUBLE,1,"");
484  COM::Attribute * w_buff_l =
485  buf_window->new_attribute("Aspect Ratio: l (shortest edge)",'e',COM_DOUBLE,1,"");
486  COM::Attribute * w_buff_rR =
487  buf_window->new_attribute("Aspect Ratio: 3r/R",'e',COM_DOUBLE,1,"");
488  COM::Attribute * w_buff_Rr =
489  buf_window->new_attribute("Aspect Ratio: R/r",'e',COM_DOUBLE,1,"");
490  COM::Attribute * w_buff_Rl =
491  buf_window->new_attribute("Aspect Ratio: R/l",'e',COM_DOUBLE,1,"");
492  COM::Attribute * w_buff_min =
493  buf_window->new_attribute("Aspect Ratio: min dih",'e',COM_DOUBLE,1,"");
494  COM::Attribute * w_buff_max =
495  buf_window->new_attribute("Aspect Ratio: max dih",'e',COM_DOUBLE,1,"");
496 
497  buf_window->resize_array(w_buff_R,0);
498  buf_window->resize_array(w_buff_r,0);
499  buf_window->resize_array(w_buff_l,0);
500  buf_window->resize_array(w_buff_rR,0);
501  buf_window->resize_array(w_buff_Rr,0);
502  buf_window->resize_array(w_buff_Rl,0);
503  buf_window->resize_array(w_buff_min,0);
504  buf_window->resize_array(w_buff_max,0);
505  buf_window->init_done();
506 
507  // Obtain buffer attribute ids
508  int R_id = w_buff_R->id();
509  int r_id = w_buff_r->id();
510  int l_id = w_buff_l->id();
511  int rR_id = w_buff_rR->id();
512  int Rr_id = w_buff_Rr->id();
513  int Rl_id = w_buff_Rl->id();
514  int min_id = w_buff_min->id();
515  int max_id = w_buff_max->id();
516 
517  // Create and resize window level user attributes
518  COM::Attribute * w_usr_R =
519  usr_window->new_attribute("Aspect Ratio: R",'e',COM_DOUBLE,1,"");
520  COM::Attribute * w_usr_r =
521  usr_window->new_attribute("Aspect Ratio: r",'e',COM_DOUBLE,1,"");
522  COM::Attribute * w_usr_l =
523  usr_window->new_attribute("Aspect Ratio: l",'e',COM_DOUBLE,1,"");
524  COM::Attribute * w_usr_rR =
525  usr_window->new_attribute("Aspect Ratio: 3r/R",'e',COM_DOUBLE,1,"");
526  COM::Attribute * w_usr_Rr =
527  usr_window->new_attribute("Aspect Ratio: R/r",'e',COM_DOUBLE,1,"");
528  COM::Attribute * w_usr_Rl =
529  usr_window->new_attribute("Aspect Ratio: R/l",'e',COM_DOUBLE,1,"");
530  COM::Attribute * w_usr_min =
531  usr_window->new_attribute("Aspect Ratio: min dih",'e',COM_DOUBLE,1,"");
532  COM::Attribute * w_usr_max =
533  usr_window->new_attribute("Aspect Ratio: max dih",'e',COM_DOUBLE,1,"");
534 
535  usr_window->resize_array(w_usr_R,0);
536  usr_window->resize_array(w_usr_r,0);
537  usr_window->resize_array(w_usr_l,0);
538  usr_window->resize_array(w_usr_rR,0);
539  usr_window->resize_array(w_usr_Rr,0);
540  usr_window->resize_array(w_usr_Rl,0);
541  usr_window->resize_array(w_usr_min,0);
542  usr_window->resize_array(w_usr_max,0);
543  usr_window->init_done();
544 
545  double R,r,l;
546  double angles[] = {0.0,0.0};
547 
548  for(int i=0,ni=(int)allpanes.size();i<ni;++i){
549 
550  // get Pane level buffer attributes
551  double *R_ptr = reinterpret_cast<double *>
552  (allpanes[i]->attribute(R_id)->pointer());
553  double *r_ptr = reinterpret_cast<double *>
554  (allpanes[i]->attribute(r_id)->pointer());
555  double *l_ptr = reinterpret_cast<double *>
556  (allpanes[i]->attribute(l_id)->pointer());
557  double *rR_ptr = reinterpret_cast<double *>
558  (allpanes[i]->attribute(rR_id)->pointer());
559  double *Rr_ptr = reinterpret_cast<double *>
560  (allpanes[i]->attribute(Rr_id)->pointer());
561  double *Rl_ptr = reinterpret_cast<double *>
562  (allpanes[i]->attribute(Rl_id)->pointer());
563  double *min_ptr = reinterpret_cast<double *>
564  (allpanes[i]->attribute(min_id)->pointer());
565  double *max_ptr = reinterpret_cast<double *>
566  (allpanes[i]->attribute(max_id)->pointer());
567 
568  for(int j=0,nj=allpanes[i]->size_of_elements();j<nj;++j){
569 
570  Element_node_enumerator ene(allpanes[i],j+1);
571 
572  Aspect_Metric_3 aspect_met;
573  aspect_met.initialize(ene);
574  aspect_met.getAspects(R,r,l);
575 
576  Angle_Metric_3 angle_met;
577  angle_met.initialize(ene);
578  angle_met.compute(angles);
579 
580  R_ptr[j] = R;
581  r_ptr[j] = r;
582  l_ptr[j] = l;
583  COM_assertion_msg(R != 0.0,
584  "Cannot calculate aspect ratios with zero magnitude circumradius");
585  rR_ptr[j] = (3.0*r)/R;
586  COM_assertion_msg(r != 0.0,
587  "Cannot calculate aspect ratios with zero magnitude circumradius");
588  Rr_ptr[j] = R/r;
589  COM_assertion_msg(l != 0.0,
590  "Cannot calculate aspect ratios with zero magnitude circumradius");
591  Rl_ptr[j] = R/l;
592 
593  min_ptr[j] = angles[0];
594  max_ptr[j] = angles[1];
595  }
596  }
597 
598  Rocmap::update_ghosts(w_buff_R);
599  Rocmap::update_ghosts(w_buff_r);
600  Rocmap::update_ghosts(w_buff_l);
601  Rocmap::update_ghosts(w_buff_rR);
602  Rocmap::update_ghosts(w_buff_Rr);
603  Rocmap::update_ghosts(w_buff_Rl);
604  Rocmap::update_ghosts(w_buff_min);
605  Rocmap::update_ghosts(w_buff_max);
606 
607  Rocblas::copy(w_buff_R,w_usr_R);
608  Rocblas::copy(w_buff_r,w_usr_r);
609  Rocblas::copy(w_buff_l,w_usr_l);
610  Rocblas::copy(w_buff_rR,w_usr_rR);
611  Rocblas::copy(w_buff_Rr,w_usr_Rr);
612  Rocblas::copy(w_buff_Rl,w_usr_Rl);
613  Rocblas::copy(w_buff_min,w_usr_min);
614  Rocblas::copy(w_buff_max,w_usr_max);
615 
616  if(del_buffer)
617  delete buf_window;
618 }
619 
620 void Rocmop::smooth(const COM::Attribute *pmesh,
621  COM::Attribute *disp){
622 
623  // The static var N will statically store the current value of
624  // N. When N == 0, we will smooth and set N back to (_smoothfreq - 1).
625  // What this amounts to is that we smooth only every _smoothfreqth call
626  // to Rocmop. _smoothfreq is specified as "N" in the config file.
627  //static int N = (_smoothfreq-1);
628  if (N==-9999) N = (_smoothfreq-1);
629 
630  if(N == 0){ // Go ahead and actually smooth if this is true
631  N = (_smoothfreq-1); // Reset N
632 
633  // We want to start profiling from here as it's smoothing we
634  // want to time, not the NOOP calls.
635 #ifdef ROCPROF
636  Profile_begin("Rocmop::smooth");
637 #endif
638 
639  COM_assertion_msg( validate_object()==0, "Invalid object");
640 
641  // Verify that we are working with a mesh or pmesh
642  int pmesh_id = pmesh->id();
643  COM_assertion_msg( pmesh &&
644  (pmesh_id==COM::COM_PMESH || pmesh_id==COM::COM_MESH),
645  "Input to Rocmop::smooth must be a mesh or pmesh attribute.");
646  _is_pmesh = (pmesh_id == COM_PMESH) ? true : false;
647 
648  // If buffer window exists and was cloned from the current user
649  // window, then just update the coordinates.
650 
651  if(_buf_window && (_usr_window == pmesh->window()))
652  Rocblas::copy(_usr_window->attribute(COM::COM_NC),
653  _buf_window->attribute(COM::COM_NC));
654 
655  // Else, inherit(clone) a buffer window from the user's mesh.
656  else{
657 
658  // Eliminate any old buffers
659  if(_buf_window){
660  delete _buf_window;
661  _invert = 1;
662  }
663 
664  _usr_window = pmesh->window();
665 
666  // Create a buffer window by cloning from the user window
667  std::string buf_name(_usr_window->name()+"-Rocmopbuf");
668  _buf_window = new COM::Window(buf_name,
669  _usr_window->get_communicator());
670  _buf_window->inherit( const_cast<COM::Attribute*>(pmesh), "",
671  COM::Pane::INHERIT_CLONE, true, NULL, 0);
672  _buf_window->init_done();
673 
674  // Perform initialization specific to the smoother.
675  smoother_specific_init();
676  }
677 
678  // Max possible worst element quality is 180.0, so this
679  // default should result in mesh smoothing if _lazy==0
680  double mesh_qual = 190.0;
681 
682  // Check initial quality if we are in lazy mode
683  if(_lazy){
684 
685  // Fill a vector with pointers to the local panes
686  std::vector<const Pane*> allpanes;
687  _buf_window->panes(allpanes);
688 
689  mesh_qual = check_all_elem_quality(allpanes);
690  }
691 
692  // Mechanism to trigger smoothing on tallied displacements
693  bool exceeded = true;
694  if(_disp_thresh > 0.0)
695  exceeded = check_displacements(disp);
696 
697  if(exceeded || ((mesh_qual > _tol) && _lazy)){
698  print_legible(0,"Smoothing...");
699  perform_smoothing();
700  print_legible(0,"Smoothing complete.");
701  // Obtain the displacements
702  const COM::Attribute *old_nc = pmesh->window()->attribute( COM::COM_NC);
703  const COM::Attribute *new_nc =_buf_window->attribute( COM::COM_NC);
704  Rocblas::sub (new_nc, old_nc, disp);
705  constrain_displacements(disp);
706  }
707  else{
708  _usr_window = pmesh->window();
709  zero_displacements(disp);
710  }
711 
712 
713 #ifdef ROCPROF
714  Profile_end("Rocmop::smooth");
715 #endif
716  } // if (N says it's smoothing time
717  else{
718  if(_smoothfreq > 0)
719  N--;
720  _usr_window = pmesh->window();
721  zero_displacements(disp);
722  }
723 }
724 
725 void Rocmop::smooth_in_place(COM::Attribute *pmesh){
726 #ifdef ROCPROF
727  Profile_begin("Rocmop::smooth_in_place");
728 #endif
729 
730  COM_assertion_msg( validate_object()==0, "Invalid object");
731  print_legible(0,"Entering rocmop::smooth_in_place");
732 
733  int pmesh_id = pmesh->id();
734 
735  COM_assertion_msg( pmesh &&
736  (pmesh_id==COM::COM_PMESH || pmesh_id==COM::COM_MESH) ,
737  "Input to Rocmop::smooth_in_place must be a mesh or pmesh");
738 
739  if(_buf_window)
740  delete _buf_window;
741  _usr_window = pmesh->window();
742 
743  // FIXME
744  // Create a buffer window by inheriting(use) from the user's mesh.
745  // can't use the _usr_window directly because of problems with
746  // Element_node_enumerator
747  _buf_window = new COM::Window(_usr_window->name()+"-Rocmopbuf",
748  _usr_window->get_communicator());
749  _buf_window->inherit( const_cast<COM::Attribute*>(pmesh), "",
750  false, true, NULL, 0);
751  _buf_window->init_done();
752 
753  std::vector<const Pane*> allpanes;
754  _buf_window->panes(allpanes);
755 
756  double mesh_qual = 190.0;
757 
758  // Check initial quality if we are in lazy mode
759  if(_lazy)
760  mesh_qual = check_all_elem_quality(allpanes);
761 
762  if (mesh_qual > _tol)
763  perform_smoothing();
764 
765  if (_buf_window){
766  delete _buf_window;
767  _buf_window = NULL;
768  }
769 
770  print_legible(1,"Exiting rocmop::smooth_in_place");
771 #ifdef ROCPROF
772  Profile_end("Rocmop::smooth_in_place");
773 #endif
774 }
775 
777 #ifdef ROCPROF
778  Profile_begin("Rocmop::perform_smoothing");
779 #endif
780  print_legible(1," Entering Rocmop::perform_smoothing");
781 
782  COM_assertion_msg(_buf_window, "Unexpected NULL pointer encountered.");
783 
784  // Select iterative or noniterative option depending on the smoother.
785  if (0) // No noniterative smoothers currently
786  perform_noniterative_smoothing();
787  else if( _method < SMOOTH_NONE)
788  perform_iterative_smoothing();
789  else
790  COM_assertion_msg(0, "No valid smoothing method selected");
791 
792  print_legible(1," Exiting Rocmop::perform_smoothing");
793 #ifdef ROCPROF
794  Profile_end("Rocmop::perform_smoothing");
795 #endif
796 }
797 
799  // All internal iterative behavior has been removed.
800 #ifdef ROCPROF
801  Profile_begin("Rocmop::perform_itersmooth");
802 #endif
803 
804  print_legible(1," Entering Rocmop::perform_iterative_smoothing");
805 
806  COM_assertion_msg(_buf_window, "Unexpected NULL pointer encountered.");
807 
808  std::vector<const Pane*> allpanes;
809  _buf_window->panes(allpanes);
810 
811 #ifdef MESQUITE
812 
813  if(_method==SMOOTH_VOL_MESQ_WG)
814  smooth_vol_mesq_wg();
815 
816  else if(_method==SMOOTH_VOL_MESQ_NG)
817  smooth_vol_mesq_ng();
818 
819 #else
820 
821  if((_method==SMOOTH_VOL_MESQ_WG) || (_method==SMOOTH_VOL_MESQ_NG))
822  COM_assertion_msg(0,"Rocmop not compiled with MESQUITE");
823 
824 #endif
825 
826  else if(_method==SMOOTH_SURF_MEDIAL)
827  smooth_surf_medial();
828 
829  else COM_assertion_msg(0, "No valid iterative smoothing method selected");
830 
831  print_legible(1," Exiting Rocmop::perform_iterative_smoothing");
832 #ifdef ROCPROF
833  Profile_end("Rocmop::perform_itersmooth");
834 #endif
835 }
836 
838 #ifdef ROCPROF
839  Profile_begin("Rocmop::perform_nonitersmooth");
840 #endif
841 
842  print_legible(1," Entering Rocmop::perform_noniterative_smoothing");
843 
844  if(_niter != 1){
845  std::cerr << "Although the maximum number of iterations > 1 is selected,\n"
846  << "the smoothing method is noniterative, and will run once.\n";
847  }
848 
849  if (0)
850  ;// Currently, no noniterative methods exist.
851  else COM_assertion_msg(0, "No valid noniterative smoothing method selected");
852 
853  print_legible(1," Exiting Rocmop::perform_noniterative_smoothing");
854 #ifdef ROCPROF
855  Profile_end("Rocmop::perform_nonitersmooth");
856 #endif
857 }
858 
859 // Perform smoother specific initializing, for example initializing the
860 // Window_manifold_2 for a surface mesh, adding smoother specific attributes
861 // to the window, etc.
863 #ifdef ROCPROF
864  Profile_begin("Rocmop::perform_smooth_init");
865 #endif
866 
867  print_legible(1," Entering Rocmop::smoother_specific_init");
868 
869  // get rid of any old data
870  if(_wm){ delete _wm; _wm = NULL; }
871 
872  // perform initialization common to surface smoothers
873  if(_method==SMOOTH_SURF_MEDIAL){
874  // Initialize the Window_manifold
875  if(_wm == NULL)
876  Rocsurf::initialize(_buf_window->attribute(_is_pmesh ? COM_PMESH : COM_MESH));
877  }
878 
879  // perform smoother specific initialization
880  switch (_method){
881 
882 #ifdef MESQUITE
883  case SMOOTH_VOL_MESQ_WG: {
884  // Obtain a list of elements containing shared nodes for each pane.
885  determine_shared_border();
886  if(_invert)
887  invert_tets();
888  break;
889  }
890  case SMOOTH_VOL_MESQ_NG: {
891 
892  // Check to see if the physical surface boundary exists
893  const std::string surf_attr("is_surface");
894  const COM::Attribute *w_is_surface = _usr_window->attribute(surf_attr);
895  if(w_is_surface){
896 
897  COM_assertion_msg( COM_compatible_types( w_is_surface->data_type(), COM_INT),
898  "Surface-list must have integer type");
899  COM_assertion_msg( w_is_surface->is_nodal() == 1,
900  "Surface-list must be nodal");
901  COM_assertion_msg( w_is_surface->size_of_components() == 1,
902  "Surface-list must have a single component");
903  COM_assertion_msg( w_is_surface->initialized() == 1,
904  "Surface-list must be initialized");
905 
906  // Clone the attribute
907  COM::Attribute * new_attr =
908  _buf_window->inherit( const_cast<COM::Attribute *>(w_is_surface),
909  surf_attr, COM::Pane::INHERIT_CLONE, true, NULL, 0);
910  COM_assertion_msg(new_attr, "Attribute could not be allocated.");
911  }
912  // else, detect the physical boundary ourselves
913  else{
914  COM::Attribute* w_surf_attr =
915  _buf_window->new_attribute( "is_surface", 'n', COM_INT, 1, "");
916  _buf_window->resize_array( w_surf_attr, 0);
917 
918  determine_physical_border(w_surf_attr);
919  }
920  _buf_window->init_done();
921 
922  if(_invert)
923  invert_tets();
924  break;
925  }
926 #else
927  case SMOOTH_VOL_MESQ_WG:
928  case SMOOTH_VOL_MESQ_NG:
929  COM_assertion_msg(0, "Not compiled with MESQUITE");
930  break;
931 #endif
932 
933  case SMOOTH_SURF_MEDIAL: {
934 
935  // Extend buffer window
936  COM::Attribute* w_disps =
937  _buf_window->new_attribute( "disps", 'n', COM_DOUBLE, 3, "");
938  _buf_window->resize_array( w_disps, 0);
939 
940  COM::Attribute* w_facenormals =
941  _buf_window->new_attribute( "facenormals", 'e', COM_DOUBLE, 3, "");
942  _buf_window->resize_array( w_facenormals, 0);
943 
944  COM::Attribute* w_facecenters =
945  _buf_window->new_attribute( "facecenters", 'e', COM_DOUBLE, 3, "");
946  _buf_window->resize_array( w_facecenters, 0);
947 
948  COM::Attribute* w_eigvalues =
949  _buf_window->new_attribute( "lambda", 'n', COM_DOUBLE, 3, "");
950  _buf_window->resize_array( w_eigvalues, 0);
951 
952  COM::Attribute* w_vnormals =
953  _buf_window->new_attribute( "vnormals", 'n', COM_DOUBLE, 3, "");
954  _buf_window->resize_array( w_vnormals, 0);
955 
956  COM::Attribute* w_awnormals =
957  _buf_window->new_attribute( "awnormals", 'n', COM_DOUBLE, 3, "");
958  _buf_window->resize_array( w_awnormals, 0);
959 
960  COM::Attribute* w_uwnormals =
961  _buf_window->new_attribute( "uwnormals", 'n', COM_DOUBLE, 3, "");
962  _buf_window->resize_array( w_uwnormals, 0);
963 
964  COM::Attribute* w_eigvecs =
965  _buf_window->new_attribute( "eigvecs", 'n', COM_DOUBLE, 9, "");
966  _buf_window->resize_array( w_eigvecs, 0);
967 
968  COM::Attribute* w_tangranks =
969  _buf_window->new_attribute( "tangranks", 'n', COM_INT, 1, "");
970  _buf_window->resize_array( w_tangranks, 0);
971 
972  COM::Attribute* w_cntnranks =
973  _buf_window->new_attribute( "cntnranks", 'n', COM_INT, 1, "");
974  _buf_window->resize_array( w_cntnranks, 0);
975 
976  COM::Attribute* w_cntnvecs =
977  _buf_window->new_attribute( "cntnvecs", 'n', COM_DOUBLE, 6, "");
978  _buf_window->resize_array( w_cntnvecs, 0);
979 
980  COM::Attribute* w_scales =
981  _buf_window->new_attribute( "scales", 'n', COM_DOUBLE, 1, "");
982  _buf_window->resize_array( w_scales, 0);
983 
984  COM::Attribute* w_weights =
985  _buf_window->new_attribute( "weights", 'n', COM_DOUBLE, 1, "");
986  _buf_window->resize_array( w_weights, 0);
987 
988  COM::Attribute* w_weights2 =
989  _buf_window->new_attribute( "weights2", 'n', COM_DOUBLE, 1, "");
990  _buf_window->resize_array( w_weights2, 0);
991 
992  COM::Attribute* w_barycrds =
993  _buf_window->new_attribute( "barycrds", 'n', COM_DOUBLE, 2, "");
994  _buf_window->resize_array( w_barycrds, 0);
995 
996  COM::Attribute* w_PNelemids =
997  _buf_window->new_attribute( "PNelemids", 'n', COM_INT, 1, "");
998  _buf_window->resize_array( w_PNelemids, 0);
999 
1000  // Extend the buffer window to hold local contributions to new placement
1001  // and the number of contributing faces for Laplacian smoothing.
1002  COM::Attribute * w_pnt_contrib =
1003  _buf_window->new_attribute("pnt_contrib", 'n', COM_DOUBLE, 3, "");
1004  _buf_window->resize_array(w_pnt_contrib, 0);
1005 
1006  COM::Attribute * w_disp_count =
1007  _buf_window->new_attribute("disp_count", 'n', COM_DOUBLE, 1, "");
1008  _buf_window->resize_array(w_disp_count, 0);
1009 
1010  _buf_window->init_done();
1011 
1012  break;
1013  }
1014  // case SMOOTH_LAPLACE : {
1015  //break;
1016  //}
1017  default:
1018  COM_assertion_msg(0, "Can't initialize for invalid smoother.");
1019  break;
1020  }
1021 
1022  COM_assertion_msg(_buf_window, "Unexpected NULL pointer encountered.");
1023 
1024  print_legible(1," Exiting Rocmop::smoother_specific_init");
1025 #ifdef ROCPROF
1026  Profile_end("Rocmop::perform_smooth_init");
1027 #endif
1028 }
1029 
1030 void Rocmop::set_value(const char* opt, const void* value)
1031 {
1032 
1033  //print_legible(0,"Entering Rocmop::set_value");
1034 
1035  COM_assertion_msg( validate_object()==0, "Invalid object");
1036 
1037  COM_assertion_msg( opt && value,
1038  "Rocmop::set_value does not except NULL parameters");
1039  std::string option;
1040  if(opt) option = opt;
1041  if ( option == "method") {
1042  COM_assertion_msg( *((int*)value) <= SMOOTH_NONE && *((int*)value)>=0
1043  ,"Illegal value for 'method' option");
1044  _method = *((int*)value);
1045  }
1046  else if ( option == "verbose"){
1047  _verb = *((int*)value); }
1048  else if ( option == "lazy"){
1049  _lazy = *((int*)value); }
1050  else if ( option == "tol"){
1051  COM_assertion_msg( *((float*)value) <= 180. && *((float*)value)>=0.
1052  ,"Illegal value for 'tol' option");
1053  _tol = *((float*)value); }
1054  else if ( option == "maxdisp"){
1055  COM_assertion_msg( *((float*)value)>0.
1056  ,"Illegal value for 'maxdisp' option");
1057  _maxdisp = *((float*)value); }
1058  else if ( option == "niter"){
1059  _niter = *((int*)value); }
1060  else if ( option == "ctol"){
1061  COM_assertion_msg( *((float*)value) <= 1. && *((float*)value)>=0.
1062  ,"Illegal value for '_ctol' option");
1063  _ctol = *((float*)value); }
1064  else if ( option == "ncycle"){
1065  _ncycle = *((int*)value); }
1066  else if ( option == "inverted"){
1067  _invert = *((int*)value);
1068  }
1069  else COM_assertion_msg( false, "Unknown option");
1070 
1071  //print_legible(1,"Exiting Rocmop::set_value");
1072 }
1073 
1074 void Rocmop::smooth_mesquite(std::vector<COM::Pane*> &allpanes,
1075  int ghost_level){
1076 
1077 #ifdef ROCPROF
1078  Profile_begin("Rocmop::smooth_mesquite");
1079 #endif
1080  Mesquite::MsqError err;
1081  ShapeImprovementWrapper mesh_quality_algorithm(err);
1082 
1083  int total_npanes = (int)allpanes.size();
1084  bool wg = (ghost_level == 0) ? false : true;
1085  for(int j=0; j < total_npanes; ++j){
1086  MesqPane mp(allpanes[j],wg);
1087  MeshSet mesh_set1;
1088  if(_verb > 4)
1089  mp.set_verb(_verb - 4);
1090 
1091  mesh_set1.add_mesh(&mp, err);
1092  MSQ_ERRRTN(err);
1093 #ifdef ROCPROF
1094  Profile_begin("Rocmop::Mesquite");
1095 #endif
1096  mesh_quality_algorithm.run_instructions(mesh_set1, err);
1097 #ifdef ROCPROF
1098  Profile_end("Rocmop::Mesquite");
1099 #endif
1100  MSQ_ERRRTN(err);
1101  }
1102 #ifdef ROCPROF
1103  Profile_end("Rocmop::smooth_mesquite");
1104 #endif
1105 }
1106 
1107 void Rocmop::reduce_sum_on_shared_nodes(COM::Attribute *att){
1108  Pane_communicator pc(att->window(), att->window()->get_communicator());
1109  pc.init(att);
1110  pc.begin_update_shared_nodes();
1111  pc.reduce_on_shared_nodes(MPI_SUM);
1112  pc.end_update_shared_nodes();
1113 }
1114 
1116 #ifdef ROCPROF
1117  Profile_begin("Rocmop::pane_border");
1118 #endif
1119 
1120  print_legible(1,"Entering Rocmop::determine_pane_border");
1121 
1122  std::vector<const COM::Pane*> allpanes;
1123  _buf_window->panes(allpanes);
1124  int local_npanes = (int)allpanes.size();
1125 
1126  _is_pane_bnd_node.resize(local_npanes);
1127  _is_pane_bnd_elem.resize(local_npanes);
1128 
1129  for(int i=0; i< local_npanes; ++i){
1130  int size_of_real_nodes = allpanes[i]->size_of_real_nodes();
1131  int size_of_real_elems = allpanes[i]->size_of_real_elements();
1132  _is_pane_bnd_node[i].resize(size_of_real_nodes,0);
1133  _is_pane_bnd_elem[i].resize(size_of_real_elems,0);
1134 
1135  std::vector<bool> is_isolated; // is a node isolated?
1136  MAP::Pane_boundary pb (allpanes[i]);
1137  pb.determine_border_nodes(_is_pane_bnd_node[i], is_isolated);
1138  }
1139 
1140  mark_elems_from_nodes(_is_pane_bnd_node,_is_pane_bnd_elem);
1141 
1142  print_legible(1,"Exiting Rocmop::determine_pane_border");
1143 #ifdef ROCPROF
1144  Profile_end("Rocmop::pane_border");
1145 #endif
1146 }
1147 
1148 
1150 #ifdef ROCPROF
1151  Profile_begin("Rocmop::shared_border");
1152 #endif
1153 
1154  print_legible(1,"Entering Rocmop::determine_shared_nodes");
1155 
1156  std::vector<const COM::Pane*> allpanes;
1157  _buf_window->panes(allpanes);
1158  int local_npanes = (int)allpanes.size();
1159 
1160  _is_shared_node.resize(local_npanes);
1161 
1162  //First, get the list of shared nodes.
1163  for(int i=0; i < (int)(local_npanes); ++i){
1164  // Obtain the pane connectivity of the local pane.
1165  const COM::Attribute *pconn = allpanes[i]->attribute(COM::COM_PCONN);
1166  // Use the pconn offset
1167  const int *vs = (const int*)pconn->pointer()+Pane_connectivity::pconn_offset();
1168  int vs_size=pconn->size_of_real_items()-Pane_connectivity::pconn_offset();
1169  _is_shared_node[i].resize(allpanes[i]->size_of_real_nodes(),0);
1170 
1171  // Determine the number of communicating panes for shared nodes.
1172  int count=0;
1173  for (int j=0, nj=vs_size; j<nj; j+=vs[j+1]+2) {
1174  if (_buf_window->owner_rank( vs[j]) >=0) ++count;
1175  }
1176 
1177  int index = 0;
1178  // Loop through communicating panes for shared nodes.
1179  for ( int j=0; j<count; ++j, index+=vs[index+1]+2) {
1180  // We skip the panes that are not in the current window
1181  while ( _buf_window->owner_rank(vs[index])<0) {
1182  index+=vs[index+1]+2;
1183  COM_assertion_msg( index<=vs_size, "Invalid communication map");
1184  }
1185  // Add shared nodes to the list
1186  for(int k=0; k<vs[index+1]; ++k){
1187  _is_shared_node[i][vs[index+2+k]-1] = 1;
1188  }
1189  }
1190  }
1191 
1192  mark_elems_from_nodes(_is_shared_node,_is_shared_elem);
1193 
1194  print_legible(1,"Exiting Rocmop::determine_shared_nodes");
1195 #ifdef ROCPROF
1196  Profile_end("Rocmop::shared_border");
1197 #endif
1198 }
1199 
1201 #ifdef ROCPROF
1202  Profile_begin("Rocmop::phys_border");
1203 #endif
1204  print_legible(1,"Entering Rocmop::determine_physical_border()");
1205 
1206  const std::string surf_attr("is_surface");
1207  COM::Attribute* w_is_surface = _buf_window->attribute(surf_attr);
1208  COM_assertion_msg( w_is_surface, "Unexpected NULL pointer");
1209  int is_surface_id = w_is_surface->id();
1210 
1211  std::vector<const COM::Pane*> allpanes;
1212  _buf_window->panes(allpanes);
1213  int local_npanes = (int)allpanes.size();
1214 
1215  _is_phys_bnd_node.resize(local_npanes);
1216 
1217  for(int i=0; i < local_npanes; ++i){
1218  _is_phys_bnd_node[i].resize(allpanes[i]->size_of_real_nodes());
1219 
1220  // get pane level pointer to physical border property.
1221  const COM::Attribute *p_is_surface = allpanes[i]->attribute(is_surface_id);
1222  int *is_surface_ptr = (int*)p_is_surface->pointer();
1223 
1224  // loop through real nodes
1225  for(int j=0, nj =(int) allpanes[i]->size_of_real_nodes();j<nj; ++j){
1226  if (is_surface_ptr[j])
1227  _is_phys_bnd_node[i][j] = true;
1228  }
1229  }
1230 
1231  mark_elems_from_nodes(_is_phys_bnd_node,_is_phys_bnd_elem);
1232 
1233 
1234  print_legible(1,"Exiting Rocmop::determine_physical_border()");
1235 #ifdef ROCPROF
1236  Profile_end("Rocmop::phys_border");
1237 #endif
1238 }
1239 
1240 void Rocmop::mark_elems_from_nodes(std::vector<std::vector<bool> > &marked_nodes,
1241  std::vector<std::vector<bool> > &marked_elems){
1242 #ifdef ROCPROF
1243  Profile_begin("Rocmop::mark_elem_node");
1244 #endif
1245 
1246  print_legible(1,"Entering Rocmop::mark_elems_from_nodes");
1247 
1248  std::vector<const COM::Pane*> allpanes;
1249  _buf_window->panes(allpanes);
1250  int local_npanes = (int)allpanes.size();
1251 
1252  marked_elems.clear();
1253  marked_elems.resize(local_npanes);
1254 
1255  //Loop through panes
1256  for(int i=0; i < (int)(local_npanes); ++i){
1257 
1258  marked_elems[i].clear();
1259  marked_elems[i].resize(allpanes[i]->size_of_real_elements(),false);
1260 
1261  // Loop through real elements.
1262  // Mark for quality check if they contain shared nodes.
1263  int s_real_elems = allpanes[i]->size_of_real_elements();
1264  std::vector<int> nodes;
1265  for(int j=1; j<= s_real_elems; ++j){
1266  Element_node_enumerator ene(allpanes[i],j);
1267  ene.get_nodes(nodes);
1268  for(int k=0, nk=nodes.size(); k<nk; ++k){
1269  if (marked_nodes[i][nodes[k]-1])
1270  marked_elems[i][j-1] = true;
1271  }
1272  }
1273  }
1274 
1275  print_legible(1,"Exiting Rocmop::mark_elems_from_nodes");
1276 #ifdef ROCPROF
1277  Profile_end("Rocmop::mark_elem_node");
1278 #endif
1279 }
1280 
1281 void Rocmop::invert_tets(){
1282 #ifdef ROCPROF
1283  Profile_begin("Rocmop::invert_tets");
1284 #endif
1285  print_legible(1,"Entering Rocmop::invert_tets");
1286  std::vector<Pane*> allpanes;
1287  _buf_window->panes(allpanes);
1288  for(int i=0, ni = allpanes.size(); i<ni; ++i){
1289  MesqPane* mp = new MesqPane(allpanes[i]);
1290  mp->invert();
1291  if(mp)
1292  delete mp;
1293  mp = NULL;
1294  }
1295  _invert = 0;
1296  print_legible(1,"Exiting Rocmop::invert_tets");
1297 #ifdef ROCPROF
1298  Profile_end("Rocmop::invert_tets");
1299 #endif
1300 }
1301 
1302 double Rocmop::check_marked_elem_quality(std::vector<std::vector<bool> > &marked_elems,
1303  std::vector<COM::Pane*> &allpanes){
1304 #ifdef ROCPROF
1305  Profile_begin("Rocmop::check_marked_quality");
1306 #endif
1307  print_legible(1,"Entering Rocmop::check_marked_elems");
1308 
1309  double worst_angle = 0.0;
1310  double angles[] = {0.0, 0.0};
1311  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1312  for(int k =0,nk=allpanes[i]->size_of_real_elements(); k<nk; ++k){
1313  if(marked_elems[i][k]){
1314  Element_node_enumerator ene(allpanes[i],k+1);
1315  Angle_Metric_3 am;
1316  am.initialize(ene);
1317  am.compute(angles);
1318  if(angles[1]>worst_angle)
1319  worst_angle = angles[1];
1320  }
1321  }
1322  }
1323  return worst_angle;
1324 
1325  print_legible(1,"Exiting Rocmop::check_marked_elems");
1326 #ifdef ROCPROF
1327  Profile_end("Rocmop::check_marked_quality");
1328 #endif
1329 }
1330 
1331 double Rocmop::check_all_elem_quality(std::vector<const COM::Pane*> &allpanes,
1332  bool with_ghosts){
1333 
1334 #ifdef ROCPROF
1335  Profile_begin("Rocmop::all_quality_const");
1336 #endif
1337  print_legible(1,"Entering Rocmop::check_all_elem_quality");
1338 
1339  int rank =0;
1340  int ierr = MPI_Comm_rank( _buf_window->get_communicator(),
1341  &rank); assert( ierr == 0);
1342  double worst_angle = 0.0;
1343  double angles[] = {0.0, 0.0};
1344  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1345  int nk=allpanes[i]->size_of_real_elements();
1346  if(with_ghosts)
1347  nk = allpanes[i]->size_of_elements();
1348  for(int k =0; k<nk; ++k){
1349  Element_node_enumerator ene(allpanes[i],k+1);
1350  Angle_Metric_3 am;
1351  am.initialize(ene);
1352  am.compute(angles);
1353  if(angles[1]>worst_angle)
1354  worst_angle = angles[1];
1355  }
1356  }
1357 
1358  agree_double(worst_angle, MPI_MAX);
1359 
1360 #ifdef ROCPROF
1361  Profile_end("Rocmop::all_quality_const");
1362 #endif
1363  return worst_angle;
1364 
1365  print_legible(1,"Exiting Rocmop::check_all_elem_quality");
1366 }
1367 
1368 double Rocmop::check_all_elem_quality(std::vector<COM::Pane*> &allpanes,
1369  bool with_ghosts){
1370 #ifdef ROCPROF
1371  Profile_begin("Rocmop::all_quality");
1372 #endif
1373 
1374  print_legible(1,"Entering Rocmop::check_all_elem_quality");
1375 
1376  if(COMMPI_Initialized()){
1377  int rank =0;
1378  int ierr = MPI_Comm_rank( _buf_window->get_communicator(),
1379  &rank); assert( ierr == 0);
1380  }
1381 
1382  double worst_angle = 0.0;
1383  double angles[] = {0.0, 0.0};
1384  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1385  int nk=allpanes[i]->size_of_real_elements();
1386  if(with_ghosts){
1387  nk = allpanes[i]->size_of_elements();
1388  }
1389  for(int k =0; k<nk; ++k){
1390  Element_node_enumerator ene(allpanes[i],k+1);
1391  Angle_Metric_3 am;
1392  am.initialize(ene);
1393  am.compute(angles);
1394 
1395  if(angles[1]>worst_angle)
1396  worst_angle = angles[1];
1397  }
1398  }
1399 #ifdef ROCPROF
1400  Profile_end("Rocmop::all_quality");
1401 #endif
1402 
1403  return worst_angle;
1404 
1405  print_legible(1,"Exiting Rocmop::check_all_elem_quality");
1406 }
1407 
1408 void Rocmop::print_legible(int verb, const char *msg){
1409  if(_verb > verb){
1410 
1411  int rank =0;
1412 
1413  if(COMMPI_Initialized()){
1414  int ierr = MPI_Comm_rank( _buf_window->get_communicator(),
1415  &rank);
1416  assert( ierr == 0);
1417  }
1418 
1419  if (rank==0)
1420  std::cout << "Rocmop: " << msg << std::endl;
1421  }
1422 }
1423 
1424 void Rocmop::constrain_displacements(COM::Attribute * w_disp){
1425 #ifdef ROCPROF
1426  Profile_begin("Rocmop::const_disp");
1427 #endif
1428 
1429  if(_maxdisp > 0.0){
1430 
1431  int disp_id = w_disp->id();
1432  double max_norm = 0.0;
1433 
1434  std::vector<Pane*> allpanes;
1435  const_cast<COM::Window*>(_usr_window)->panes(allpanes);
1436 
1437  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1438 
1439  Vector_3<double> *ptr = NULL;
1440  COM::Attribute* ptr_att = allpanes[i]->attribute(disp_id);
1441  void* void_ptr = ptr_att->pointer();
1442  ptr = reinterpret_cast<Vector_3<double>*>(void_ptr);
1443 
1444  for(int j=0,nj = allpanes[i]->size_of_real_nodes(); j<nj; ++j){
1445  double norm = ptr[j].norm();
1446  if(norm > max_norm)
1447  max_norm = norm;
1448  }
1449  }
1450 
1451  agree_double(max_norm,MPI_MAX);
1452 
1453  if(max_norm > _maxdisp){
1454  double div = max_norm/_maxdisp;
1455  Rocblas::div_scalar(const_cast<const COM::Attribute*>(w_disp),&div,w_disp);
1456  }
1457  }
1458 #ifdef ROCPROF
1459  Profile_end("Rocmop::const_disp");
1460 #endif
1461 }
1462 
1463 void Rocmop::print_extremal_dihedrals(COM::Window * window){
1464 #ifdef ROCPROF
1465  Profile_begin("Rocmop::ext_dihedrals");
1466 #endif
1467 
1468  // Find the rank of this processor, making sure to only make
1469  // MPI calls on parallel runs
1470  int myrank =0;
1471  if(COMMPI_Initialized()){ // true if in parallel
1472  int ierr = MPI_Comm_rank( window->get_communicator(),
1473  &myrank);
1474  assert( ierr == 0);
1475  }
1476 
1477  // Calculate extremal angles on local panes, and
1478  // record their locations by pane id and element id
1479 
1480  double max_angle = 0.0;
1481  double min_angle = 180.0;
1482  int max_pane = -1; // id of pane w/ the largest dihedral angle
1483  int min_pane = -1; // id of pane w/ the smallest dihedral angle
1484  int max_elem = -1; // id of element w/ the largest dihedral angle
1485  int min_elem = -1; // id of element w/ the smallest dihedral angle
1486  double angles[] = {0.0, 0.0};
1487 
1488  std::vector<Pane*> allpanes;
1489  window->panes(allpanes);
1490 
1491  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1492  for(int k =0,nk=allpanes[i]->size_of_real_elements(); k<nk; ++k){
1493  Element_node_enumerator ene(allpanes[i],k+1);
1494  Angle_Metric_3 am;
1495  am.initialize(ene);
1496  am.compute(angles);
1497  if(angles[1]>max_angle){
1498  max_angle = angles[1];
1499  max_pane = allpanes[i]->id();
1500  max_elem = k+1;
1501  }
1502  if(angles[0]<min_angle){
1503  min_angle = angles[0];
1504  min_pane = allpanes[i]->id();
1505  min_elem = k+1;
1506  }
1507  }
1508  }
1509 
1510  // Find minimum angle across all panes.
1511 
1512  // create MPI_DOUBLE_INT data types for send/recv buffs
1513  struct {
1514  double value;
1515  int rank;
1516  } send, recv;
1517  send.value = min_angle;
1518  send.rank = myrank;
1519 
1520  if(COMMPI_Initialized()){
1521  MPI_Allreduce(&send,&recv,1,MPI_DOUBLE_INT,MPI_MINLOC,
1522  window->get_communicator());
1523  }
1524  if(recv.rank == myrank && _verb > 1){
1525  std::cout << "Rocmop:" << std::endl << "Rocmop: "
1526  << std::setw(10) << min_angle << " on element "
1527  << min_elem << " of pane " << min_pane
1528  << "." << std::endl;
1529  }
1530 
1531  // Sync. output.
1532  if(COMMPI_Initialized()){
1533  MPI_Barrier(window->get_communicator());
1534  }
1535 
1536  // Find maximum angle across all panes.
1537 
1538  send.value = max_angle;
1539 
1540  if(COMMPI_Initialized()){
1541  MPI_Allreduce(&send,&recv,1,MPI_DOUBLE_INT,MPI_MAXLOC,
1542  window->get_communicator());
1543  }
1544  if(recv.rank == myrank && _verb > 1){
1545  std::cout << "Rocmop:" << std::endl << "Rocmop: "
1546  << std::setw(10) << max_angle << " on element "
1547  << max_elem << " of pane " << max_pane << std::endl;
1548  }
1549  // Sync. output.
1550  if(COMMPI_Initialized()){
1551  MPI_Barrier(window->get_communicator());
1552  }
1553 #ifdef ROCPROF
1554  Profile_end("Rocmop::ext_dihedrals");
1555 #endif
1556 
1557 }
1558 
1559 void Rocmop::print_quality(std::string &s,const std::string &s2){
1560 
1561  string outstr("angles.txt");
1562 
1563 
1564  ofstream file;
1565  ofstream file2;
1566 
1567  bool cominit = COMMPI_Initialized();
1568 
1569  int rank =0;
1570  if(cominit){
1571  int ierr = MPI_Comm_rank( _buf_window->get_communicator(),
1572  &rank); assert( ierr == 0);
1573  }
1574 
1575  std::vector<Pane*> allpanes;
1576  _buf_window->panes(allpanes);
1577 
1578  double max_angle = 0.0;
1579  double min_angle = 180.0;
1580  double angles[] = {0.0, 0.0};
1581 
1582  file2.open(s2.c_str());
1583  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1584  for(int k =0,nk=allpanes[i]->size_of_real_elements(); k<nk; ++k){
1585  Element_node_enumerator ene(allpanes[i],k+1);
1586  Angle_Metric_3 am;
1587  am.initialize(ene);
1588  am.compute(angles);
1589  file2 << angles[0] << " " << angles[1] << std::endl;
1590  if(angles[1]>max_angle)
1591  max_angle = angles[1];
1592  if(angles[0]<min_angle)
1593  min_angle = angles[0];
1594  }
1595  }
1596  file2.close();
1597 
1598  agree_double(max_angle,MPI_MAX);
1599  agree_double(min_angle,MPI_MIN);
1600 
1601  if (rank==0){
1602  file.open(outstr.c_str(), std::ios::app);
1603  COM_assertion_msg( file, "File failed to open\n");
1604  file << std::left << std::setw(30) << s << std::setw(0)
1605  << "(" << min_angle << " , " << max_angle << ")\n";
1606  file.close();
1607  }
1608 }
1609 
1610 void Rocmop::print_mquality(std::string &s,
1611  std::vector<std::vector<bool> > &to_check){
1612 
1613  int ierr = 0, rank =0;
1614 
1615  if(COMMPI_Initialized()){
1616  ierr = MPI_Comm_rank( _buf_window->get_communicator()
1617  , &rank);
1618  }
1619  assert( ierr == 0);
1620 
1621 
1622  std::vector<std::vector<bool> > elem_to_check;
1623  mark_elems_from_nodes(to_check, elem_to_check);
1624 
1625  std::vector<Pane*> allpanes;
1626  _buf_window->panes(allpanes);
1627 
1628  double max_angle = 0.0;
1629  double min_angle = 180.0;
1630  double angles[] = {0.0, 0.0};
1631  int id = -1;
1632  for(int i=0,ni = allpanes.size(); i<ni; ++i){
1633  for(int k =0,nk = elem_to_check[i].size(); k<nk; ++k){
1634  if(elem_to_check[i][k]){
1635  Element_node_enumerator ene(allpanes[i],k+1);
1636  Angle_Metric_3 am;
1637  am.initialize(ene);
1638  am.compute(angles);
1639  if(angles[1]>max_angle)
1640  max_angle = angles[1];
1641  if(angles[0]<min_angle){
1642  id = k;
1643  min_angle = angles[0];
1644  }
1645  }
1646  }
1647  }
1648 
1649  double temp = min_angle;
1650 
1651  agree_double(max_angle,MPI_MAX);
1652  agree_double(min_angle,MPI_MIN);
1653 
1654  if (rank==0){
1655  string outstr("angles.txt");
1656  ofstream file (outstr.c_str(), std::ios::app);
1657  COM_assertion_msg( file, "File failed to open\n");
1658 
1659  file << std::left << std::setw(30) << s << std::setw(0)
1660  << "(" << min_angle << " , " << max_angle << ")";
1661 
1662  if(_verb > 1)
1663  std::cout << std::left << std::setw(30) << "Rocmop: " << s
1664  << std::setw(0) << "(" << min_angle << " , "
1665  << max_angle << ")" << std::endl;
1666 
1667  file.close();
1668  }
1669 
1670  if(COMMPI_Initialized())
1671  ierr = MPI_Barrier(_buf_window->get_communicator());
1672  assert( ierr == 0);
1673 
1674  if(min_angle == temp){
1675 
1676  string outstr("angles.txt");
1677  ofstream file (outstr.c_str(), std::ios::app);
1678  COM_assertion_msg( file, "File failed to open\n");
1679 
1680  file << " worst = (" << rank << " , " << id << ")\n";
1681  file.close();
1682  }
1683 
1684  if(COMMPI_Initialized())
1685  ierr = MPI_Barrier(_buf_window->get_communicator());
1686  assert( ierr == 0);
1687 }
1688 
1690 #ifdef ROCPROF
1691  Profile_begin("Rocmop::perturb_stat");
1692 #endif
1693  // first calculate current quality of all nodes.
1694  std::vector<const Pane*> allpanes;
1695  std::vector<const Pane*> allpanes_usr;
1696  _buf_window->panes(allpanes);
1697  _usr_window->panes(allpanes_usr);
1698 
1699  COM::Attribute *w_fgpn_bnd =
1700  _buf_window->attribute("is_fgpn_bnd");
1701  COM::Attribute *w_qual_b_perturb =
1702  _buf_window->attribute("qual_b_perturb");
1703  COM::Attribute *w_qual_a_perturb =
1704  _buf_window->attribute("qual_a_perturb");
1705 
1706  double angles[] = {0.0, 0.0};
1707 
1708  // Get worst quality on local panes
1709  for(int i=0,ni=allpanes.size(); i<ni; ++i){
1710 
1711  COM::Attribute *p_fgpn_bnd =
1712  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_fgpn_bnd->id()));
1713  COM::Attribute *p_qual_b_perturb =
1714  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_qual_b_perturb->id()));
1715 
1716  int* fgpn_bnd_ptr = reinterpret_cast<int*>(p_fgpn_bnd->pointer());
1717  double* qual_b_perturb_ptr =
1718  reinterpret_cast<double*>(p_qual_b_perturb->pointer());
1719 
1720  std::vector<int> elist;
1721  // only worry about real nodes, ghost nodes should be fixed
1722  for(int j=0, nj= allpanes[i]->size_of_real_nodes(); j<nj; ++j){
1723  if(fgpn_bnd_ptr[j]){
1724  _dcs[i]->incident_elements(j+1,elist);
1725  qual_b_perturb_ptr[j] = 0.0;
1726  for(uint k=0, nk=elist.size(); k<nk; ++k){
1727  Element_node_enumerator ene(allpanes[i],k+1);
1728  Angle_Metric_3 am;
1729  am.initialize(ene);
1730  am.compute(angles);
1731  if(angles[1]>qual_b_perturb_ptr[j])
1732  qual_b_perturb_ptr[j] = angles[1];
1733  }
1734  }
1735  }
1736  }
1737 
1738  // Get the worst quality across all panes
1739  if(COMMPI_Initialized()){
1740  MAP::Pane_communicator pc(_buf_window, _buf_window->get_communicator());
1741  pc.init(w_qual_b_perturb);
1742  pc.begin_update_shared_nodes();
1743  pc.reduce_on_shared_nodes(MPI_MAX);
1744  pc.end_update_shared_nodes();
1745  }
1746 
1747  // Now generate random perturbations
1748  for(int i=0,ni=allpanes.size(); i<ni; ++i){
1749 
1750  COM::Attribute *p_fgpn_bnd =
1751  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_fgpn_bnd->id()));
1752  COM::Attribute *p_nc =
1753  const_cast<COM::Attribute*>(allpanes[i]->attribute(COM::COM_NC));
1754 
1755  int* fgpn_bnd_ptr =
1756  reinterpret_cast<int*>(p_fgpn_bnd->pointer());
1757  Vector_3<double>* nc_ptr =
1758  reinterpret_cast<Vector_3<double>*>(p_nc->pointer());
1759 
1760  std::vector<int> elist;
1761  // only worry about real nodes, ghost nodes should be fixed
1762  for(int j=0, nj= (int)allpanes[i]->size_of_real_nodes(); j<nj; ++j){
1763 
1764  if(fgpn_bnd_ptr[j]){
1765  _dcs[i]->incident_elements(j+1,elist);
1766 
1767  if(_verb > 1)
1768  std::cout << "Rocmop: Perturbing node " << j+1 << std::endl;
1769 
1770  //select a random element
1771  int rand_el = (std::rand()%elist.size());
1772  Element_node_enumerator ene(allpanes[i],elist[rand_el]);
1773  std::vector<int> enodes;
1774  ene.get_nodes(enodes);
1775 
1776  // get length of a randomly selected incident edge of the element
1777  int rand_ed = (std::rand()%3)+1;
1778  int nindex = 0;
1779  for(int nk= (int)enodes.size(); nindex<nk; ++nindex){
1780  if(enodes[nindex]==j+1)
1781  break;
1782  }
1783 
1784  COM_assertion_msg((nindex>=0 && nindex<= (int)enodes.size()),
1785  "Node not found in supposedly adjacent element\n");
1786  double length = (nc_ptr[j]-nc_ptr[enodes[(nindex+rand_ed)%4]-1]).norm();
1787 
1788  Vector_3<double> perturb(length,length,length);
1789  for(int k=0; k<3; ++k){
1790  perturb[0] *= (std::rand()%2 == 0) ?
1791  (double)((std::rand()%1000)+1)/1000.0 :
1792  -1.0*((double)((std::rand()%1000)+1)/1000.0);
1793  }
1794  nc_ptr[j] += perturb;
1795  }
1796  }
1797  }
1798 
1799  // Get perturbed worst quality on local panes
1800  for(int i=0,ni=(int)allpanes.size(); i<ni; ++i){
1801 
1802  COM::Attribute *p_fgpn_bnd =
1803  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_fgpn_bnd->id()));
1804  COM::Attribute *p_qual_a_perturb =
1805  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_qual_a_perturb->id()));
1806 
1807  int* fgpn_bnd_ptr =
1808  reinterpret_cast<int*>(p_fgpn_bnd->pointer());
1809  double* qual_a_perturb_ptr =
1810  reinterpret_cast<double*>(p_qual_a_perturb->pointer());
1811 
1812  std::vector<int> elist;
1813  // only worry about real nodes, ghost nodes should be fixed
1814  for(int j=0, nj= (int)allpanes[i]->size_of_real_nodes(); j<nj; ++j){
1815  if(fgpn_bnd_ptr[j]){
1816  _dcs[i]->incident_elements(j+1,elist);
1817  qual_a_perturb_ptr[j] = 0.0;
1818  for(int k=0, nk=(int)elist.size(); k<nk; ++k){
1819  Element_node_enumerator ene(allpanes[i],k+1);
1820  Angle_Metric_3 am;
1821  am.initialize(ene);
1822  am.compute(angles);
1823  if(angles[1]>qual_a_perturb_ptr[j])
1824  qual_a_perturb_ptr[j] = angles[1];
1825  }
1826  }
1827  }
1828  }
1829 
1830  // Get the perturbed worst quality across all panes
1831  if(COMMPI_Initialized()){
1832  MAP::Pane_communicator pc(_buf_window, _buf_window->get_communicator());
1833  pc.init(w_qual_a_perturb);
1834  pc.begin_update_shared_nodes();
1835  pc.reduce_on_shared_nodes(MPI_MAX);
1836  pc.end_update_shared_nodes();
1837  }
1838 
1839  // Reset positions of any nodes whose worst adj. element quality
1840  // has gotten worse.
1841  for(int i=0,ni=allpanes.size(); i<ni; ++i){
1842 
1843  COM::Attribute *p_fgpn_bnd =
1844  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_fgpn_bnd->id()));
1845  COM::Attribute *p_nc =
1846  const_cast<COM::Attribute*>(allpanes[i]->attribute(COM::COM_NC));
1847  COM::Attribute *p_nc_usr =
1848  const_cast<COM::Attribute*>(allpanes_usr[i]->attribute(COM::COM_NC));
1849 
1850  COM::Attribute *p_qual_b_perturb =
1851  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_qual_b_perturb->id()));
1852  COM::Attribute *p_qual_a_perturb =
1853  const_cast<COM::Attribute*>(allpanes[i]->attribute(w_qual_a_perturb->id()));
1854 
1855  int* fgpn_bnd_ptr =
1856  reinterpret_cast<int*>(p_fgpn_bnd->pointer());
1857  Vector_3<double>* nc_ptr =
1858  reinterpret_cast<Vector_3<double>*>(p_nc->pointer());
1859  Vector_3<double>* nc_ptr_usr =
1860  reinterpret_cast<Vector_3<double>*>(p_nc_usr->pointer());
1861  double* qual_b_perturb_ptr =
1862  reinterpret_cast<double*>(p_qual_b_perturb->pointer());
1863  double* qual_a_perturb_ptr =
1864  reinterpret_cast<double*>(p_qual_a_perturb->pointer());
1865 
1866  // only worry about real nodes, ghost nodes should be fixed
1867 for(int j=0, nj= (int)allpanes[i]->size_of_real_nodes(); j<nj; ++j){
1868  if(fgpn_bnd_ptr[j] &&
1869  (qual_a_perturb_ptr[j] > qual_b_perturb_ptr[j]))
1870  nc_ptr[j] = nc_ptr_usr[j];
1871  }
1872  }
1873 #ifdef ROCPROF
1874  Profile_end("Rocmop::perturb_stat");
1875 #endif
1876 }
1877 
1878 
1879 extern "C" void Rocmop_load_module( const char *mname)
1880 { Rocmop::load( mname); }
1881 
1882 extern "C" void Rocmop_unload_module( const char *mname)
1883 { Rocmop::unload( mname); }
1884 
1885 // Fortran bindings
1886 extern "C" void COM_F_FUNC2(rocmop_load_module, ROCMOP_LOAD_MODULE)( const char *mname, long int length)
1887 { Rocmop::load( std::string(mname, length)); }
1888 
1889 extern "C" void COM_F_FUNC2(rocmop_unload_module, ROCMOP_UNLOAD_MODULE)( const char *mname, long int length)
1890 { Rocmop::unload( std::string(mname, length)); }
1891 
1893 
1894 
1895 
1896 
1897 
1898 
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
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
void smooth_in_place(COM::Attribute *pmesh)
Smooth a mesh in place..
Definition: Rocmop.C:204
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 invert_tets()
Repair inverted tets.
Definition: Rocmop.C:748
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
This file contains the prototypes for Roccom API.
3D geometric quality Metric declarations.
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 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
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 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
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