Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Rocmop.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.C,v 1.3 2008/12/06 08:45:25 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 "MesquiteError.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 "EdgeLengthQualityMetric.hpp"
41 #include "LPtoPTemplate.hpp"
42 #include "FeasibleNewton.hpp"
43 #include "ConjugateGradient.hpp"
44 #include "MsqMessage.hpp"
45 #include "MesqPane.h"
46 
47 using namespace Mesquite;
48 #endif
49 
50 #include "Rocblas.h"
51 #include "Rocmop.h"
52 #include "Rocmap.h"
53 #include "roccom.h"
54 #include "Pane_communicator.h"
55 #include "Pane_connectivity.h"
56 #include "Geometric_Metrics_3.h"
57 #include "PN_patch.h"
58 #include "geometry.h"
59 #include "mapbasic.h"
60 
61 // for debugging
62 #include <iostream>
63 #include <iomanip>
64 #include <fstream>
65 using namespace std;
66 // end for debugging
67 
69 
70 using MAP::Pane_connectivity;
71 using MAP::Pane_communicator;
72 using MAP::Rocmap;
73 using std::cout;
74 using std::endl;
75 
77  if(_verb)
78  cout << "Entering Rocmop::~Rocmop\n";
79 
80  if (_wrk_window) {
81  delete _wrk_window; _wrk_window = NULL;
82  }
83 
84  if(_verb > 1)
85  cout << "Exiting Rocmop::~Rocmop\n";
86 }
87 
88 void Rocmop::load( const std::string &mname) {
89 
90  Rocmop *mop = new Rocmop();
91 
92  COM_new_window( mname.c_str());
93 
94  std::string glb=mname+".global";
95 
96  COM_new_attribute( glb.c_str(), 'w', COM_VOID, 1, "");
97  COM_set_object( glb.c_str(), 0, mop);
98 
99  COM_Type types[3];
100  types[0] = COM_RAWDATA; types[1] = COM_METADATA;
101  types[2] = COM_METADATA;
102 
103  COM_set_member_function( (mname+".smooth").c_str(),
104  (Member_func_ptr)(&Rocmop::smooth),
105  glb.c_str(), "biB", types);
106 
107  COM_set_member_function( (mname+".smooth_in_place").c_str(),
108  (Member_func_ptr)(&Rocmop::smooth_in_place),
109  glb.c_str(), "bb", types);
110 
111  types[1] = COM_STRING; types[2] = COM_VOID;
112  COM_set_member_function( (mname+".set_value").c_str(),
113  (Member_func_ptr)(&Rocmop::set_value),
114  glb.c_str(), "bii", types);
115 
116  COM_window_init_done( mname.c_str());
117 
118 }
119 
120 void Rocmop::unload( const std::string &mname) {
121 
122  Rocmop *mop;
123  std::string glb=mname+".global";
124 
125  COM_get_object( glb.c_str(), 0, &mop);
126  delete mop;
127 
128  COM_delete_window( mname.c_str());
129 
130 }
131 
132 void Rocmop::smooth(const COM::Attribute *pmesh,
133  COM::Attribute *disp){
134  COM_assertion_msg( validate_object()==0, "Invalid object");
135  if(_verb)
136  cout << "Entering Rocmop::smooth\n";
137 
138  int pmesh_id = pmesh->id();
139  COM_assertion_msg( pmesh &&
140  (pmesh_id==COM::COM_PMESH || pmesh_id==COM::COM_MESH),
141  "Input to Rocmop::smooth must be a pmesh.");
142  _is_pmesh = (pmesh_id == COM_PMESH) ? true : false;
143 
144  if(_wrk_window) delete _wrk_window;
145  _usr_window = pmesh->window();
146 
147  // Create a buffer window by inheriting(clone) from the user's mesh.
148  if (_verb >3)
149  std::cout << " Creating(clone) buffer window." << std::endl;
150  std::string buf_name(_usr_window->name()+"-Rocmopbuf");
151  _wrk_window = new COM::Window(buf_name,
152  _usr_window->get_communicator());
153  _wrk_window->inherit( const_cast<COM::Attribute*>(pmesh), "",
154  COM::Pane::INHERIT_CLONE, true, NULL, 0);
155  _wrk_window->init_done();
156 
157  std::vector<const Pane*> allpanes;
158  _wrk_window->panes(allpanes);
159 
160  double pre_worst = 180.0, post_worst = 0.0;
161 
162  // Check initial quality if we are in lazy or monotone mode
163  if(_monotone || _lazy){
164  pre_worst = check_all_elem_quality(allpanes);
165  // get the worst pre smoothing quality across all panes
166  agree_double(pre_worst, MPI_MAX);
167  }
168 
169  bool to_smooth = (!_lazy || (pre_worst > 180.*_tol));
170 
171  int degraded = 0;
172  if (to_smooth){
173  perform_smoothing(pre_worst);
174 
175  // Check final mesh quality if a tolerance is set, or we're in monotonic mode
176  if(_monotone || (_tol!=0.0)){
177  post_worst = check_all_elem_quality(allpanes);
178  agree_double(post_worst, MPI_MAX);
179  }
180 
181  // If in monotone mode, see if quality degraded on any pane
182  if(_monotone && (pre_worst > post_worst)){
183  cerr << "Warning, smoothing would have degraded mesh quality \n"
184  << "so the mesh has not been modified.\n";
185  degraded = 1;
186  }
187 
188  // Warn the user if could not reach a specified minimum mesh quality.
189  if(_tol && (post_worst < _tol)){
190  cerr << "Warning, post-smoothing mesh quality is below specified minimum "
191  << "quality \n";
192  }
193  }
194 
195  const COM::Attribute *old_nc = pmesh->window()->attribute( COM::COM_NC);
196  const COM::Attribute *new_nc = (degraded || !to_smooth) ?
197  old_nc :_wrk_window->attribute( COM::COM_NC);
198  Rocblas::sub (new_nc, old_nc, disp);
199 
200  if (_verb > 1)
201  std::cout << "Exiting rocmop::smooth" << std::endl;
202 }
203 
204 void Rocmop::smooth_in_place(COM::Attribute *pmesh){
205  COM_assertion_msg( validate_object()==0, "Invalid object");
206  if (_verb)
207  std::cout << "Entering rocmop::smooth_in_place" << std::endl;
208 
209  int pmesh_id = pmesh->id();
210 
211  COM_assertion_msg( pmesh &&
212  (pmesh_id==COM::COM_PMESH || pmesh_id==COM::COM_MESH) ,
213  "Input to Rocmop::smooth_in_place must be a mesh or pmesh");
214 
215  if(_wrk_window)
216  delete _wrk_window;
217  _usr_window = pmesh->window();
218 
219  // FIXME
220  // Create a buffer window by inheriting(use) from the user's mesh.
221  // can't use the _usr_window directly because of problems with
222  // Element_node_enumerator
223  _wrk_window = new COM::Window(_usr_window->name()+"-Rocmopbuf",
224  _usr_window->get_communicator());
225  _wrk_window->inherit( const_cast<COM::Attribute*>(pmesh), "",
226  false, true, NULL, 0);
227  _wrk_window->init_done();
228 
229  std::vector<const Pane*> allpanes;
230  _wrk_window->panes(allpanes);
231 
232  double pre_worst = 180.0, post_worst = 0.0;
233 
234  // Check initial quality if we are in lazy or monotone mode
235  if(_monotone || _lazy) {
236  pre_worst = check_all_elem_quality(allpanes);
237  // get the worst pre smoothing quality on all panes
238  agree_double(pre_worst, MPI_MIN);
239  }
240 
241  bool to_smooth = (!_lazy || (pre_worst > 180.*_tol));
242 
243  if (to_smooth){
244  perform_smoothing(pre_worst);
245 
246  // Check final mesh quality if a tolerance is set, or we're in monotonic mode
247  if(_monotone || (_tol!=0.0)){
248  post_worst = check_all_elem_quality(allpanes);
249  agree_double(post_worst, MPI_MIN);
250  }
251 
252  // If in monotone mode, see if quality degraded on any pane
253  if(_monotone && (pre_worst > post_worst))
254  cerr << "Warning, mesh quality degraded during smoothing in place." << endl;
255 
256  // If a quality tolerance is set, and we didn't meet it, then warn
257  if(_tol && (post_worst < _tol)){
258  cerr << "Warning, post-smoothing mesh quality is below specified minimum "
259  << "quality \n";
260  }
261  }
262 
263  if (_wrk_window){ delete _wrk_window;_wrk_window = NULL;}
264 
265  if (_verb > 1)
266  std::cout << "Exiting rocmop::smooth_in_place" << std::endl;
267 }
268 
269 void Rocmop::perform_smoothing(double pre_quality){
270  if(_verb)
271  std::cout << " Entering Rocmop::perform_smoothing" << std::endl;
272 
273  COM_assertion_msg(_wrk_window, "Unexpected NULL pointer encountered.");
274 
275  // Perform initialization specific to the smoother.
276  smoother_specific_init();
277 
278  // Select iterative or noniterative option depending on the smoother.
279  if (0) // No noniterative smoothers currently
280  perform_noniterative_smoothing();
281  else if( _method < SMOOTH_NONE)
282  perform_iterative_smoothing(pre_quality);
283  else
284  COM_assertion_msg(0, "No valid smoothing method selected");
285 
286  if(_verb)
287  std::cout << " Exiting Rocmop::perform_smoothing" << std::endl;
288 }
289 
290 void Rocmop::perform_iterative_smoothing(double pre_quality){
291  if(_verb)
292  std::cout << " Entering Rocmop::perform_iterative_smoothing" << std::endl;
293 
294  COM_assertion_msg(_wrk_window, "Unexpected NULL pointer encountered.");
295 
296  // bool_iter is true until the max number of iterations (_niter)
297  // is reached or the minimum quality (_tol) is reached.
298  int to_iter = true;
299  std::vector<const Pane*> allpanes;
300  _wrk_window->panes(allpanes);
301  double cur_qual = pre_quality;
302 
303  for(int i = 0;
304  ( (i < _niter) && (to_iter) );
305  ++i, agree_int(to_iter, MPI_MIN)){
306 
307  if(_verb > 2)
308  std::cout << " Smoothing iteration " << i << std::endl;
309 
310 #ifdef MESQUITE
311  if(_method==SMOOTH_VOL_MESQ_WG){
312  //std::string msg("\nQuality prior to smoothing = ");
313  //print_quality(msg);
314  smooth_vol_mesq_wg(cur_qual);
315  }
316  // else if(_method == SMOOTH_LAPLACE)
317  // smooth_laplace();
318  else if(_method == SMOOTH_VOL_MESQ_NG){
319  //std::string msg("Quality prior to smoothing = ");
320  //print_quality(msg);
321  smooth_vol_mesq_ng(cur_qual);
322  }
323 #else
324  if((_method==SMOOTH_VOL_MESQ_WG) || (_method==SMOOTH_VOL_MESQ_NG))
325  COM_assertion_msg(0,"Rocmop not compiled with MESQUITE");
326 #endif
327  else if(_method==SMOOTH_SURF_MEDIAL)
328  smooth_surf_medial();
329  else COM_assertion_msg(0, "No valid iterative smoothing method selected");
330 
331  // If a non zero quality tolerance is set, then determine if quality
332  // is low enough to warrant smoothing.
333  if( _tol != 0.0 ){
334  cur_qual = check_all_elem_quality(allpanes);
335  if(cur_qual >= _tol)
336  to_iter = false;
337  }
338  }
339 
340  if(_verb > 1)
341  std::cout << " Exiting Rocmop::perform_iterative_smoothing" << std::endl;
342 }
343 
345  if(_verb)
346  std::cout << " Entering Rocmop::perform_noniterative_smoothing" << std::endl;
347 
348  if(_niter != 1){
349  std::cerr << "Although the maximum number of iterations > 1 is selected,\n"
350  << "the smoothing method is noniterative, and will run once.\n";
351  }
352 
353  if (0)
354  ;// Currently, no noniterative methods exist.
355  else COM_assertion_msg(0, "No valid noniterative smoothing method selected");
356 
357  if(_verb > 1)
358  std::cout << " Exiting Rocmop::perform_noniterative_smoothing" << std::endl;
359 }
360 
361 // Perform smoother specific initializing, for example initializing the
362 // Window_manifold_2 for a surface mesh, adding smoother specific attributes
363 // to the window, etc.
365  if(_verb)
366  std::cout << " Entering Rocmop::smoother_specific_init" << std::endl;
367 
368  // get rid of any old data
369  if(_wm){ delete _wm; _wm = NULL; }
370 
371  // perform initialization common to surface smoothers
372  if(_method==SMOOTH_SURF_MEDIAL){
373  // Initialize the Window_manifold
374  if(_wm == NULL)
375  Rocsurf::initialize(_wrk_window->attribute(_is_pmesh ? COM_PMESH : COM_MESH));
376 
377  }
378 
379  // perform smoother specific initialization
380  switch (_method){
381 
382 #ifdef MESQUITE
383  case SMOOTH_VOL_MESQ_WG: {
384  // Obtain a list of elements containing shared nodes for each pane.
385  // Don't bother if _ctol == 0 or _ncycle ==1
386  // if(!(_ctol==0.) && !(_ncycle==1))
387  determine_shared_border();
388  if(_invert)
389  invert_tets();
390  break;
391  }
392  case SMOOTH_VOL_MESQ_NG: {
393 
394  // Check to see if the physical surface boundary exists
395  const std::string surf_attr("is_surface");
396  const COM::Attribute *w_is_surface = _usr_window->attribute(surf_attr);
397  if(w_is_surface){
398 
399  COM_assertion_msg( COM_compatible_types( w_is_surface->data_type(), COM_INT),
400  "Surface-list must have integer type");
401  COM_assertion_msg( w_is_surface->is_nodal() == 1,
402  "Surface-list must be nodal");
403  COM_assertion_msg( w_is_surface->size_of_components() == 1,
404  "Surface-list must have a single component");
405  COM_assertion_msg( w_is_surface->initialized() == 1,
406  "Surface-list must be initialized");
407 
408  // Clone the attribute
409  COM::Attribute * new_attr =
410  _wrk_window->inherit( const_cast<COM::Attribute *>(w_is_surface),
411  surf_attr, COM::Pane::INHERIT_CLONE, true, NULL, 0);
412  }
413  // else, detect the physical boundary ourselves
414  else{
415  COM::Attribute* w_surf_attr =
416  _wrk_window->new_attribute( "is_surface", 'n', COM_INT, 1, "");
417  _wrk_window->resize_array( w_surf_attr, 0);
418 
419  determine_physical_border(w_surf_attr);
420  }
421  _wrk_window->init_done();
422 
423  if(_invert)
424  invert_tets();
425  break;
426  }
427 #else
428  case SMOOTH_VOL_MESQ_WG:
429  case SMOOTH_VOL_MESQ_NG:
430  COM_assertion_msg(0, "Not compiled with MESQUITE");
431  break;
432 #endif
433 
434  case SMOOTH_SURF_MEDIAL: {
435 
436  // Extend buffer window
437  COM::Attribute* w_disps =
438  _wrk_window->new_attribute( "disps", 'n', COM_DOUBLE, 3, "");
439  _wrk_window->resize_array( w_disps, 0);
440 
441  COM::Attribute* w_facenormals =
442  _wrk_window->new_attribute( "facenormals", 'e', COM_DOUBLE, 3, "");
443  _wrk_window->resize_array( w_facenormals, 0);
444 
445  COM::Attribute* w_facecenters =
446  _wrk_window->new_attribute( "facecenters", 'e', COM_DOUBLE, 3, "");
447  _wrk_window->resize_array( w_facecenters, 0);
448 
449  COM::Attribute* w_eigvalues =
450  _wrk_window->new_attribute( "lambda", 'n', COM_DOUBLE, 3, "");
451  _wrk_window->resize_array( w_eigvalues, 0);
452 
453  COM::Attribute* w_vnormals =
454  _wrk_window->new_attribute( "vnormals", 'n', COM_DOUBLE, 3, "");
455  _wrk_window->resize_array( w_vnormals, 0);
456 
457  COM::Attribute* w_awnormals =
458  _wrk_window->new_attribute( "awnormals", 'n', COM_DOUBLE, 3, "");
459  _wrk_window->resize_array( w_awnormals, 0);
460 
461  COM::Attribute* w_uwnormals =
462  _wrk_window->new_attribute( "uwnormals", 'n', COM_DOUBLE, 3, "");
463  _wrk_window->resize_array( w_uwnormals, 0);
464 
465  COM::Attribute* w_eigvecs =
466  _wrk_window->new_attribute( "eigvecs", 'n', COM_DOUBLE, 9, "");
467  _wrk_window->resize_array( w_eigvecs, 0);
468 
469  COM::Attribute* w_tangranks =
470  _wrk_window->new_attribute( "tangranks", 'n', COM_INT, 1, "");
471  _wrk_window->resize_array( w_tangranks, 0);
472 
473  COM::Attribute* w_cntnranks =
474  _wrk_window->new_attribute( "cntnranks", 'n', COM_INT, 1, "");
475  _wrk_window->resize_array( w_cntnranks, 0);
476 
477  COM::Attribute* w_cntnvecs =
478  _wrk_window->new_attribute( "cntnvecs", 'n', COM_DOUBLE, 6, "");
479  _wrk_window->resize_array( w_cntnvecs, 0);
480 
481  COM::Attribute* w_scales =
482  _wrk_window->new_attribute( "scales", 'n', COM_DOUBLE, 1, "");
483  _wrk_window->resize_array( w_scales, 0);
484 
485  COM::Attribute* w_weights =
486  _wrk_window->new_attribute( "weights", 'n', COM_DOUBLE, 1, "");
487  _wrk_window->resize_array( w_weights, 0);
488 
489  COM::Attribute* w_weights2 =
490  _wrk_window->new_attribute( "weights2", 'n', COM_DOUBLE, 1, "");
491  _wrk_window->resize_array( w_weights2, 0);
492 
493  COM::Attribute* w_barycrds =
494  _wrk_window->new_attribute( "barycrds", 'n', COM_DOUBLE, 2, "");
495  _wrk_window->resize_array( w_barycrds, 0);
496 
497  COM::Attribute* w_PNelemids =
498  _wrk_window->new_attribute( "PNelemids", 'n', COM_INT, 1, "");
499  _wrk_window->resize_array( w_PNelemids, 0);
500 
501  // Extend the buffer window to hold local contributions to new placement
502  // and the number of contributing faces for Laplacian smoothing.
503  COM::Attribute * w_pnt_contrib =
504  _wrk_window->new_attribute("pnt_contrib", 'n', COM_DOUBLE, 3, "");
505  _wrk_window->resize_array(w_pnt_contrib, 0);
506 
507  COM::Attribute * w_disp_count =
508  _wrk_window->new_attribute("disp_count", 'n', COM_DOUBLE, 1, "");
509  _wrk_window->resize_array(w_disp_count, 0);
510 
511  _wrk_window->init_done();
512 
513  break;
514  }
515  // case SMOOTH_LAPLACE : {
516  //break;
517  //}
518  default:
519  COM_assertion_msg(0, "Can't initialize for invalid smoother.");
520  break;
521  }
522 
523  COM_assertion_msg(_wrk_window, "Unexpected NULL pointer encountered.");
524 
525  if(_verb > 1)
526  std::cout << " Exiting Rocmop::smoother_specific_init" << std::endl;
527 }
528 
529 void Rocmop::set_value(const char* opt, const void* value)
530 {
531  if(_verb)
532  std::cout << "Entering Rocmop::set_value" << std::endl;
533 
534  COM_assertion_msg( validate_object()==0, "Invalid object");
535 
536  COM_assertion_msg( opt && value,
537  "Rocmop::set_value does not except NULL parameters");
538  std::string option;
539  if(opt) option = opt;
540  if ( option == "method") {
541  COM_assertion_msg( *((int*)value) <= SMOOTH_NONE && *((int*)value)>=0
542  ,"Illegal value for 'method' option");
543  _method = *((int*)value);
544  }
545  else if ( option == "verbose"){
546  _verb = *((int*)value); }
547  else if ( option == "lazy"){
548  _lazy = *((int*)value); }
549  else if ( option == "tol"){
550  COM_assertion_msg( *((float*)value) <= 180. && *((float*)value)>=0.
551  ,"Illegal value for 'method' option");
552  _tol = *((float*)value); }
553  else if ( option == "niter"){
554  _niter = *((int*)value); }
555  else if ( option == "ctol"){
556  COM_assertion_msg( *((float*)value) <= 1. && *((float*)value)>=0.
557  ,"Illegal value for 'method' option");
558  _ctol = *((float*)value); }
559  else if ( option == "ncycle"){
560  _ncycle = *((int*)value); }
561  else if ( option == "inverted"){
562  _invert = *((int*)value);
563  }
564  else COM_assertion_msg( false, "Unknown option");
565 
566  if(_verb > 1)
567  std::cout << "Exiting Rocmop::set_value" << std::endl;
568 }
569 
570 void Rocmop::smooth_mesquite(std::vector<COM::Pane*> &allpanes,
571  int ghost_level){
572 
573  Mesquite::MsqError err;
574  MesqPane *mp;
575  ShapeImprovementWrapper mesh_quality_algorithm;
576 
577  int total_npanes = (int)allpanes.size();
578  bool wg = (ghost_level == 0) ? false : true;
579  for(int j=0; j < total_npanes; ++j){
580  MeshSet* mesh_set1 = new MeshSet;
581  mp = new MesqPane(allpanes[j], wg);
582  if(_verb > 4)
583  mp->set_verb(_verb - 4);
584  mesh_set1->add_mesh(mp, err);
585  MSQ_CHKERR(err);
586  mesh_quality_algorithm.run_instructions(*mesh_set1, err);
587  MSQ_CHKERR(err);
588  delete mesh_set1;
589  if(mp)
590  delete mp;
591  mp = NULL;
592  }
593 }
594 
595 void Rocmop::reduce_sum_on_shared_nodes(COM::Attribute *att){
596  Pane_communicator pc(att->window(), att->window()->get_communicator());
597  pc.init(att);
598  pc.begin_update_shared_nodes();
599  pc.reduce_on_shared_nodes(MPI_SUM);
600  pc.end_update_shared_nodes();
601 }
602 
604  if(_verb)
605  std::cout << "Entering Rocmop::determine_pane_border" << std::endl;
606 
607  std::vector<const COM::Pane*> allpanes;
608  _wrk_window->panes(allpanes);
609  int local_npanes = (int)allpanes.size();
610 
611  _is_pane_bnd_node.resize(local_npanes);
612  _is_pane_bnd_elem.resize(local_npanes);
613 
614  for(int i=0; i< local_npanes; ++i){
615  int size_of_real_nodes = allpanes[i]->size_of_real_nodes();
616  int size_of_real_elems = allpanes[i]->size_of_real_elements();
617  _is_pane_bnd_node[i].resize(size_of_real_nodes,0);
618 
619  std::vector<bool> is_isolated; // is a node isolated?
620  MAP::Pane_boundary pb (allpanes[i]);
621  pb.determine_border_nodes(_is_pane_bnd_node[i], is_isolated);
622  }
623 
624  mark_elems_from_nodes(_is_pane_bnd_node,_is_pane_bnd_elem);
625 
626  if(_verb > 1)
627  std::cout << "Exiting Rocmop::determine_pane_border" << std::endl;
628 }
629 
630 
632  if(_verb)
633  std::cout << "Entering Rocmop::determine_shared_nodes" << std::endl;
634 
635  std::vector<const COM::Pane*> allpanes;
636  _wrk_window->panes(allpanes);
637  int local_npanes = (int)allpanes.size();
638 
639  _is_shared_node.resize(local_npanes);
640 
641  //First, get the list of shared nodes.
642  for(int i=0; i < (int)(local_npanes); ++i){
643  // Obtain the pane connectivity of the local pane.
644  const COM::Attribute *pconn = allpanes[i]->attribute(COM::COM_PCONN);
645  // Use the pconn offset
646  const int *vs = (const int*)pconn->pointer()+Pane_connectivity::pconn_offset();
647  int vs_size=pconn->size_of_real_items()-Pane_connectivity::pconn_offset();
648  _is_shared_node[i].resize(allpanes[i]->size_of_real_nodes(),0);
649 
650  // Determine the number of communicating panes for shared nodes.
651  int count=0;
652  for (int j=0, nj=vs_size; j<nj; j+=vs[j+1]+2) {
653  if (_wrk_window->owner_rank( vs[j]) >=0) ++count;
654  }
655 
656  int index = 0;
657  // Loop through communicating panes for shared nodes.
658  for ( int j=0; j<count; ++j, index+=vs[index+1]+2) {
659  // We skip the panes that are not in the current window
660  while ( _wrk_window->owner_rank(vs[index])<0) {
661  index+=vs[index+1]+2;
662  COM_assertion_msg( index<=vs_size, "Invalid communication map");
663  }
664  // Add shared nodes to the list
665  for(int k=0; k<vs[index+1]; ++k){
666  _is_shared_node[i][vs[index+2+k]-1] = 1;
667  }
668  }
669  }
670 
671  mark_elems_from_nodes(_is_shared_node,_is_shared_elem);
672 
673  if(_verb > 1)
674  std::cout << "Exiting Rocmop::determine_shared_nodes" << std::endl;
675 }
676 
678  if(_verb)
679  std::cout << "Entering Rocmop::determine_physical_border()" << std::endl;
680 
681  const std::string surf_attr("is_surface");
682  COM::Attribute* w_is_surface = _wrk_window->attribute(surf_attr);
683  COM_assertion_msg( w_is_surface, "Unexpected NULL pointer");
684  int is_surface_id = w_is_surface->id();
685 
686  std::vector<const COM::Pane*> allpanes;
687  _wrk_window->panes(allpanes);
688  int local_npanes = (int)allpanes.size();
689 
690  _is_pane_bnd_node.resize(local_npanes);
691 
692  for(int i=0; i < local_npanes; ++i){
693  _is_pane_bnd_node[i].resize(allpanes[i]->size_of_real_nodes());
694 
695  // get pane level pointer to physical border property.
696  const COM::Attribute *p_is_surface = allpanes[i]->attribute(is_surface_id);
697  int *is_surface_ptr = (int*)p_is_surface->pointer();
698 
699  // loop through real nodes
700  for(int j=0; j< allpanes[i]->size_of_real_nodes(); ++j){
701  if (is_surface_ptr[j])
702  _is_pane_bnd_node[i][j] = true;
703  }
704  }
705 
706  mark_elems_from_nodes(_is_pane_bnd_node,_is_pane_bnd_elem);
707 
708  if(_verb > 1)
709  std::cout << "Exiting Rocmop::determine_physical_border()" << std::endl;
710 }
711 
712 void Rocmop::mark_elems_from_nodes(std::vector<std::vector<bool> > &marked_nodes,
713  std::vector<std::vector<bool> > &marked_elems){
714  if(_verb)
715  std::cout << "Entering Rocmop::mark_elems_from_nodes" << std::endl;
716 
717  std::vector<const COM::Pane*> allpanes;
718  _wrk_window->panes(allpanes);
719  int local_npanes = (int)allpanes.size();
720 
721  marked_elems.clear();
722  marked_elems.resize(local_npanes);
723 
724  //Loop through panes
725  for(int i=0; i < (int)(local_npanes); ++i){
726 
727  marked_elems[i].clear();
728  marked_elems[i].resize(allpanes[i]->size_of_real_elements(),false);
729 
730  // Loop through real elements.
731  // Mark for quality check if they contain shared nodes.
732  int s_real_elems = allpanes[i]->size_of_real_elements();
733  std::vector<int> nodes;
734  for(int j=1; j<= s_real_elems; ++j){
735  Element_node_enumerator ene(allpanes[i],j);
736  ene.get_nodes(nodes);
737  for(int k=0, nk=nodes.size(); k<nk; ++k){
738  if (marked_nodes[i][nodes[k]-1])
739  marked_elems[i][j-1] = true;
740  }
741  }
742  }
743 
744  if(_verb > 1)
745  std::cout << "Exiting Rocmop::mark_elems_from_nodes" << std::endl;
746 }
747 
749  std::vector<Pane*> allpanes;
750  _wrk_window->panes(allpanes);
751  for(int i=0, ni = allpanes.size(); i<ni; ++i){
752  MesqPane* mp = new MesqPane(allpanes[i]);
753  mp->invert();
754  if(mp)
755  delete mp;
756  mp = NULL;
757  }
758 }
759 
760 double Rocmop::check_marked_elem_quality(std::vector<std::vector<bool> > &marked_elems,
761  std::vector<COM::Pane*> &allpanes){
762  if(_verb)
763  std::cout << "Entering Rocmop::check_marked_elems" << std::endl;
764 
765  double worst_angle = 0.0;
766  double angles[] = {0.0, 0.0};
767  for(int i=0,ni = allpanes.size(); i<ni; ++i){
768  for(int k =0,nk=allpanes[i]->size_of_real_elements(); k<nk; ++k){
769  if(marked_elems[i][k]){
770  Element_node_enumerator ene(allpanes[i],k+1);
771  Angle_Metric_3 am;
772  am.initialize(ene);
773  am.compute(angles);
774  if(angles[1]>worst_angle)
775  worst_angle = angles[1];
776  }
777  }
778  }
779  return worst_angle;
780 
781  if(_verb > 1)
782  std::cout << "Exiting Rocmop::check_marked_elems" << std::endl;
783 }
784 
785 double Rocmop::check_all_elem_quality(std::vector<const COM::Pane*> &allpanes,
786  bool with_ghosts){
787  if(_verb)
788  std::cout << "Exiting Rocmop::check_all_elem_quality" << std::endl;
789 
790  int rank =0;
791  int ierr = MPI_Comm_rank( _wrk_window->get_communicator(),
792  &rank); assert( ierr == 0);
793  double worst_angle = 0.0;
794  double angles[] = {0.0, 0.0};
795  for(int i=0,ni = allpanes.size(); i<ni; ++i){
796  int nk=allpanes[i]->size_of_real_elements();
797  if(with_ghosts)
798  nk = allpanes[i]->size_of_elements();
799  for(int k =0; k<nk; ++k){
800  Element_node_enumerator ene(allpanes[i],k+1);
801  Angle_Metric_3 am;
802  am.initialize(ene);
803  am.compute(angles);
804  if(angles[1]>worst_angle)
805  worst_angle = angles[1];
806  }
807  }
808  return worst_angle;
809 
810  if(_verb > 1)
811  std::cout << "Exiting Rocmop::check_all_elem_quality" << std::endl;
812 }
813 
814 double Rocmop::check_all_elem_quality(std::vector<COM::Pane*> &allpanes,
815  bool with_ghosts){
816  if(_verb)
817  std::cout << "Entering Rocmop::check_all_elem_quality" << std::endl;
818 
819  int rank =0;
820  int ierr = MPI_Comm_rank( _wrk_window->get_communicator(),
821  &rank); assert( ierr == 0);
822 
823  double worst_angle = 0.0;
824  double angles[] = {0.0, 0.0};
825  for(int i=0,ni = allpanes.size(); i<ni; ++i){
826  int nk=allpanes[i]->size_of_real_elements();
827  if(with_ghosts){
828  nk = allpanes[i]->size_of_elements();
829  }
830  for(int k =0; k<nk; ++k){
831  Element_node_enumerator ene(allpanes[i],k+1);
832  Angle_Metric_3 am;
833  am.initialize(ene);
834  am.compute(angles);
835 
836  if(angles[1]>worst_angle)
837  worst_angle = angles[1];
838  }
839  }
840  return worst_angle;
841 
842  if(_verb > 1)
843  std::cout << "Exiting Rocmop::check_all_elem_quality" << std::endl;
844 }
845 
846 void Rocmop::print_quality(std::string &s){
847 
848  string outstr("angles.txt");
849  ofstream file (outstr.c_str(), std::ios::app);
850  COM_assertion_msg( file, "File failed to open\n");
851 
852  std::vector<Pane*> allpanes;
853  _wrk_window->panes(allpanes);
854 
855  double max_angle = 0.0;
856  double min_angle = 180.0;
857  double angles[] = {0.0, 0.0};
858  for(int i=0,ni = allpanes.size(); i<ni; ++i){
859  for(int k =0,nk=allpanes[i]->size_of_real_elements(); k<nk; ++k){
860  Element_node_enumerator ene(allpanes[i],k+1);
861  Angle_Metric_3 am;
862  am.initialize(ene);
863  am.compute(angles);
864  if(angles[1]>max_angle)
865  max_angle = angles[1];
866  if(angles[0]<min_angle)
867  min_angle = angles[0];
868  }
869  }
870  int rank =0;
871  if(COMMPI_Initialized()){
872  agree_double(max_angle,MPI_MAX);
873  agree_double(min_angle,MPI_MIN);
874  int ierr = MPI_Comm_rank( _wrk_window->get_communicator(),
875  &rank); assert( ierr == 0);
876  }
877  if (rank==0){
878  file << std::left << std::setw(30) << s << std::setw(0)
879  << "(" << min_angle << " , " << max_angle << ")\n";
880  }
881 }
882 
883 void Rocmop::print_mquality(std::string &s,
884  std::vector<std::vector<bool> > &to_check){
885 
886  std::vector<std::vector<bool> > elem_to_check;
887  mark_elems_from_nodes(to_check, elem_to_check);
888 
889  std::vector<Pane*> allpanes;
890  _wrk_window->panes(allpanes);
891 
892  double max_angle = 0.0;
893  double min_angle = 180.0;
894  double angles[] = {0.0, 0.0};
895  int id = -1;
896  for(int i=0,ni = allpanes.size(); i<ni; ++i){
897  for(int k =0,nk = elem_to_check[i].size(); k<nk; ++k){
898  if(elem_to_check[i][k]){
899  Element_node_enumerator ene(allpanes[i],k+1);
900  Angle_Metric_3 am;
901  am.initialize(ene);
902  am.compute(angles);
903  if(angles[1]>max_angle)
904  max_angle = angles[1];
905  if(angles[0]<min_angle){
906  id = k;
907  min_angle = angles[0];
908  }
909  }
910  }
911  }
912  int rank =0;
913  double temp = min_angle;
914  if(COMMPI_Initialized()){
915  agree_double(max_angle,MPI_MAX);
916  agree_double(min_angle,MPI_MIN);
917  int ierr = MPI_Comm_rank( _wrk_window->get_communicator()
918  , &rank);
919  assert( ierr == 0);
920  }
921 
922  if (rank==0){
923  string outstr("angles.txt");
924  ofstream file (outstr.c_str(), std::ios::app);
925  COM_assertion_msg( file, "File failed to open\n");
926 
927  file << std::left << std::setw(30) << s << std::setw(0)
928  << "(" << min_angle << " , " << max_angle << ")";
929 
930  file.close();
931  }
932 
933  if(COMMPI_Initialized())
934  int ierr = MPI_Barrier(_wrk_window->get_communicator());
935 
936  if(min_angle == temp){
937 
938  string outstr("angles.txt");
939  ofstream file (outstr.c_str(), std::ios::app);
940  COM_assertion_msg( file, "File failed to open\n");
941 
942  file << " worst = (" << rank << " , " << id << ")\n";
943  file.close();
944  }
945 
946  if(COMMPI_Initialized())
947  int ierr = MPI_Barrier(_wrk_window->get_communicator());
948 }
949 
950 extern "C" void Rocmop_load_module( const char *mname)
951 { Rocmop::load( mname); }
952 
953 extern "C" void Rocmop_unload_module( const char *mname)
954 { Rocmop::unload( mname); }
955 
956 // Fortran bindings
957 extern "C" void COM_F_FUNC2(rocmop_load_module, ROCMOP_LOAD_MODULE)( const char *mname, long int length)
958 { Rocmop::load( std::string(mname, length)); }
959 
960 extern "C" void COM_F_FUNC2(rocmop_unload_module, ROCMOP_UNLOAD_MODULE)( const char *mname, long int length)
961 { Rocmop::unload( std::string(mname, length)); }
962 
964 
965 
966 
967 
968 
969 
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 set_verb(int verb)
Set the MesqPane verbose level (int, &gt;= 0)
Definition: MesqPane.h:144
Utility for constructing pane connectivities in parallel.
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 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
virtual void run_instructions(MeshSet &ms, MsqError &err)
run_instructions runs the wrapper on the given MeshSet.
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
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
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
#define MSQ_CHKERR(err)
Mesquite&#39;s Error Checking macro.
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
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
#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
MesqPane.h.
j indices j
Definition: Indexing.h:6
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 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
int COMMPI_Initialized()
Definition: commpi.h:168
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