Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
smooth_boeing.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 #include <stdio.h>
24 #include <iostream>
25 #include <iomanip>
26 #include <vector>
27 #include <assert.h>
28 #include <bitset>
29 #include "../../Roccom/External/cgnslib_2.4/cgnslib.h"
30 #include "roccom.h"
31 #include "mapbasic.h"
32 #include "Rocblas.h"
33 #include "Rocmop_1_1.h"
34 #include "mopbasic.h"
35 
36 using namespace std;
37 
41 
42 int main(int argc, char*argv[])
43 {
44 
45  MPI_Init( &argc, &argv);
46 
47  if (argc < 3){
48  cout << "Usage: " << argv[0]
49  << " <fname><niter>" << endl;
50  exit(-1);
51  }
52 
53  COM_init( &argc, &argv);
54 
57 
58  // Get function handles
59  int OUT_write = COM_get_function_handle( "OUT.write_attribute");
60  int MOP_sb = COM_get_function_handle( "MOP.smooth_boeing");
61  int MOP_set = COM_get_function_handle( "MOP.set_value");
62  int MOP_angles= COM_get_function_handle( "MOP.obtain_extremal_dihedrals");
63 
64  string fname(argv[1]);
65  int niter = atoi(argv[2]);
66 
67  const int nameSize = 33;
68  int file_hdl;
69  int nbases;
70  int nzones;
71  int bCellDim;
72  int bPhysDim;
73  char bName[33];
74  char zName[33];
75  int sizes[3];
76  SimulationType_t sType;
77 
78  const char* _3DUnstructInfo[3] =
79  {"NVertex", "NCell3D", "NBoundVertex"};
80 
81  std::cout << "Opening file: " << fname.c_str() << "\n";
82 
83  // open CGNS file
84  if(cg_open(fname.c_str(), MODE_MODIFY, &file_hdl))
85  cg_error_exit();
86 
87  // read the number of bases
88  if(cg_nbases(file_hdl,&nbases))
89  cg_error_exit();
90 
91  if(nbases != 1){
92  cout << "Error: .cgns files with multiple bases not supported.\n";
93  assert(0);
94  }
95 
96  // get info about each base
97  std::cout << "File opened successfully.\n";
98 
99  int i =1;
100 
101  if(cg_base_read(file_hdl, i, bName,&bCellDim, &bPhysDim))
102  cg_error_exit();
103 
104  std::cout << "Checking mesh format.\n";
105  if(bCellDim != 3 ||
106  bPhysDim != 3){
107  cout << "Error: Only volume meshes are supported by this utility.\n";
108  exit(-1);
109  }
110 
111  // Examine zone data:
112  if(cg_nzones(file_hdl, i, &nzones))
113  cg_error_exit();
114 
115  ZoneType_t zType;
116 
117  if( nzones != 1 ){
118  cout << "Error: .cgns files with multiple zones not supported by this utility.\n";
119  assert(0);
120  }
121 
122  int j = 1;
123 
124  if(cg_zone_type(file_hdl, i, j, &zType))
125  cg_error_exit();
126 
127  if(zType != Unstructured){
128  cout << "Error: only structured meshes supported by this utility.\n";
129  assert(0);
130  }
131 
132  if(cg_zone_read(file_hdl, i, j, zName, &sizes[0]))
133  cg_error_exit();
134 
135  for(int k = 0; k < 3; ++k)
136  cout << _3DUnstructInfo[k] << " = " << sizes[k] << "\n";
137 
138  if(zType == Structured){
139  cout << "Error: this utility does not supoort structured meshes.\n";
140  exit(-1);
141  }
142 
143  // Check for Grids associated w/ this node,zone:
144  int nGrids;
145  if(cg_ngrids(file_hdl, i, j, &nGrids))
146  cg_error_exit();
147 
148  if( nGrids != 1 ){
149  cout << "Erorr: this utility only supports files with 1 grid\n";
150  exit(-1);
151  }
152 
153  int ncoords = 0;
154  if(cg_ncoords(file_hdl,i,j,&ncoords))
155  cg_error_exit();
156 
157  if(ncoords != 3){
158  cout << "Error: this utility only supports meshes with 3 coordinate components\n";
159  exit(-1);
160  }
161 
162  int nnodes = sizes[0];
163  std::vector<double> coord_data(3*nnodes);
164 
165  for(int k=1; k<=ncoords; ++k){
166 
167  DataType_t dataType;
168  char coordName[nameSize];
169  if(cg_coord_info(file_hdl, i, j, k, &dataType, &coordName[0]))
170  cg_error_exit();
171 
172  if(dataType != RealDouble){
173  std::cout << "Error: this utility only supports mesh coordinates of CGNS type RealDouble\n";
174  exit(-1);
175  }
176 
177  int ranges[2] = {1,nnodes};
178  if(cg_coord_read(file_hdl,i,j,&coordName[0],dataType,&ranges[0],
179  &ranges[1],&coord_data[(k-1)*nnodes]))
180  cg_error_exit();
181  }
182 
183  // Check for Conn tables associated w/ this node,zone:
184  int nConns;
185  if(cg_nsections(file_hdl, i, j, &nConns))
186  cg_error_exit();
187 
188  char cName[nameSize];
189  ElementType_t eType;
190  int rmin_elems, rmax_elems, nbnrdy, parent_flag;
191  int nodes_pe = 0; // nodes per element
192 
193  // Ok, we've spit out enough info, lets actually go smooth
194  for(int k=1; k<nConns; ++k){
195 
196  if(cg_section_read(file_hdl, i, j, k, &cName[0], &eType,
197  &rmin_elems, &rmax_elems, &nbnrdy, &parent_flag))
198  cg_error_exit();
199 
200  /*
201  The .cgns documentation says that parent_data "contains
202  information on the cell(s) and cell faces(s) sharing the element"
203 
204  There appears to be no way to determine the size of the parent_data
205  a priori, and I see no cg_ call to determine this information.
206  Since the Boeing meshes I've examined so far do not contain this
207  piece of information, I've decided not to write the utility to support
208  its presence.
209  */
210  if(parent_flag){
211  cout << "Error: the parent flag is set, and this utility does not "
212  << "support meshes with parent data.\n";
213  exit(-1);
214  }
215 
216  // For the time being, we're only optimizing tet elements
217  if(eType == TETRA_4){
218 
219  /*
220  We will create node index mappings in both directions:
221  .cgns -> temp. Roccom window,
222  temp.Roccom window -> .cgns
223  This is overkill, but doesn't change the big O order of the
224  program. I've chosen this method because it is very clear and
225  should make future maintenance very easy.
226  */
227 
228  // Determine the number of elements in the mesh
229  int nElems;
230  int nodes_pe = 4;
231  if(cg_ElementDataSize(file_hdl, i, j, k, &nElems))
232  cg_error_exit();
233  nElems /= nodes_pe;
234 
235  // Allocate buffers for the tetrahedral connectivity tables for
236  // both the .cgns file and the temp Roccom window
237  std::vector<int> conn_data(nElems*nodes_pe,-1);
238  std::vector<int> temp_conn(nElems*nodes_pe,-2);
239  int parent_data[1];
240 
241  // Allocate a buffer for the mapping the ids in the .cgns file
242  // to those in the Roccom window we are going to create
243  std::vector<int> cgns_to_roccom(nnodes,-1);
244 
245  // Read in the connectivity table to our buffer
246  if(cg_elements_read(file_hdl, i, j, k, &conn_data[0], &parent_data[0]))
247  cg_error_exit();
248 
249  cout << "Found a tetrahedral zone with " << nElems << " elements\n";
250  // Make a pass over the connectivity table
251  // 1) Determine the number of nodes used by tet elements.
252  // 2) Assign new ids to these nodes
253  // 3) Fill in the connectivity table for the Roccom window
254  int used_nodes = 0;
255  for(int ii=0; ii< nElems; ++ii){
256  for(int jj=0; jj< nodes_pe; ++jj){
257  int old_node_ind = conn_data[ii*nodes_pe + jj]-1;
258  if(cgns_to_roccom[old_node_ind] == -1)
259  cgns_to_roccom[old_node_ind] = used_nodes++;
260  temp_conn[ii*nodes_pe + jj] = cgns_to_roccom[old_node_ind]+1;
261  }
262  }
263 
264  // We're finished w/ the connectivity data now, so minimize its footprint
265  std::vector<int>().swap(conn_data);
266 
267  // Now that we know how many nodes will be in the Roccom window,
268  // allocate buffers for its nodal coordinates and for the
269  // mapping of node ids from the Roccom window to the .cgns file
270  std::vector<double> temp_coords(used_nodes*3,-3);
271  std::vector<int> roccom_to_cgns(used_nodes,-4);
272 
273  // Pass over the .cgns coordinate array
274  // 1) Fill in the coordinate array for the Roccom window
275  // 2) Fill in the 2nd node id mapping
276  for(int ii =0; ii<nnodes; ++ii){
277  if(cgns_to_roccom[ii] != -1){
278  int node_ind = cgns_to_roccom[ii];
279  temp_coords[node_ind*3] = coord_data[ii];
280  temp_coords[node_ind*3+1] = coord_data[ii+nnodes];
281  temp_coords[node_ind*3+2] = coord_data[ii+2*nnodes];
282  }
283  }
284 
285  // close CGNS file temporarily to decrease mem footprint
286  if(cg_close(file_hdl))
287  cg_error_exit();
288 
289  // Create a new window
290  cout << "Initializing smoothing data structures\n";
291  COM_new_window("unstr_temp");
292 
293  // Register nodal coordinates and connectivity table
294  COM_set_size("unstr_temp.nc", 1, used_nodes);
295  COM_set_array("unstr_temp.nc",1, &temp_coords[0],3);
296  COM_set_size("unstr_temp.:T4:", 1, nElems);
297  COM_set_array("unstr_temp.:T4:",1, &temp_conn[0],4);
298 
299  COM_window_init_done("unstr_temp");
300 
301  // Obtain attribute handles
302  int HDL_mesh = COM_get_attribute_handle("unstr_temp.mesh");
303 
304  #if 0
305 
306  // Write out the mesh in its initial configuration
307  cout << "Writing initial mesh configuration\n";
308  COM_call_function(OUT_write, "unstr_temp", &HDL_mesh,
309  "unstr_temp", "001");
310 
311  #endif
312 
313  double min_angle = 190, max_angle=0;
314  COM_call_function(MOP_angles, &HDL_mesh, &min_angle, &max_angle);
315  cout << "Initial dihedral angle range = ( " << min_angle << " , " << max_angle << " )\n";
316  cout << "Beginning mesh optimizaton\n";
317 
318  cout << setiosflags(std::ios::left);
319  cout << std::setw(15) << "iteration" << std::setw(20) << "min dihedral "
320  << std::setw(20) << "max dihedral " << endl;
321  cout << std::setw(55) << std::setfill('-') << "" << endl;
322  cout << std::setfill(' ');
323 
324  // Use a conjugate gradient solver to decrease the required
325  // memory footprint
326  int wrapper_cg = 1;
327  COM_call_function(MOP_set, "wrapper", &wrapper_cg);
328 
329  for(int ii =0; ii< niter; ++ii){
330 
331  int one = 1;
332  COM_call_function( MOP_sb, &HDL_mesh, &one);
333  COM_call_function(MOP_angles, &HDL_mesh, &min_angle, &max_angle);
334 
335  cout << std::setw(15) << ii+1 << std::setw(20) << min_angle
336  << std::setw(20) << max_angle << "\n";
337  }
338 
339 
340  #if 0
341  // Writing out the smoothed mesh configuration
342  cout << "Writing out smoothed configuration\n";
343  COM_call_function(OUT_write, "unstr_temp_smoothed", &HDL_mesh,
344  "unstr_temp", "001");
345  #endif
346 
347  // Pass over the .cgns coordinate array
348  // 1) Fill in the coordinate array for the Roccom window
349  // 2) Fill in the 2nd node id mapping
350  for(int ii =0; ii<nnodes; ++ii){
351  if(cgns_to_roccom[ii] != -1){
352  int node_ind = cgns_to_roccom[ii];
353  coord_data[ii] = temp_coords[node_ind*3];
354  coord_data[ii+nnodes] = temp_coords[node_ind*3+1];
355  coord_data[ii+2*nnodes] = temp_coords[node_ind*3+2];
356  }
357  }
358 
359  // reopen CGNS file
360  if(cg_open(fname.c_str(), MODE_MODIFY, &file_hdl))
361  cg_error_exit();
362 
363  cout << "Writing updated coordinates to .cgns file\n";
364  for(int ii= 1; ii<=3; ++ii){
365  char coordName[33];
366  int coord_ind;
367  DataType_t dataType;
368 
369  if(cg_coord_info(file_hdl, i, j, ii, &dataType, &coordName[0]))
370  cg_error_exit();
371 
372  if(cg_coord_write(file_hdl,i,j,RealDouble,coordName,
373  &coord_data[(ii-1)*nnodes], &coord_ind))
374  cg_error_exit();
375 
376  assert(coord_ind == ii);
377  }
378 
379  } // if(eType == TETRA_4)
380  }
381 
382  // close CGNS file
383  if(cg_close(file_hdl))
384  cg_error_exit();
385 }
386 
387 
388 
389 
390 
391 
void swap(int &a, int &b)
Definition: buildface.cpp:88
j indices k indices k
Definition: Indexing.h:6
void COM_set_size(const char *wa_str, int pane_id, int size, int ng=0)
Set sizes of for a specific attribute.
Definition: roccom_c++.h:136
This file contains the prototypes for Roccom API.
A Roccom mesh optimization module.
Definition: Rocmop.h:41
int COM_get_attribute_handle(const char *waname)
Definition: roccom_c++.h:412
Definition: Rocout.h:81
blockLoc i
Definition: read.cpp:79
void COM_window_init_done(const char *w_str, int pane_changed=true)
Definition: roccom_c++.h:102
void COM_new_window(const char *wname, MPI_Comm c=MPI_COMM_NULL)
Definition: roccom_c++.h:86
void COM_call_function(const int wf, int argc,...)
Definition: roccom_c.C:48
Definition for Rocblas API.
void COM_set_array(const char *wa_str, int pane_id, void *addr, int strd=0, int cap=0)
Associates an array with an attribute for a specific pane.
Definition: roccom_c++.h:156
int main(int argc, char *argv[])
Definition: blastest.C:94
j indices j
Definition: Indexing.h:6
void COM_init(int *argc, char ***argv)
Definition: roccom_c++.h:57
#define COM_LOAD_MODULE_STATIC_DYNAMIC(moduleName, windowString)
Definition: roccom_basic.h:111
int COM_get_function_handle(const char *wfname)
Definition: roccom_c++.h:428
#define COM_EXTERN_MODULE(moduleName)
Definition: roccom_basic.h:116